00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00042
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
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
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
00510 for ( j = 0; j < w2; j++ )
00511 {
00512
00513 *( y++ ) = *( input++ );
00514 *( cb++ ) = *( input++ );
00515 *( y++ ) = *( input++ );
00516 *( cr++ ) = *( input++ );
00517 }
00518
00519 for ( j = 0; j < w2; j++ )
00520 {
00521
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
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