Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

kino_av_pipe.cc

Go to the documentation of this file.
00001 /*
00002 * kino_av_pipe.cc -- AV Export Pipe Implementations and Factories
00003 * Copyright (C) 2002 Charles Yates <charles.yates@pandora.be>
00004 * Copyright (C) 2002-2007 Dan Dennedy <dan@dennedy.org>
00005 *
00006 * This program is free software; you can redistribute it and/or modify
00007 * it under the terms of the GNU General Public License as published by
00008 * the Free Software Foundation; either version 2 of the License, or
00009 * (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU General Public License
00017 * along with this program; if not, write to the Free Software Foundation,
00018 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024 
00025 #include <gtk/gtk.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <unistd.h>
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #include <fcntl.h>
00032 
00033 #include "error.h"
00034 #include "kino_av_pipe.h"
00035 #include "endian_types.h"
00036 #include "rwpipe.h"
00037 #include "frame.h"
00038 #include "stringutils.h"
00039 
00040 /*
00041  * C Functions for generating a WAV output. Should be rewritten in C++ 
00042  * rather than just wrapped...
00043  */
00044 
00045 typedef struct
00046 {
00047     char        riff[ 4 ];
00048     int32_le_t  length;
00049     char        type[ 4 ];
00050 }
00051 RIFFChunkType, *RIFFChunk;
00052 
00053 typedef struct
00054 {
00055     char        format[ 4 ];
00056     int32_le_t  length;
00057     int16_le_t  filler;
00058     int16_le_t  channels;
00059     int32_le_t  rate;
00060     int32_le_t  bytespersecond;
00061     int16_le_t  bytespersample;
00062     int16_le_t  bitspersample;
00063 }
00064 FORMATChunkType, *FORMATChunk;
00065 
00066 typedef struct
00067 {
00068     char        data[ 4 ];
00069     int32_le_t  length;
00070 }
00071 DATAChunkType, *DATAChunk;
00072 
00073 typedef struct
00074 {
00075     FILE *file;
00076     RIFFChunk riff;
00077     FORMATChunk format;
00078     DATAChunk data;
00079     int isapipe;
00080 }
00081 WAVStructType, *WAVStruct;
00082 
00083 static RIFFChunk RIFFChunk_Init( )
00084 {
00085     RIFFChunk chunk = ( RIFFChunk ) malloc( sizeof( RIFFChunkType ) );
00086     memcpy( chunk->riff, "RIFF", 4 );
00087     chunk->length = 4 + sizeof( FORMATChunkType ) + sizeof( DATAChunkType );
00088     memcpy( chunk->type, "WAVE", 4 );
00089     return chunk;
00090 }
00091 
00092 static FORMATChunk FORMATChunk_Init( short channels, int rate, int bytespersample )
00093 {
00094     FORMATChunk format = ( FORMATChunk ) malloc( sizeof( FORMATChunkType ) );
00095     memset( format, 0, sizeof( FORMATChunkType ) );
00096     memcpy( format->format, "fmt ", 4 );
00097     format->length = 0x10;
00098     format->filler = 0x01;
00099     format->channels = channels;
00100     format->rate = rate;
00101     format->bytespersecond = rate * channels * bytespersample;
00102     format->bytespersample = bytespersample * channels;
00103     format->bitspersample = bytespersample * 8;
00104     return format;
00105 }
00106 
00107 static DATAChunk DATAChunk_Init( )
00108 {
00109     DATAChunk data = ( DATAChunk ) malloc( sizeof( DATAChunkType ) );
00110     memset( data, 0, sizeof( DATAChunkType ) );
00111     memcpy( data->data, "data", 4 );
00112     return data;
00113 }
00114 
00115 static void WAVStruct_WriteHeader( WAVStruct wav )
00116 {
00117     if ( wav->isapipe )
00118     {
00119         wav->riff->length |= 0x7ffff000;
00120         wav->data->length |= 0x7ffff000;
00121     }
00122     fwrite( wav->riff, sizeof( RIFFChunkType ), 1, wav->file );
00123     fwrite( wav->format, sizeof( FORMATChunkType ), 1, wav->file );
00124     fwrite( wav->data, sizeof( DATAChunkType ), 1, wav->file );
00125     fflush( wav->file );
00126 }
00127 
00128 static WAVStruct WAVStruct_Init( char *output, short channels, int frequency, short bytespersample )
00129 {
00130     WAVStruct wav = ( WAVStruct ) malloc( sizeof( WAVStructType ) );
00131     wav->riff = RIFFChunk_Init();
00132     wav->format = FORMATChunk_Init( channels, frequency, bytespersample );
00133     wav->data = DATAChunk_Init();
00134     wav->isapipe = output[ 0 ] == '|';
00135     if ( wav->isapipe )
00136         wav->file = popen( output + 1, "w" );
00137     else
00138         wav->file = fopen( output, "w" );
00139     WAVStruct_WriteHeader( wav );
00140     return wav;
00141 }
00142 
00143 static int WAVStruct_WriteData( WAVStruct wav, void *data, int length )
00144 {
00145     wav->riff->length += length;
00146     wav->data->length += length;
00147     int written = fwrite( data, length, 1, wav->file );
00148     fflush( wav->file );
00149     return written == 1;
00150 }
00151 
00152 static void WAVStruct_Close( WAVStruct wav )
00153 {
00154     if ( !wav->isapipe )
00155     {
00156         rewind( wav->file );
00157         WAVStruct_WriteHeader( wav );
00158         fclose( wav->file );
00159     }
00160     else
00161     {
00162         pclose( wav->file );
00163     }
00164     free( wav->riff );
00165     free( wav->format );
00166     free( wav->data );
00167     free( wav );
00168 }
00169 
00170 class WAVImport : public KinoAudioInput
00171 {
00172 private:
00173     WAVStructType wav;
00174     long start;
00175     int channels;
00176     int frequency;
00177     int bytespersample;
00178     long length;
00179 public:
00180     WAVImport();
00181     virtual ~WAVImport( );
00182     bool Open( char *input );
00183     int GetChannels( )
00184     {
00185         return channels;
00186     }
00187     int GetFrequency( )
00188     {
00189         return frequency;
00190     }
00191     int GetBytesPerSample( )
00192     {
00193         return bytespersample;
00194     }
00195     long GetNumberOfSamples( )
00196     {
00197         return length / channels / bytespersample;
00198     }
00199     bool Seek( off_t offset );
00200     bool Get( int16_t *data, int length );
00201     bool Close( );
00202 };
00203 
00204 WAVImport::WAVImport()
00205 {
00206     wav.file = NULL;
00207 }
00208 
00209 WAVImport::~WAVImport()
00210 {
00211     Close( );
00212 }
00213 
00214 bool WAVImport::Open( char *input )
00215 {
00216     bool iswav = false;
00217 
00218     wav.file = fopen( input, "r" );
00219 
00220     if ( wav.file != NULL )
00221     {
00222         wav.riff = ( RIFFChunk ) malloc( sizeof( RIFFChunkType ) );
00223         wav.format = ( FORMATChunk ) malloc( sizeof( FORMATChunkType ) );
00224         wav.data = ( DATAChunk ) malloc( sizeof( DATAChunkType ) );
00225 
00226         // Bad... temporary code
00227         fread( wav.riff, sizeof( RIFFChunkType ), 1, wav.file );
00228         fread( wav.format, sizeof( FORMATChunkType ), 1, wav.file );
00229         int remainder = wav.format->length - sizeof( FORMATChunkType );
00230         if ( remainder > 0 )
00231             fseek( wav.file, remainder, SEEK_CUR );
00232         fread( wav.data, sizeof( DATAChunkType ), 1, wav.file );
00233         if ( strncasecmp( wav.data->data, "JUNK", 4 ) == 0 )
00234         {
00235             fseek( wav.file, wav.data->length, SEEK_CUR );
00236             fread( wav.data, sizeof( DATAChunkType ), 1, wav.file );
00237         }
00238 
00239         if ( !strncmp( wav.riff->riff, "RIFF", 4 ) && !strncmp( wav.riff->type, "WAVE", 4 ) )
00240         {
00241             iswav = true;
00242             channels = wav.format->channels;
00243             frequency = wav.format->rate;
00244             bytespersample = wav.format->bytespersample / channels;
00245             start = ftell( wav.file );
00246             length = wav.data->length;
00247         }
00248     }
00249 
00250     return iswav;
00251 }
00252 
00253 bool WAVImport::Seek( off_t offset )
00254 {
00255     return fseek( wav.file, offset + start, SEEK_SET ) == 0;
00256 }
00257 
00258 bool WAVImport::Get( int16_t *data, int length )
00259 {
00260     return fread( data, 1, length, wav.file ) == ( unsigned ) length;
00261 }
00262 
00263 bool WAVImport::Close( )
00264 {
00265     if ( wav.file != NULL )
00266     {
00267         fclose( wav.file );
00268         free( wav.riff );
00269         free( wav.format );
00270         free( wav.data );
00271         wav.file = NULL;
00272     }
00273     return true;
00274 }
00275 
00276 
00277 class PipeImport : public KinoAudioInput
00278 {
00279 private:
00280     RWPipe m_pipe;
00281     string m_file;
00282     int16_t m_buffer[ 4 * DV_AUDIO_MAX_SAMPLES ];
00283     char *m_command;
00284 public:
00285     PipeImport()
00286         : m_command( 0 )
00287     {
00288     }
00289     virtual ~PipeImport( )
00290     {
00291         m_pipe.stop();
00292         delete m_command;
00293     }
00294     bool Open( char *input )
00295     {
00296         bool result = false;
00297         char *kinoHome = getenv("KINO_HOME");
00298         string homeFile, script;
00299         int testHomeFile = 0;
00300 
00301         // Allow a script in home directory to override
00302         if ( kinoHome )
00303             homeFile = string( kinoHome ) + string( "/import/audio.sh" );
00304         else
00305             homeFile = string( getenv( "HOME" ) ) + string( "/kino/import/audio.sh" );
00306         testHomeFile = open( homeFile.c_str(), O_RDONLY );
00307         if ( testHomeFile > -1 )
00308         {
00309             close( testHomeFile );
00310             script = homeFile;
00311         }
00312         else
00313         {
00314             script = string( DATADIR "/kino/scripts/import/audio.sh" );
00315         }
00316 
00317         delete m_command;
00318         string inputFilename = StringUtils::replaceAll( input, "\"", "\\\"" );
00319         m_command = g_strdup_printf( "%s \"%s\"", script.c_str(), inputFilename.c_str() );
00320         m_pipe.stop();
00321         if ( m_pipe.run( m_command ) )
00322         {
00323             char temp[ 10 ];
00324             result = ( m_pipe.readData( temp, 10 ) == 10 );
00325             m_pipe.stop();
00326             if ( result )
00327                 return m_pipe.run( m_command );
00328         }
00329         return result;
00330     }
00331     int GetChannels( )
00332     {
00333         return 2;
00334     }
00335     int GetFrequency( )
00336     {
00337         return 44100;
00338     }
00339     int GetBytesPerSample( )
00340     {
00341         return 2;
00342     }
00343     long GetNumberOfSamples( )
00344     {
00345         return -1;
00346     }
00347     bool Seek( off_t offset )
00348     {
00349         return false;
00350     }
00351     bool Get( int16_t *data, int length )
00352     {
00353         return ( m_pipe.readData( data, length ) == length );
00354     }
00355     bool Close( )
00356     {
00357         m_pipe.stop();
00358         return true;
00359     }
00360 };
00361 
00362 
00363 KinoAudioInput *KinoAudioInputFactory::CreateAudioInput( char *input )
00364 {
00365     const std::string filename( input );
00366     const std::string suffix( filename.begin() + filename.rfind( "." ), filename.end() );
00367     KinoAudioInput* filter;
00368 
00369     if ( suffix == ".wav" )
00370         filter = new WAVImport();
00371     else
00372         filter = new PipeImport();
00373     if ( filter->Open( input ) )
00374         return filter;
00375     else
00376         delete filter;
00377     return 0;
00378 }
00379 
00383 class WAVExport : public KinoAudioPipe
00384 {
00385 private:
00386     WAVStruct wav;
00387 public:
00388     bool OpenAudio( char *output, int channels, int frequency, int bytespersample );
00389     bool OutputAudioFrame( int16_t *data, int length );
00390     bool CloseAudio( );
00391 };
00392 
00396 bool WAVExport::OpenAudio( char *output, int channels, int frequency, int bytespersample )
00397 {
00398     sigpipe_clear();
00399     wav = WAVStruct_Init( output, channels, frequency, bytespersample );
00400     return wav != NULL && sigpipe_get() == 0;
00401 }
00402 
00406 bool WAVExport::OutputAudioFrame( int16_t *data, int length )
00407 {
00408     sigpipe_clear();
00409     return WAVStruct_WriteData( wav, data, length ) == 1 && sigpipe_get() == 0;
00410 }
00411 
00415 bool WAVExport::CloseAudio( )
00416 {
00417     sigpipe_clear();
00418     WAVStruct_Close( wav );
00419     return sigpipe_get() == 0;
00420 }
00421 
00425 class PCMExport : public KinoAudioPipe
00426 {
00427 private:
00428     FILE *out;
00429     int isapipe;
00430 public:
00431     bool OpenAudio( char *output, int channels, int frequency, int bytespersample );
00432     bool OutputAudioFrame( int16_t *data, int length );
00433     bool CloseAudio( );
00434 };
00435 
00439 bool PCMExport::OpenAudio( char *output, int channels, int frequency, int bytespersample )
00440 {
00441     if ( output[ 0 ] == '|' )
00442     {
00443         out = popen( output + 1, "w" );
00444         isapipe = 1;
00445     }
00446     else
00447     {
00448         out = fopen( output, "w" );
00449         isapipe = 0;
00450     }
00451 
00452     return out != NULL && sigpipe_get() == 0;
00453 }
00454 
00458 bool PCMExport::OutputAudioFrame( int16_t *data, int length )
00459 {
00460     sigpipe_clear();
00461     return fwrite( data, length, 1, out ) == 1 && sigpipe_get() == 0;
00462 }
00463 
00467 bool PCMExport::CloseAudio( )
00468 {
00469     sigpipe_clear();
00470     if ( isapipe )
00471         pclose( out );
00472     else
00473         fclose( out );
00474     return sigpipe_get() == 0;
00475 }
00476 
00480 KinoAudioPipe *KinoAudioFactory::CreateAudioPipe( kino_audio_pipe type )
00481 {
00482     switch ( type )
00483     {
00484     case PIPE_AUDIO_WAV:
00485         return new WAVExport();
00486     case PIPE_AUDIO_PCM:
00487         return new PCMExport();
00488     default:
00489         return NULL;
00490     }
00491 }
00492 
00497 static void frame_YUV422_to_YUV420P( uint8_t **output, uint8_t *input, int width, int height )
00498 {
00499     int i, j, w2;
00500     uint8_t *y, *cb, *cr;
00501 
00502     w2 = width / 2;
00503     y = output[ 0 ];
00504     cb = output[ 1 ];
00505     cr = output[ 2 ];
00506 
00507     for ( i = 0; i < height; i += 2 )
00508     {
00509         /* process two scanlines (one from each field, interleaved) */
00510         for ( j = 0; j < w2; j++ )
00511         {
00512             /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
00513             *( y++ ) = *( input++ );
00514             *( cb++ ) = *( input++ );
00515             *( y++ ) = *( input++ );
00516             *( cr++ ) = *( input++ );
00517         }
00518         /* process next two scanlines (one from each field, interleaved) */
00519         for ( j = 0; j < w2; j++ )
00520         {
00521             /* skip every second line for U and V */
00522             *( y++ ) = *( input++ );
00523             input++;
00524             *( y++ ) = *( input++ );
00525             input++;
00526         }
00527     }
00528 }
00529 #define SCALEBITS 8
00530 #define ONE_HALF  (1 << (SCALEBITS - 1))
00531 #define FIX(x)      ((int) ((x) * (1L<<SCALEBITS) + 0.5))
00532 
00533 static void frame_RGB24_to_YUV420P( uint8_t **output, uint8_t *input, int width, int height )
00534 {
00535     int wrap, wrap3, x, y;
00536     int r, g, b, r1, g1, b1;
00537     uint8_t *p;
00538 
00539     uint8_t *lum = output[ 0 ];
00540     uint8_t *cb = output[ 1 ];
00541     uint8_t *cr = output[ 2 ];
00542 
00543     wrap = width;
00544     wrap3 = width * 3;
00545     //wrap3 = 0;
00546     p = input;
00547     for ( y = 0;y < height;y += 2 )
00548     {
00549         for ( x = 0;x < width;x += 2 )
00550         {
00551             r = p[ 0 ];
00552             g = p[ 1 ];
00553             b = p[ 2 ];
00554             r1 = r;
00555             g1 = g;
00556             b1 = b;
00557             lum[ width ] = lum[ 0 ] = ( FIX( 0.29900 ) * r + FIX( 0.58700 ) * g +
00558                                         FIX( 0.11400 ) * b + ONE_HALF ) >> SCALEBITS;
00559             r = p[ 3 ];
00560             g = p[ 4 ];
00561             b = p[ 5 ];
00562             r1 += r;
00563             g1 += g;
00564             b1 += b;
00565             lum[ width + 1 ] = lum[ 1 ] = ( FIX( 0.29900 ) * r + FIX( 0.58700 ) * g +
00566                                             FIX( 0.11400 ) * b + ONE_HALF ) >> SCALEBITS;
00567             lum += wrap;
00568 
00569             cb[ 0 ] = ( ( - FIX( 0.16874 ) * r1 - FIX( 0.33126 ) * g1 +
00570                           FIX( 0.50000 ) * b1 + 4 * ONE_HALF - 1 ) >> ( SCALEBITS + 1 ) ) + 128;
00571             cr[ 0 ] = ( ( FIX( 0.50000 ) * r1 - FIX( 0.41869 ) * g1 -
00572                           FIX( 0.08131 ) * b1 + 4 * ONE_HALF - 1 ) >> ( SCALEBITS + 1 ) ) + 128;
00573 
00574             cb++;
00575             cr++;
00576             p += 6;
00577             lum += -wrap + 2;
00578         }
00579         p += wrap3;
00580         lum += wrap;
00581     }
00582 }
00583 
00584 
00588 class KinoMJPEGVideoPipe : public KinoVideoPipe
00589 {
00590 protected:
00591     FILE *output;
00592     int width;
00593     int height;
00594     int pitches[ 3 ];
00595     uint8_t *frame[ 3 ];
00596 
00597 public:
00598     bool OpenVideoPipe( char *pipe, int width, int height, bool interlaced = true );
00599     bool OutputVideoFrame( uint8_t *frame, int size );
00600     bool CloseVideo( );
00601 };
00602 
00606 bool KinoMJPEGVideoPipe::OpenVideoPipe( char *pipe, int width, int height, bool interlaced )
00607 {
00608     sigpipe_clear();
00609     output = popen( pipe, "w" );
00610 
00611     this->width = width;
00612     this->height = height;
00613 
00614     pitches[ 0 ] = width * 2;
00615     pitches[ 1 ] = 0;
00616     pitches[ 2 ] = 0;
00617 
00618     frame[ 0 ] = new uint8_t[ width * height ];
00619     frame[ 1 ] = new uint8_t[ width * height / 4 ];
00620     frame[ 2 ] = new uint8_t[ width * height / 4 ];
00621 
00622     int written = 0;
00623     if ( output != NULL )
00624         written = fprintf( output, "YUV4MPEG2 W%d H%d F%s %s\n", width, height, 
00625             height == 576 ? "25:1 A118:81" : "30000:1001 A40:33", interlaced ? "Ib" : "Ip" );
00626 
00627     return written != 0 && sigpipe_get() == 0;
00628 }
00629 
00634 bool KinoMJPEGVideoPipe::OutputVideoFrame( uint8_t *pixels, int size )
00635 {
00636     sigpipe_clear();
00637     fprintf( output, "FRAME\n" );
00638     frame_YUV422_to_YUV420P( frame, pixels, width, height );
00639     fwrite( frame[ 0 ], width * height, 1, output );
00640     fwrite( frame[ 1 ], width * height / 4, 1, output );
00641     fwrite( frame[ 2 ], width * height / 4, 1, output );
00642     return sigpipe_get() == 0;
00643 }
00644 
00648 bool KinoMJPEGVideoPipe::CloseVideo( )
00649 {
00650     sigpipe_clear();
00651     pclose( output );
00652     delete[] frame[ 0 ];
00653     delete[] frame[ 1 ];
00654     delete[] frame[ 2 ];
00655     return sigpipe_get() == 0;
00656 }
00657 
00658 class KinoDeinterlacedMJPEGVideoPipe : public KinoMJPEGVideoPipe
00659 {
00660 public:
00661     bool OutputVideoFrame( uint8_t *frame, int size );
00662 };
00663 
00668 bool KinoDeinterlacedMJPEGVideoPipe::OutputVideoFrame( uint8_t *pixels, int size )
00669 {
00670     sigpipe_clear();
00671     fprintf( output, "FRAME\n" );
00672     frame_RGB24_to_YUV420P( frame, pixels, width, height );
00673     fwrite( frame[ 0 ], width * height, 1, output );
00674     fwrite( frame[ 1 ], width * height / 4, 1, output );
00675     fwrite( frame[ 2 ], width * height / 4, 1, output );
00676     return sigpipe_get() == 0;
00677 }
00678 
00679 
00683 class DvEncoderVideoPipeYUV : public KinoVideoPipe
00684 {
00685 private:
00686     int width;
00687     int height;
00688     int m_pid, m_writer;
00689     GError *m_error;
00690 
00691 public:
00692     bool OpenVideoPipe( char *pipe, int width, int height, bool interlaced = true );
00693     bool OutputVideoFrame( uint8_t *frame, int size );
00694     bool CloseVideo( );
00695 };
00696 
00700 bool DvEncoderVideoPipeYUV::OpenVideoPipe( char *pipe, int width, int height, bool interlaced )
00701 {
00702     sigpipe_clear();
00703     char * args[ 4 ];
00704 
00705     args[ 0 ] = "/bin/sh";
00706     args[ 1 ] = "-c";
00707     args[ 2 ] = ( char * )pipe;
00708     args[ 3 ] = NULL;
00709 
00710     g_spawn_async_with_pipes( ".", args, NULL, G_SPAWN_LEAVE_DESCRIPTORS_OPEN, NULL, NULL, &m_pid, &m_writer, NULL, NULL, &m_error );
00711 
00712     this->width = width;
00713     this->height = height;
00714     char output[ 256 ];
00715     sprintf( output, "YUV4MPEG2 W%d H%d F%s %s XYSCSS=422\n", width, height,
00716             height == 576 ? "25:1 A118:81" : "30000:1001 A40:33", interlaced ? "Ib" : "Ip" );
00717     write( m_writer, output, strlen( output ) );
00718     return m_writer != -1 && sigpipe_get() == 0;
00719 }
00720 
00724 bool DvEncoderVideoPipeYUV::OutputVideoFrame( uint8_t *frame, int size )
00725 {
00726     sigpipe_clear();
00727     char output[ 256 ];
00728     sprintf( output, "FRAME\n" );
00729     write( m_writer, output, strlen( output ) );
00730     write( m_writer, frame, size );
00731     return sigpipe_get() == 0;
00732 }
00733 
00737 bool DvEncoderVideoPipeYUV::CloseVideo( )
00738 {
00739     sigpipe_clear();
00740     close( m_writer );
00741     return sigpipe_get() == 0;
00742 }
00743 
00747 class DvEncoderVideoPipePGM : public KinoVideoPipe
00748 {
00749 private:
00750     int width;
00751     int height;
00752     int m_pid, m_writer;
00753     GError *m_error;
00754     
00755 public:
00756     bool OpenVideoPipe( char *pipe, int width, int height, bool interlaced = true );
00757     bool OutputVideoFrame( uint8_t *frame, int size );
00758     bool CloseVideo( );
00759 };
00760 
00764 bool DvEncoderVideoPipePGM::OpenVideoPipe( char *pipe, int width, int height, bool interlaced )
00765 {
00766     sigpipe_clear();
00767     char * args[ 4 ];
00768 
00769     args[ 0 ] = "/bin/sh";
00770     args[ 1 ] = "-c";
00771     args[ 2 ] = ( char * )pipe;
00772     args[ 3 ] = NULL;
00773 
00774     g_spawn_async_with_pipes( ".", args, NULL, G_SPAWN_LEAVE_DESCRIPTORS_OPEN, NULL, NULL, &m_pid, &m_writer, NULL, NULL, &m_error );
00775     
00776     this->width = width;
00777     this->height = height;
00778     return m_writer != -1 && sigpipe_get() == 0;
00779 }
00780 
00784 bool DvEncoderVideoPipePGM::OutputVideoFrame( uint8_t *frame, int size )
00785 {
00786     sigpipe_clear();
00787     char output[ 256 ];
00788     sprintf( output, "P5\n%d %d\n255\n", width, height * 3 / 2 );
00789     write( m_writer, output, strlen( output ) );
00790     write( m_writer, frame, width * height );
00791     int h = height >> 1;
00792     int w = width >> 1;
00793     uint8_t *ptr1 = frame + width * height;
00794     uint8_t *ptr2 = ptr1 + ( w * h ) ;
00795     for ( int i = 0; i < h; i++ )
00796     {
00797         write( m_writer, ptr1, w );
00798         write( m_writer, ptr2, w );
00799         ptr1 += w;
00800         ptr2 += w;
00801     }
00802     return sigpipe_get() == 0;
00803 }
00804 
00808 bool DvEncoderVideoPipePGM::CloseVideo( )
00809 {
00810     sigpipe_clear();
00811     close( m_writer );
00812     return sigpipe_get() == 0;
00813 }
00814 
00822 KinoVideoPipe *KinoVideoFactory::CreateVideoPipe( kino_video_pipe type )
00823 {
00824     switch ( type )
00825     {
00826     case PIPE_VIDEO_MJPEG:
00827         return new KinoMJPEGVideoPipe();
00828     case PIPE_VIDEO_DEINTERLACED_MJPEG:
00829         return new KinoDeinterlacedMJPEGVideoPipe();
00830     case PIPE_VIDEO_DV_YUV:
00831         return new DvEncoderVideoPipeYUV();
00832     case PIPE_VIDEO_DV_PGM:
00833         return new DvEncoderVideoPipePGM();
00834     default:
00835         return NULL;
00836     }
00837 }
00838 
00839 

Generated on Sun Mar 11 22:11:45 2007 for Kino by  doxygen 1.4.2