00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00029 #ifdef HAVE_CONFIG_H
00030 #include <config.h>
00031 #endif
00032
00033
00034
00035 #include <string>
00036 #include <iostream>
00037 #include <sstream>
00038 #include <iomanip>
00039 #include <deque>
00040
00041 using std::ostringstream;
00042 using std::setw;
00043 using std::setfill;
00044 using std::hex;
00045 using std::dec;
00046 using std::deque;
00047 using std::cerr;
00048 using std::endl;
00049
00050
00051
00052 #include <pthread.h>
00053 #include <math.h>
00054
00055
00056 #include "frame.h"
00057 #include "preferences.h"
00058
00059 VideoInfo::VideoInfo() : width( 0 ), height( 0 ), isPAL( false )
00060 {}
00061
00062 #ifndef HAVE_LIBDV
00063 static bool Frame::maps_initialized = false;
00064 static int Frame::palmap_ch1[ 2000 ];
00065 static int Frame::palmap_ch2[ 2000 ];
00066 static int Frame::palmap_2ch1[ 2000 ];
00067 static int Frame::palmap_2ch2[ 2000 ];
00068 static int Frame::ntscmap_ch1[ 2000 ];
00069 static int Frame::ntscmap_ch2[ 2000 ];
00070 static int Frame::ntscmap_2ch1[ 2000 ];
00071 static int Frame::ntscmap_2ch2[ 2000 ];
00072 static short Frame::compmap[ 4096 ];
00073 #endif
00074
00075
00076 static pthread_mutex_t avcodec_mutex = PTHREAD_MUTEX_INITIALIZER;
00077 #if defined(HAVE_LIBAVCODEC)
00078 static AVFormatContext *avformatEncoder = NULL;
00079 static AVPacket avpacketEncoder;
00080 static bool isEncoderHeaderWritten = false;
00081 #if defined(HAVE_SWSCALE)
00082 static struct SwsContext *imgConvertEncoderCtx = NULL;
00083 #endif
00084 #endif
00085 static uint8_t *tempImage = NULL;
00086
00094 Frame::Frame() : bytesInFrame( 0 )
00095 {
00096 #if defined(HAVE_LIBAVCODEC)
00097 pthread_mutex_lock( &avcodec_mutex );
00098 av_register_all();
00099 libavcodec = avcodec_alloc_context();
00100 libavcodec->thread_count = 2;
00101 avcodec_open( libavcodec, &dvvideo_decoder );
00102 pthread_mutex_unlock( &avcodec_mutex );
00103 data = ( unsigned char* ) av_mallocz( 144000 );
00104 #if defined(HAVE_SWSCALE)
00105 imgConvertRgbCtx = NULL;
00106 imgConvertYuvCtx = NULL;
00107 #endif
00108 #else
00109 data = ( unsigned char* ) calloc( 1, 144000 );
00110 #endif
00111
00112 #ifdef HAVE_LIBDV
00113 decoder = dv_decoder_new( FALSE,
00114 Preferences::getInstance().dvDecoderClampLuma,
00115 Preferences::getInstance().dvDecoderClampChroma );
00116 decoder->audio->arg_audio_emphasis = 2;
00117 this->SetPreferredQuality( );
00118 dv_set_audio_correction ( decoder, DV_AUDIO_CORRECT_AVERAGE );
00119 dv_set_error_log( decoder, NULL );
00120 encoder = NULL;
00121 #else
00122
00123 if ( maps_initialized == false )
00124 {
00125
00126 for ( int n = 0; n < 1944; ++n )
00127 {
00128 int sequence1 = ( ( n / 3 ) + 2 * ( n % 3 ) ) % 6;
00129 int sequence2 = sequence1 + 6;
00130 int block = 3 * ( n % 3 ) + ( ( n % 54 ) / 18 );
00131
00132 block = 6 + block * 16;
00133 {
00134 register int byte = 8 + 2 * ( n / 54 );
00135 palmap_ch1[ n ] = sequence1 * 150 * 80 + block * 80 + byte;
00136 palmap_ch2[ n ] = sequence2 * 150 * 80 + block * 80 + byte;
00137 byte += ( n / 54 );
00138 palmap_2ch1[ n ] = sequence1 * 150 * 80 + block * 80 + byte;
00139 palmap_2ch2[ n ] = sequence2 * 150 * 80 + block * 80 + byte;
00140 }
00141 }
00142 for ( int n = 0; n < 1620; ++n )
00143 {
00144 int sequence1 = ( ( n / 3 ) + 2 * ( n % 3 ) ) % 5;
00145 int sequence2 = sequence1 + 5;
00146 int block = 3 * ( n % 3 ) + ( ( n % 45 ) / 15 );
00147
00148 block = 6 + block * 16;
00149 {
00150 register int byte = 8 + 2 * ( n / 45 );
00151 ntscmap_ch1[ n ] = sequence1 * 150 * 80 + block * 80 + byte;
00152 ntscmap_ch2[ n ] = sequence2 * 150 * 80 + block * 80 + byte;
00153 byte += ( n / 45 );
00154 ntscmap_2ch1[ n ] = sequence1 * 150 * 80 + block * 80 + byte;
00155 ntscmap_2ch2[ n ] = sequence2 * 150 * 80 + block * 80 + byte;
00156 }
00157 }
00158 for ( int y = 0x700; y <= 0x7ff; ++y )
00159 compmap[ y ] = ( y - 0x600 ) << 6;
00160 for ( int y = 0x600; y <= 0x6ff; ++y )
00161 compmap[ y ] = ( y - 0x500 ) << 5;
00162 for ( int y = 0x500; y <= 0x5ff; ++y )
00163 compmap[ y ] = ( y - 0x400 ) << 4;
00164 for ( int y = 0x400; y <= 0x4ff; ++y )
00165 compmap[ y ] = ( y - 0x300 ) << 3;
00166 for ( int y = 0x300; y <= 0x3ff; ++y )
00167 compmap[ y ] = ( y - 0x200 ) << 2;
00168 for ( int y = 0x200; y <= 0x2ff; ++y )
00169 compmap[ y ] = ( y - 0x100 ) << 1;
00170 for ( int y = 0x000; y <= 0x1ff; ++y )
00171 compmap[ y ] = y;
00172 for ( int y = 0x800; y <= 0xfff; ++y )
00173 compmap[ y ] = -1 - compmap[ 0xfff - y ];
00174 maps_initialized = true;
00175 }
00176 #endif
00177 for ( int n = 0; n < 4; n++ )
00178 audio_buffers[ n ] = ( int16_t * ) malloc( 2 * DV_AUDIO_MAX_SAMPLES * sizeof( int16_t ) );
00179 }
00180
00181
00182 Frame::~Frame()
00183 {
00184 #if defined(HAVE_LIBAVCODEC)
00185 pthread_mutex_lock( &avcodec_mutex );
00186 avcodec_close( libavcodec );
00187 av_free( libavcodec );
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 pthread_mutex_unlock( &avcodec_mutex );
00198 av_free( data );
00199 #if defined(HAVE_SWSCALE)
00200 if ( imgConvertRgbCtx )
00201 sws_freeContext( imgConvertRgbCtx );
00202 if ( imgConvertYuvCtx )
00203 sws_freeContext( imgConvertYuvCtx );
00204 #endif
00205 #else
00206 free( data );
00207 #endif
00208
00209 #ifdef HAVE_LIBDV
00210 dv_decoder_free( decoder );
00211 if ( encoder )
00212 dv_encoder_free( encoder );
00213 #endif
00214
00215 for ( int n = 0; n < 4; n++ )
00216 free( audio_buffers[ n ] );
00217 }
00218
00219
00220 Frame& Frame::operator=( const Frame& rhs )
00221 {
00222 bytesInFrame = rhs.GetFrameSize();
00223 if ( bytesInFrame > 144000 )
00224 bytesInFrame = 144000;
00225 memcpy( data, rhs.data, bytesInFrame );
00226 ExtractHeader();
00227 return *this;
00228 }
00229
00230
00239 bool Frame::GetSSYBPack( int packNum, Pack &pack ) const
00240 {
00241 #ifdef HAVE_LIBDV
00242 pack.data[ 0 ] = packNum;
00243 dv_get_ssyb_pack( decoder, packNum, &pack.data[ 1 ] );
00244 return true;
00245 #else
00246
00247
00248 int seqCount = IsPAL() ? 12 : 10;
00249
00250
00251
00252 for ( int i = 0; i < seqCount; ++i )
00253 {
00254
00255
00256
00257 for ( int j = 0; j < 2; ++j )
00258 {
00259
00260
00261
00262 for ( int k = 0; k < 6; ++k )
00263 {
00264
00265
00266
00267
00268
00269
00270 const unsigned char *s = &data[ i * 150 * 80 + 1 * 80 + j * 80 + 3 + k * 8 + 3 ];
00271
00272
00273 if ( s[ 0 ] == packNum )
00274 {
00275
00276 pack.data[ 0 ] = s[ 0 ];
00277 pack.data[ 1 ] = s[ 1 ];
00278 pack.data[ 2 ] = s[ 2 ];
00279 pack.data[ 3 ] = s[ 3 ];
00280 pack.data[ 4 ] = s[ 4 ];
00281 return true;
00282 }
00283 }
00284 }
00285 }
00286 return false;
00287 #endif
00288 }
00289
00290
00302 bool Frame::GetVAUXPack( int packNum, Pack &pack ) const
00303 {
00304 #ifdef HAVE_LIBDV
00305 pack.data[ 0 ] = packNum;
00306 dv_get_vaux_pack( decoder, packNum, &pack.data[ 1 ] );
00307
00308
00309
00310
00311
00312
00313
00314 return true;
00315
00316 #else
00317
00318
00319 int seqCount = IsPAL() ? 12 : 10;
00320
00321
00322
00323 for ( int i = 0; i < seqCount; ++i )
00324 {
00325
00326
00327
00328 for ( int j = 0; j < 3; ++j )
00329 {
00330
00331
00332
00333 for ( int k = 0; k < 15; ++k )
00334 {
00335
00336
00337
00338
00339
00340
00341 const unsigned char *s = &data[ i * 150 * 80 + 3 * 80 + j * 80 + 3 + k * 5 ];
00342
00343
00344 if ( s[ 0 ] == packNum )
00345 {
00346 pack.data[ 0 ] = s[ 0 ];
00347 pack.data[ 1 ] = s[ 1 ];
00348 pack.data[ 2 ] = s[ 2 ];
00349 pack.data[ 3 ] = s[ 3 ];
00350 pack.data[ 4 ] = s[ 4 ];
00351 return true;
00352 }
00353 }
00354 }
00355 }
00356 return false;
00357 #endif
00358 }
00359
00360
00371 bool Frame::GetAAUXPack( int packNum, Pack &pack ) const
00372 {
00373 #ifdef HAVE_LIBDV
00374 bool done = false;
00375 switch ( packNum )
00376 {
00377 case 0x50:
00378 memcpy( pack.data, &decoder->audio->aaux_as, 5 );
00379 done = true;
00380 break;
00381
00382 case 0x51:
00383 memcpy( pack.data, &decoder->audio->aaux_asc, 5 );
00384 done = true;
00385 break;
00386
00387 case 0x52:
00388 memcpy( pack.data, &decoder->audio->aaux_as1, 5 );
00389 done = true;
00390 break;
00391
00392 case 0x53:
00393 memcpy( pack.data, &decoder->audio->aaux_asc1, 5 );
00394 done = true;
00395 break;
00396 }
00397 if ( done )
00398 return true;
00399 #endif
00400
00401
00402
00403 int seqCount = IsPAL() ? 12 : 10;
00404
00405
00406
00407 for ( int i = 0; i < seqCount; ++i )
00408 {
00409
00410
00411 for ( int j = 0; j < 9; ++j )
00412 {
00413
00414
00415
00416
00417
00418
00419 const unsigned char *s = &data[ i * 150 * 80 + 6 * 80 + j * 16 * 80 + 3 ];
00420 if ( s[ 0 ] == packNum )
00421 {
00422
00423
00424 pack.data[ 0 ] = s[ 0 ];
00425 pack.data[ 1 ] = s[ 1 ];
00426 pack.data[ 2 ] = s[ 2 ];
00427 pack.data[ 3 ] = s[ 3 ];
00428 pack.data[ 4 ] = s[ 4 ];
00429 return true;
00430 }
00431 }
00432 }
00433 return false;
00434 }
00435
00445 bool Frame::GetRecordingDate( struct tm &recDate ) const
00446 {
00447 #ifdef HAVE_LIBDV
00448 return dv_get_recording_datetime_tm( decoder, ( struct tm * ) &recDate );
00449 #else
00450
00451 Pack pack62;
00452 Pack pack63;
00453
00454 if ( GetSSYBPack( 0x62, pack62 ) == false )
00455 return false;
00456
00457 int day = pack62.data[ 2 ];
00458 int month = pack62.data[ 3 ];
00459 int year = pack62.data[ 4 ];
00460
00461 if ( GetSSYBPack( 0x63, pack63 ) == false )
00462 return false;
00463
00464 int sec = pack63.data[ 2 ];
00465 int min = pack63.data[ 3 ];
00466 int hour = pack63.data[ 4 ];
00467
00468 sec = ( sec & 0xf ) + 10 * ( ( sec >> 4 ) & 0x7 );
00469 min = ( min & 0xf ) + 10 * ( ( min >> 4 ) & 0x7 );
00470 hour = ( hour & 0xf ) + 10 * ( ( hour >> 4 ) & 0x3 );
00471 year = ( year & 0xf ) + 10 * ( ( year >> 4 ) & 0xf );
00472 month = ( month & 0xf ) + 10 * ( ( month >> 4 ) & 0x1 );
00473 day = ( day & 0xf ) + 10 * ( ( day >> 4 ) & 0x3 );
00474
00475 if ( year < 25 )
00476 year += 2000;
00477 else
00478 year += 1900;
00479
00480 recDate.tm_sec = sec;
00481 recDate.tm_min = min;
00482 recDate.tm_hour = hour;
00483 recDate.tm_mday = day;
00484 recDate.tm_mon = month - 1;
00485 recDate.tm_year = year - 1900;
00486 recDate.tm_wday = -1;
00487 recDate.tm_yday = -1;
00488 recDate.tm_isdst = -1;
00489
00490
00491
00492 if ( mktime( &recDate ) == -1 )
00493 return false;
00494 return true;
00495 #endif
00496 }
00497
00498
00499 string Frame::GetRecordingDate( void ) const
00500 {
00501 string recDate;
00502 #ifdef HAVE_LIBDV
00503
00504 char s[ 64 ];
00505 if ( dv_get_recording_datetime( decoder, s ) )
00506 recDate = s;
00507 else
00508 recDate = "0000-00-00 00:00:00";
00509 #else
00510
00511 struct tm date;
00512 ostringstream sb;
00513
00514 if ( GetRecordingDate( date ) == true )
00515 {
00516 sb << setfill( '0' )
00517 << setw( 4 ) << date.tm_year + 1900 << '.'
00518 << setw( 2 ) << date.tm_mon + 1 << '.'
00519 << setw( 2 ) << date.tm_mday << '_'
00520 << setw( 2 ) << date.tm_hour << '-'
00521 << setw( 2 ) << date.tm_min << '-'
00522 << setw( 2 ) << date.tm_sec;
00523 sb >> recDate;
00524 }
00525 else
00526 {
00527 recDate = "0000.00.00_00-00-00";
00528 }
00529 #endif
00530 return recDate;
00531 }
00532
00533
00543 bool Frame::GetTimeCode( TimeCode &timeCode ) const
00544 {
00545 #ifdef HAVE_LIBDV
00546 int timestamp[ 4 ];
00547
00548 dv_get_timestamp_int( decoder, timestamp );
00549
00550 timeCode.hour = timestamp[ 0 ];
00551 timeCode.min = timestamp[ 1 ];
00552 timeCode.sec = timestamp[ 2 ];
00553 timeCode.frame = timestamp[ 3 ];
00554 #else
00555
00556 Pack tc;
00557
00558 if ( GetSSYBPack( 0x13, tc ) == false )
00559 return false;
00560
00561 int frame = tc.data[ 1 ];
00562 int sec = tc.data[ 2 ];
00563 int min = tc.data[ 3 ];
00564 int hour = tc.data[ 4 ];
00565
00566 timeCode.frame = ( frame & 0xf ) + 10 * ( ( frame >> 4 ) & 0x3 );
00567 timeCode.sec = ( sec & 0xf ) + 10 * ( ( sec >> 4 ) & 0x7 );
00568 timeCode.min = ( min & 0xf ) + 10 * ( ( min >> 4 ) & 0x7 );
00569 timeCode.hour = ( hour & 0xf ) + 10 * ( ( hour >> 4 ) & 0x3 );
00570 #endif
00571
00572 return true;
00573 }
00574
00575
00583 bool Frame::GetAudioInfo( AudioInfo &info ) const
00584 {
00585 #ifdef HAVE_LIBDV
00586 info.frequency = dv_get_frequency( decoder );
00587 info.samples = dv_get_num_samples( decoder );
00588 info.frames = IsPAL() ? 50 : 60;
00589 info.channels = dv_get_num_channels( decoder );
00590 info.quantization = ( decoder->audio->aaux_as.pc4.qu == 0 ) ? 16 : 12;
00591 return true;
00592 #else
00593
00594 int af_size;
00595 int smp;
00596 int flag;
00597 Pack pack50;
00598
00599
00600 info.channels = 2;
00601
00602
00603
00604
00605
00606 if ( GetAAUXPack( 0x50, pack50 ) == true )
00607 {
00608
00609
00610
00611
00612 af_size = pack50.data[ 1 ] & 0x3f;
00613 smp = ( pack50.data[ 4 ] >> 3 ) & 0x07;
00614 flag = pack50.data[ 3 ] & 0x20;
00615
00616 if ( flag == 0 )
00617 {
00618 info.frames = 60;
00619 switch ( smp )
00620 {
00621 case 0:
00622 info.frequency = 48000;
00623 info.samples = 1580 + af_size;
00624 break;
00625 case 1:
00626 info.frequency = 44100;
00627 info.samples = 1452 + af_size;
00628 break;
00629 case 2:
00630 info.frequency = 32000;
00631 info.samples = 1053 + af_size;
00632 break;
00633 }
00634 }
00635 else
00636 {
00637 info.frames = 50;
00638 switch ( smp )
00639 {
00640 case 0:
00641 info.frequency = 48000;
00642 info.samples = 1896 + af_size;
00643 break;
00644 case 1:
00645 info.frequency = 44100;
00646 info.samples = 0;
00647 break;
00648 case 2:
00649 info.frequency = 32000;
00650 info.samples = 1264 + af_size;
00651 break;
00652 }
00653 }
00654 return true;
00655 }
00656 else
00657 {
00658 return false;
00659 }
00660 #endif
00661 }
00662
00663
00664 bool Frame::GetVideoInfo( VideoInfo &info ) const
00665 {
00666 GetTimeCode( info.timeCode );
00667 GetRecordingDate( info.recDate );
00668 info.isPAL = IsPAL();
00669 return true;
00670 }
00671
00672
00679 int Frame::GetFrameSize( void ) const
00680 {
00681 return IsPAL() ? 144000 : 120000;
00682 }
00683
00684
00691 float Frame::GetFrameRate( void ) const
00692 {
00693 return IsPAL() ? 25.0 : 30000.0 / 1001.0;
00694 }
00695
00696
00703 bool Frame::IsPAL( void ) const
00704 {
00705 unsigned char dsf = data[ 3 ] & 0x80;
00706 bool pal = ( dsf == 0 ) ? false : true;
00707
00708 #ifdef HAVE_LIBDV
00709 if ( !pal )
00710 pal = dv_is_PAL( decoder );
00711 #endif
00712 return pal;
00713 }
00714
00715
00723 bool Frame::IsNewRecording() const
00724 {
00725 #ifdef HAVE_LIBDV
00726 return dv_is_new_recording( decoder, data );
00727 #else
00728
00729 Pack aauxSourceControl;
00730
00731
00732
00733 if ( GetAAUXPack( 0x51, aauxSourceControl ) == false )
00734 return false;
00735
00736 unsigned char recStartPoint = aauxSourceControl.data[ 2 ] & 0x80;
00737
00738 return recStartPoint == 0 ? true : false;
00739 #endif
00740 }
00741
00742
00751 bool Frame::IsNormalSpeed() const
00752 {
00753 bool normal_speed = true;
00754
00755 #ifdef HAVE_LIBDV
00756
00757 return dv_is_normal_speed( decoder );
00758 #endif
00759
00760 return ( normal_speed );
00761 }
00762
00763
00768 bool Frame::IsComplete( void ) const
00769 {
00770 return bytesInFrame >= GetFrameSize();
00771 }
00772
00773
00785 int Frame::ExtractAudio( void *sound ) const
00786 {
00787 AudioInfo info;
00788
00789 #ifdef HAVE_LIBDV
00790
00791 if ( GetAudioInfo( info ) == true )
00792 {
00793 int n, i;
00794 int16_t* s = ( int16_t * ) sound;
00795 if ( dv_decode_full_audio( decoder, data, ( int16_t ** ) audio_buffers ) == TRUE )
00796 {
00797 for ( n = 0; n < info.samples; ++n )
00798 for ( i = 0; i < info.channels; i++ )
00799 *s++ = audio_buffers[ i ][ n ];
00800 }
00801 else
00802 {
00803 info.samples = 0;
00804 }
00805 }
00806 else
00807 info.samples = 0;
00808
00809 #else
00810
00811 char* s = ( char * ) sound;
00812
00813 GetAudioInfo( info );
00814 switch ( info.frequency )
00815 {
00816 case 32000:
00817
00818
00819
00820 if ( IsPAL() )
00821 {
00822 short * p = ( short* ) sound;
00823 for ( int n = 0; n < info.samples; ++n )
00824 {
00825 register int r = ( ( unsigned char* ) data ) [ palmap_2ch1[ n ] + 1 ];
00826 *p++ = compmap[ ( ( ( unsigned char* ) data ) [ palmap_2ch1[ n ] ] << 4 ) + ( r >> 4 ) ];
00827 *p++ = compmap[ ( ( ( unsigned char* ) data ) [ palmap_2ch1[ n ] + 1 ] << 4 ) + ( r & 0x0f ) ];
00828 }
00829
00830
00831 }
00832 else
00833 {
00834 short* p = ( short* ) sound;
00835 for ( int n = 0; n < info.samples; ++n )
00836 {
00837 register int r = ( ( unsigned char* ) data ) [ ntscmap_2ch1[ n ] + 1 ];
00838 *p++ = compmap[ ( ( ( unsigned char* ) data ) [ ntscmap_2ch1[ n ] ] << 4 ) + ( r >> 4 ) ];
00839 *p++ = compmap[ ( ( ( unsigned char* ) data ) [ ntscmap_2ch1[ n ] + 1 ] << 4 ) + ( r & 0x0f ) ];
00840 }
00841 }
00842 break;
00843
00844 case 44100:
00845 case 48000:
00846
00847
00848
00849 if ( IsPAL() )
00850 {
00851 for ( int n = 0; n < info.samples; ++n )
00852 {
00853 *s++ = ( ( char* ) data ) [ palmap_ch1[ n ] + 1 ];
00854 *s++ = ( ( char* ) data ) [ palmap_ch1[ n ] ];
00855 *s++ = ( ( char* ) data ) [ palmap_ch2[ n ] + 1 ];
00856 *s++ = ( ( char* ) data ) [ palmap_ch2[ n ] ];
00857 }
00858 }
00859 else
00860 {
00861 for ( int n = 0; n < info.samples; ++n )
00862 {
00863 *s++ = ( ( char* ) data ) [ ntscmap_ch1[ n ] + 1 ];
00864 *s++ = ( ( char* ) data ) [ ntscmap_ch1[ n ] ];
00865 *s++ = ( ( char* ) data ) [ ntscmap_ch2[ n ] + 1 ];
00866 *s++ = ( ( char* ) data ) [ ntscmap_ch2[ n ] ];
00867 }
00868 }
00869 break;
00870
00871
00872
00873 default:
00874 info.samples = 0;
00875 }
00876
00877 #endif
00878 return info.samples * info.channels * 2;
00879 }
00880
00881
00882 void Frame::GetUpperField( void * image, int bpp )
00883 {
00884 register int width = GetWidth( ) * bpp;
00885 register int height = GetHeight( );
00886 for ( register int i = 0; i < height; i += 2 )
00887 memcpy( ( uint8_t * ) image + width * ( i + 1 ), ( uint8_t * ) image + width * i, width );
00888 }
00889
00890
00891 void Frame::GetLowerField( void * image, int bpp )
00892 {
00893 register int width = GetWidth( ) * bpp;
00894 register int height = GetHeight( );
00895 for ( register int i = 0; i < height; i += 2 )
00896 memcpy( ( uint8_t * ) image + width * i, ( uint8_t * ) image + width * ( i + 1 ), width );
00897 }
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916 void Frame::Deinterlace( uint8_t *pdst, uint8_t *psrc, int stride, int height )
00917 {
00918 register int x, y;
00919 register uint8_t *l0, *l1, *l2, *l3;
00920
00921 l0 = pdst;
00922 l1 = psrc;
00923 l2 = l1 + stride;
00924 l3 = l2 + stride;
00925
00926
00927 memcpy( l0, l1, stride );
00928 l0 += stride;
00929
00930 for (y = 1; y < height-1; ++y)
00931 {
00932
00933 for ( x = 0; x < stride; ++x )
00934 l0[x] = ( l1[ x ] + ( l2[ x ] << 1 ) + l3[ x ] ) >> 2;
00935
00936
00937 l1 = l2;
00938 l2 = l3;
00939 l3 += stride;
00940 l0 += stride;
00941 }
00942
00943
00944 memcpy( l0, l1, stride );
00945 }
00946
00947
00954 bool Frame::IsWide( void ) const
00955 {
00956
00957
00958
00959 Pack pack;
00960 if ( GetVAUXPack( 0x61, pack ) )
00961 return ( ( pack.data[2] & 0x7 ) == 0x2 ) || ( ( pack.data[2] & 0x7 ) == 0x7 );
00962 else
00963 return false;
00964 }
00965
00966
00971 int Frame::GetWidth()
00972 {
00973 return 720;
00974 }
00975
00976
00981 int Frame::GetHeight()
00982 {
00983 return IsPAL() ? 576 : 480;
00984 }
00985
00986
00987 #ifdef HAVE_LIBDV
00988
00989 void Frame::SetPreferredQuality( )
00990 {
00991 switch ( Preferences::getInstance().displayQuality )
00992 {
00993 case 5:
00994 dv_set_quality( decoder, DV_QUALITY_FASTEST );
00995 break;
00996 case 4:
00997 dv_set_quality( decoder, DV_QUALITY_AC_1 );
00998 break;
00999 case 3:
01000 dv_set_quality( decoder, DV_QUALITY_COLOR | DV_QUALITY_DC );
01001 break;
01002 case 2:
01003 dv_set_quality( decoder, DV_QUALITY_COLOR | DV_QUALITY_AC_1 );
01004 break;
01005 default:
01006 dv_set_quality( decoder, DV_QUALITY_BEST );
01007 break;
01008 }
01009 }
01010
01022 int Frame::ExtractAudio( int16_t **channels ) const
01023 {
01024 AudioInfo info;
01025
01026 if ( GetAudioInfo( info ) )
01027 {
01028 if ( dv_decode_full_audio( decoder, data, channels ) == FALSE )
01029 info.samples = 0;
01030 }
01031 else
01032 {
01033 info.samples = 0;
01034 }
01035
01036 return info.samples * info.channels * 2;
01037 }
01038
01039 void Frame::ExtractHeader( void )
01040 {
01041 dv_parse_header( decoder, data );
01042 dv_parse_packs( decoder, data );
01043 }
01044
01045 int Frame::ExtractRGB( void * rgb )
01046 {
01047 #if defined(HAVE_LIBAVCODEC)
01048 AVFrame *frame = avcodec_alloc_frame();
01049 AVPicture dest;
01050 int got_picture;
01051
01052 avcodec_decode_video( libavcodec, frame, &got_picture, data, GetFrameSize() );
01053 if ( got_picture )
01054 {
01055 avpicture_fill( &dest, static_cast<uint8_t*>( rgb ), PIX_FMT_RGB24, GetWidth(), GetHeight() );
01056 #if defined(HAVE_SWSCALE)
01057 if ( !imgConvertRgbCtx )
01058 imgConvertRgbCtx = sws_getContext( libavcodec->width, libavcodec->height, libavcodec->pix_fmt,
01059 GetWidth(), GetHeight(), PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL );
01060 sws_scale( imgConvertRgbCtx, frame->data, frame->linesize, 0, libavcodec->height, dest.data, dest.linesize );
01061 #else
01062 img_convert( &dest, PIX_FMT_RGB24, reinterpret_cast<AVPicture*>( frame ), libavcodec->pix_fmt, GetWidth(), GetHeight() );
01063 #endif
01064 }
01065 av_free( frame );
01066 #else
01067 unsigned char *pixels[ 3 ];
01068 int pitches[ 3 ];
01069
01070 pixels[ 0 ] = ( unsigned char* ) rgb;
01071 pixels[ 1 ] = NULL;
01072
01073
01074 pixels[ 2 ] = NULL;
01075
01076 pitches[ 0 ] = 720 * 3;
01077 pitches[ 1 ] = 0;
01078 pitches[ 2 ] = 0;
01079
01080 dv_decode_full_frame( decoder, data, e_dv_color_rgb, pixels, pitches );
01081 #endif
01082 return 0;
01083 }
01084
01085 int Frame::ExtractPreviewRGB( void *rgb )
01086 {
01087 ExtractRGB( rgb );
01088 switch ( Preferences::getInstance().displayExtract )
01089 {
01090 case 1:
01091 Deinterlace( ( uint8_t* ) rgb, ( uint8_t* ) rgb, GetWidth() * 3, GetHeight() );
01092 break;
01093 case 2:
01094 GetLowerField( rgb, 3 );
01095 break;
01096 case 3:
01097 GetUpperField( rgb, 3 );
01098 break;
01099 default:
01100 break;
01101 }
01102 return 0;
01103 }
01104
01105 int Frame::ExtractYUV( void *yuv )
01106 {
01107 #if defined(HAVE_LIBAVCODEC)
01108 AVFrame *frame = avcodec_alloc_frame();;
01109 AVPicture output;
01110 int got_picture;
01111
01112 avcodec_decode_video( libavcodec, frame, &got_picture, data, GetFrameSize() );
01113 if ( got_picture )
01114 {
01115 avpicture_fill( &output, static_cast<uint8_t*>( yuv ), PIX_FMT_YUV422, GetWidth(), GetHeight() );
01116 #if defined(HAVE_SWSCALE)
01117 if ( !imgConvertYuvCtx )
01118 imgConvertYuvCtx = sws_getContext( libavcodec->width, libavcodec->height, libavcodec->pix_fmt,
01119 GetWidth(), GetHeight(), PIX_FMT_YUV422, SWS_FAST_BILINEAR, NULL, NULL, NULL );
01120 sws_scale( imgConvertYuvCtx, frame->data, frame->linesize, 0, libavcodec->height, output.data, output.linesize );
01121 #else
01122 img_convert( &output, PIX_FMT_YUV422, (AVPicture *)frame, libavcodec->pix_fmt, GetWidth(), GetHeight() );
01123 #endif
01124 }
01125 av_free( frame );
01126 #else
01127 unsigned char *pixels[ 3 ];
01128 int pitches[ 3 ];
01129
01130 pixels[ 0 ] = ( unsigned char* ) yuv;
01131 pitches[ 0 ] = decoder->width * 2;
01132
01133 dv_decode_full_frame( decoder, data, e_dv_color_yuv, pixels, pitches );
01134 #endif
01135
01136 return 0;
01137 }
01138
01139 int Frame::ExtractYUV420( uint8_t *yuv, uint8_t *output[ 3 ] )
01140 {
01141 #if defined(HAVE_LIBAVCODEC)
01142 AVFrame *frame = avcodec_alloc_frame();
01143 int got_picture;
01144
01145 avcodec_decode_video( libavcodec, frame, &got_picture, data, GetFrameSize() );
01146
01147 int width = GetWidth(), height = GetHeight();
01148
01149 if ( libavcodec->pix_fmt == PIX_FMT_YUV420P )
01150 {
01151 int h2 = height / 2;
01152 int w2 = width / 2;
01153
01154 uint8_t *Y = output[ 0 ];
01155 uint8_t *Cb = output[ 1 ];
01156 uint8_t *Cr = output[ 2 ];
01157 uint8_t *fY = frame->data[ 0 ];
01158 uint8_t *fCb = frame->data[ 1 ];
01159 uint8_t *fCr = frame->data[ 2 ];
01160
01161 for ( int y = 0; y < height; y ++ )
01162 {
01163 memcpy( Y, fY, width );
01164 Y += width;
01165 fY += frame->linesize[ 0 ];
01166 if ( y < h2 )
01167 {
01168 memcpy( Cb, fCb, w2 );
01169 memcpy( Cr, fCr, w2 );
01170 Cb += w2;
01171 Cr += w2;
01172 fCb += frame->linesize[ 1 ];
01173 fCr += frame->linesize[ 2 ];
01174 }
01175 }
01176 }
01177 else
01178 {
01179 int w4 = width / 4;
01180
01181 uint8_t *Y = output[ 0 ];
01182 uint8_t *Cb = output[ 1 ];
01183 uint8_t *Cr = output[ 2 ];
01184 uint8_t *fY = frame->data[ 0 ];
01185 uint8_t *fCb = frame->data[ 1 ];
01186 uint8_t *fCr = frame->data[ 2 ];
01187
01188 for ( int y = 0; y < height; y ++ )
01189 {
01190 memcpy( Y, fY, width );
01191 Y += width;
01192 fY += frame->linesize[ 0 ];
01193 if ( y % 2 == 0 )
01194 {
01195 for ( int x = 0; x < w4; x ++ )
01196 {
01197 *Cb ++ = fCb[ x ];
01198 *Cb ++ = fCb[ frame->linesize[ 1 ] + x ];
01199 *Cr ++ = fCr[ x ];
01200 *Cr ++ = fCr[ frame->linesize[ 2 ] + x ];
01201 }
01202 fCb += 2 * frame->linesize[ 1 ];
01203 fCr += 2 * frame->linesize[ 2 ];
01204 }
01205 }
01206 }
01207 av_free( frame );
01208 #else
01209 unsigned char *pixels[ 3 ];
01210 int pitches[ 3 ];
01211 int width = GetWidth(), height = GetHeight();
01212
01213 pixels[ 0 ] = ( unsigned char* ) yuv;
01214 pitches[ 0 ] = decoder->width * 2;
01215
01216 dv_decode_full_frame( decoder, data, e_dv_color_yuv, pixels, pitches );
01217
01218 int w2 = width / 2;
01219 uint8_t *y = output[ 0 ];
01220 uint8_t *cb = output[ 1 ];
01221 uint8_t *cr = output[ 2 ];
01222 uint8_t *p = yuv;
01223
01224 for ( int i = 0; i < height; i += 2 )
01225 {
01226
01227 for ( int j = 0; j < w2; j++ )
01228 {
01229
01230 *( y++ ) = *( p++ );
01231 *( cb++ ) = *( p++ );
01232 *( y++ ) = *( p++ );
01233 *( cr++ ) = *( p++ );
01234 }
01235
01236 for ( int j = 0; j < w2; j++ )
01237 {
01238
01239 *( y++ ) = *( p++ );
01240 p++;
01241 *( y++ ) = *( p++ );
01242 p++;
01243 }
01244 }
01245 #endif
01246 return 0;
01247 }
01248
01249 int Frame::ExtractPreviewYUV( void *yuv )
01250 {
01251 ExtractYUV( yuv );
01252 switch ( Preferences::getInstance().displayExtract )
01253 {
01254 case 1:
01255 Deinterlace( ( uint8_t* ) yuv, ( uint8_t* ) yuv, GetWidth() * 2, GetHeight() );
01256 break;
01257 case 2:
01258 GetLowerField( yuv, 2 );
01259 break;
01260 case 3:
01261 GetUpperField( yuv, 2 );
01262 break;
01263 default:
01264 break;
01265 }
01266 return 0;
01267 }
01268
01269
01285 void Frame::SetRecordingDate( time_t *datetime, int frame )
01286 {
01287 dv_encode_metadata( data, IsPAL(), IsWide(), datetime, frame );
01288 }
01289
01297 void Frame::SetTimeCode( int frame )
01298 {
01299 dv_encode_timecode( data, IsPAL(), frame );
01300 }
01301
01302 bool Frame::CreateEncoder( bool isPAL, bool isWide )
01303 {
01304 pthread_mutex_lock( &avcodec_mutex );
01305 #if defined(HAVE_LIBAVCODEC)
01306 if ( avformatEncoder == NULL )
01307 {
01308 avformatEncoder = av_alloc_format_context();
01309 if ( avformatEncoder )
01310 {
01311 avformatEncoder->oformat = guess_format( "dv", NULL, NULL );
01312 av_new_stream( avformatEncoder, 0 );
01313 AVCodecContext *avcodecEncoder = avformatEncoder->streams[0]->codec;
01314 avcodecEncoder->width = FRAME_MAX_WIDTH;
01315 avcodecEncoder->height = isPAL ? 576 : 480;
01316 if ( isPAL )
01317 {
01318 if ( isWide )
01319 avcodecEncoder->sample_aspect_ratio = av_d2q( 17.0 / avcodecEncoder->width * avcodecEncoder->height / 10.0, 255 );
01320 else
01321 avcodecEncoder->sample_aspect_ratio = isWide ? ( AVRational ){ 118, 81 } : ( AVRational ){ 59, 54 };
01322 }
01323 else
01324 {
01325 if ( isWide )
01326 avcodecEncoder->sample_aspect_ratio = av_d2q( 17.0 / avcodecEncoder->width * avcodecEncoder->height / 10.0, 255 );
01327 else
01328 avcodecEncoder->sample_aspect_ratio = isWide ? ( AVRational ){ 40, 33 } : ( AVRational ){ 10, 11 };
01329 }
01330 avcodecEncoder->thread_count = 2;
01331 avcodecEncoder->time_base= isPAL ? ( AVRational ){ 1, 25 } : ( AVRational ){ 1001, 30000 };
01332 avcodecEncoder->pix_fmt = isPAL ? PIX_FMT_YUV420P : PIX_FMT_YUV411P;
01333 av_set_parameters( avformatEncoder, NULL );
01334 avcodec_open( avcodecEncoder, &dvvideo_encoder );
01335 av_new_packet( &avpacketEncoder, 144000 );
01336 tempImage = ( uint8_t* ) av_malloc(
01337 avpicture_get_size( avcodecEncoder->pix_fmt, avcodecEncoder->width, avcodecEncoder->height ) );
01338 #if defined(HAVE_SWSCALE)
01339 imgConvertEncoderCtx = sws_getContext( avcodecEncoder->width, avcodecEncoder->height, PIX_FMT_RGB24,
01340 avcodecEncoder->width, avcodecEncoder->height, avcodecEncoder->pix_fmt, SWS_FAST_BILINEAR, NULL, NULL, NULL);
01341 #endif
01342 }
01343 else
01344 {
01345 pthread_mutex_unlock( &avcodec_mutex );
01346 return false;
01347 }
01348 }
01349 #endif
01350 if ( encoder == NULL )
01351 {
01352 if ( isPAL )
01353 encoder = dv_encoder_new( FALSE, FALSE, FALSE );
01354 else
01355 encoder = dv_encoder_new( FALSE,
01356 Preferences::getInstance().dvDecoderClampLuma,
01357 Preferences::getInstance().dvDecoderClampChroma );
01358 if ( encoder )
01359 {
01360 encoder->isPAL = isPAL;
01361 encoder->is16x9 = isWide;
01362 encoder->vlc_encode_passes = 3;
01363 encoder->static_qno = 0;
01364 encoder->force_dct = DV_DCT_AUTO;
01365
01366 tempImage = new uint8_t[ FRAME_MAX_WIDTH * FRAME_MAX_HEIGHT * 4 ];
01367 }
01368 }
01369 pthread_mutex_unlock( &avcodec_mutex );
01370 return ( encoder != NULL );
01371 }
01372
01373 bool Frame::EncodeAudio( AudioInfo &info, int16_le_t **channels )
01374 {
01375 int result = -1;
01376
01377 if ( CreateEncoder( IsPAL(), IsWide() ) )
01378 {
01379 encoder->samples_this_frame = info.samples;
01380 result = dv_encode_full_audio( encoder, (int16_t**)channels, info.channels, info.frequency, data );
01381 }
01382 return ( result != -1 );
01383 }
01384
01385 #if BYTE_ORDER == BIG_ENDIAN
01386 bool Frame::EncodeAudio( AudioInfo &info, int16_ne_t **channels )
01387 {
01388 int result = -1;
01389
01390 if ( CreateEncoder( IsPAL(), IsWide() ) )
01391 {
01392 int16_le_t** le_audio = reinterpret_cast< int16_le_t** >( audio_buffers );
01393 for ( int s = 0; s < info.samples; s++ )
01394 for ( int c = 0; c < info.channels; c++ )
01395 le_audio[ c ][ s ] = channels[ c ][ s ];
01396 encoder->samples_this_frame = info.samples;
01397 result = dv_encode_full_audio( encoder, audio_buffers, info.channels, info.frequency, data );
01398 }
01399 return ( result != -1 );
01400 }
01401 #endif
01402
01403 int Frame::CalculateNumberSamples( int frequency, int iteration )
01404 {
01405 int samples = 0;
01406
01407 if ( CreateEncoder( IsPAL(), IsWide() ) )
01408 samples = dv_calculate_samples( encoder, frequency, iteration );
01409
01410 return samples;
01411 }
01412
01413 void Frame::EncodeRGB( uint8_t *rgb )
01414 {
01415 if ( CreateEncoder( IsPAL(), IsWide() ) )
01416 {
01417 #if defined(HAVE_LIBAVCODEC)
01418 AVFrame *input = avcodec_alloc_frame();
01419 AVFrame *output = avcodec_alloc_frame();
01420
01421 if ( input && output )
01422 {
01423 AVCodecContext *avcodecEncoder = avformatEncoder->streams[0]->codec;
01424 int width = avcodecEncoder->width;
01425 int height = avcodecEncoder->height;
01426 size_t size = height > 480 ? 144000 : 120000;
01427
01428
01429 avpicture_fill( ( AVPicture* )output, tempImage, avcodecEncoder->pix_fmt, width, height );
01430 avpicture_fill( ( AVPicture* )input, rgb, PIX_FMT_RGB24, width, height );
01431 #if defined(HAVE_SWSCALE)
01432 sws_scale( imgConvertEncoderCtx, input->data, input->linesize, 0, height,
01433 output->data, output->linesize);
01434 #else
01435 img_convert( ( AVPicture* )output, avcodecEncoder->pix_fmt, ( AVPicture* )input, PIX_FMT_RGB24, width, height );
01436 #endif
01437
01438
01439 bytesInFrame = avcodec_encode_video( avcodecEncoder, avpacketEncoder.data, size, output );
01440 url_open_buf( &avformatEncoder->pb, data, bytesInFrame, URL_WRONLY );
01441 avpacketEncoder.size = bytesInFrame;
01442 if ( !isEncoderHeaderWritten )
01443 {
01444 av_write_header( avformatEncoder );
01445 isEncoderHeaderWritten = true;
01446 }
01447 av_write_frame( avformatEncoder, &avpacketEncoder );
01448 url_close_buf( &avformatEncoder->pb );
01449
01450
01451 ExtractHeader();
01452
01453
01454 data[4] &= 0xf8;
01455
01456 av_free( output );
01457 av_free( input );
01458 }
01459 #else
01460 if ( Preferences::getInstance().dvTwoPassEncoder )
01461 {
01462 dv_encode_full_frame( encoder, &rgb, e_dv_color_rgb, data );
01463 decoder->quality = DV_QUALITY_BEST;
01464 ExtractHeader( );
01465 ExtractRGB( tempImage );
01466 int size = GetWidth( ) * GetHeight( ) * 3;
01467 for ( int i = 0; i < size; i ++ )
01468 rgb[ i ] = std::min( std::max( ( int ) rgb[ i ] - ( ( int ) tempImage[ i ] - ( int ) rgb[ i ] ), 0 ), 255 );
01469 dv_encode_full_frame( encoder, &rgb, e_dv_color_rgb, data );
01470 SetPreferredQuality();
01471 ExtractHeader();
01472 }
01473 else
01474 {
01475 dv_encode_full_frame( encoder, &rgb, e_dv_color_rgb, data );
01476 }
01477 #endif
01478 }
01479 }
01480
01481 #endif
01482
01483 class KinoFramePool : public FramePool
01484 {
01485 private:
01486
01487 deque < Frame* > frames;
01488
01489 public:
01490 KinoFramePool( )
01491 {}
01492
01493 virtual ~KinoFramePool( )
01494 {
01495 for ( int i = frames.size( ); i > 0; --i )
01496 {
01497 Frame *frame = frames[ 0 ];
01498 frames.pop_front( );
01499 delete frame;
01500 }
01501 }
01502
01503 Frame *GetFrame( )
01504 {
01505 Frame * frame;
01506 if ( frames.begin() == frames.end() )
01507 {
01508 frame = new Frame( );
01509 }
01510 else
01511 {
01512 frame = frames[ 0 ];
01513 frames.pop_front( );
01514 }
01515 frame->SetPreferredQuality( );
01516 return frame;
01517 }
01518
01519 void DoneWithFrame( Frame *frame )
01520 {
01521 frames.push_back( frame );
01522 }
01523 };
01524
01525 FramePool *GetFramePool( )
01526 {
01527 static KinoFramePool * pool = new KinoFramePool( );
01528 return pool;
01529 }