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

frame.cc

Go to the documentation of this file.
00001 /*
00002 * frame.cc -- utilities for processing digital video frames
00003 * Copyright (C) 2000 Arne Schirmacher <arne@schirmacher.de>
00004 * Copyright (C) 2001-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 
00029 #ifdef HAVE_CONFIG_H
00030 #include <config.h>
00031 #endif
00032 
00033 // C++ includes
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 // C includes
00051 
00052 #include <pthread.h>
00053 #include <math.h>
00054 
00055 // local includes
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 // Static globals for encoder, not accessed by more than one thread
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 /*  if ( avformatEncoder )
00189     {
00190         av_write_trailer( avformatEncoder );
00191         av_destruct_packet( &avpacketEncoder );
00192         avcodec_close( avformatEncoder->streams[0]->codec );
00193         av_free( avformatEncoder->streams[0]->codec );
00194         av_free( avformatEncoder->streams[0] );
00195         av_free( avformatEncoder );
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     /* number of DIF sequences is different for PAL and NTSC */
00247 
00248     int seqCount = IsPAL() ? 12 : 10;
00249 
00250     /* process all DIF sequences */
00251 
00252     for ( int i = 0; i < seqCount; ++i )
00253     {
00254 
00255         /* there are two DIF blocks in the subcode section */
00256 
00257         for ( int j = 0; j < 2; ++j )
00258         {
00259 
00260             /* each block has 6 packets */
00261 
00262             for ( int k = 0; k < 6; ++k )
00263             {
00264 
00265                 /* calculate address: 150 DIF blocks per sequence, 80 bytes
00266                 per DIF block, subcode blocks start at block 1, block and
00267                 packet have 3 bytes header, packet is 8 bytes long
00268                 (including header) */
00269 
00270                 const unsigned char *s = &data[ i * 150 * 80 + 1 * 80 + j * 80 + 3 + k * 8 + 3 ];
00271                 // printf("ssyb %d: %2.2x %2.2x %2.2x %2.2x %2.2x\n",
00272                 // j * 6 + k, s[0], s[1], s[2], s[3], s[4]);
00273                 if ( s[ 0 ] == packNum )
00274                 {
00275                     //                  printf("GetSSYBPack[%x]: sequence %d, block %d, packet %d\n", packNum,i,j,k);
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     //cerr << "VAUX: 0x"
00308     //<< setw(2) << setfill('0') << hex << (int) pack.data[0]
00309     //<< setw(2) << setfill('0') << hex << (int) pack.data[1]
00310     //<< setw(2) << setfill('0') << hex << (int) pack.data[2]
00311     //<< setw(2) << setfill('0') << hex << (int) pack.data[3]
00312     //<< setw(2) << setfill('0') << hex << (int) pack.data[4]
00313     //<< endl;
00314     return true;
00315 
00316 #else
00317     /* number of DIF sequences is different for PAL and NTSC */
00318 
00319     int seqCount = IsPAL() ? 12 : 10;
00320 
00321     /* process all DIF sequences */
00322 
00323     for ( int i = 0; i < seqCount; ++i )
00324     {
00325 
00326         /* there are three DIF blocks in the VAUX section */
00327 
00328         for ( int j = 0; j < 3; ++j )
00329         {
00330 
00331             /* each block has 15 packets */
00332 
00333             for ( int k = 0; k < 15; ++k )
00334             {
00335 
00336                 /* calculate address: 150 DIF blocks per sequence, 80 bytes
00337                 per DIF block, vaux blocks start at block 3, block has 3
00338                 bytes header, packets have no header and are 5 bytes
00339                 long. */
00340 
00341                 const unsigned char *s = &data[ i * 150 * 80 + 3 * 80 + j * 80 + 3 + k * 5 ];
00342                 //printf("vaux %d: %2.2x %2.2x %2.2x %2.2x %2.2x\n",
00343                 //  j * 15 + k, s[0],  s[1],  s[2],  s[3],  s[4]);
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     /* number of DIF sequences is different for PAL and NTSC */
00402 
00403     int seqCount = IsPAL() ? 12 : 10;
00404 
00405     /* process all DIF sequences */
00406 
00407     for ( int i = 0; i < seqCount; ++i )
00408     {
00409 
00410         /* there are nine audio DIF blocks */
00411         for ( int j = 0; j < 9; ++j )
00412         {
00413 
00414             /* calculate address: 150 DIF blocks per sequence, 80 bytes
00415                per DIF block, audio blocks start at every 16th beginning
00416                with block 6, block has 3 bytes header, followed by one
00417                packet. */
00418 
00419             const unsigned char *s = &data[ i * 150 * 80 + 6 * 80 + j * 16 * 80 + 3 ];
00420             if ( s[ 0 ] == packNum )
00421             {
00422                 // printf("aaux %d: %2.2x %2.2x %2.2x %2.2x %2.2x\n",
00423                 // j, s[0], s[1], s[2], s[3], s[4]);
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     /* sanity check of the results */
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     /* Check whether this frame has a valid AAUX source packet
00603     (header == 0x50). If so, get the audio samples count. If not,
00604     skip this audio data. */
00605 
00606     if ( GetAAUXPack( 0x50, pack50 ) == true )
00607     {
00608 
00609         /* get size, sampling type and the 50/60 flag. The number of
00610         audio samples is dependend on all of these. */
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         { // 50 frames (PAL)
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; // I don't know
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     /* if we can't find the packet, we return "no new recording" */
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     /* don't do audio if speed is not 1 */
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     /* Collect the audio samples */
00811     char* s = ( char * ) sound;
00812 
00813     GetAudioInfo( info );
00814     switch ( info.frequency )
00815     {
00816     case 32000:
00817 
00818         /* This is 4 channel audio */
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 ]; // LSB
00826                 *p++ = compmap[ ( ( ( unsigned char* ) data ) [ palmap_2ch1[ n ] ] << 4 ) + ( r >> 4 ) ];   // MSB
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 ]; // LSB
00838                 *p++ = compmap[ ( ( ( unsigned char* ) data ) [ ntscmap_2ch1[ n ] ] << 4 ) + ( r >> 4 ) ];   // MSB
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         /* this can be optimized significantly */
00848 
00849         if ( IsPAL() )
00850         {
00851             for ( int n = 0; n < info.samples; ++n )
00852             {
00853                 *s++ = ( ( char* ) data ) [ palmap_ch1[ n ] + 1 ]; /* LSB */
00854                 *s++ = ( ( char* ) data ) [ palmap_ch1[ n ] ];     /* MSB */
00855                 *s++ = ( ( char* ) data ) [ palmap_ch2[ n ] + 1 ]; /* LSB */
00856                 *s++ = ( ( char* ) data ) [ palmap_ch2[ n ] ];     /* MSB */
00857             }
00858         }
00859         else
00860         {
00861             for ( int n = 0; n < info.samples; ++n )
00862             {
00863                 *s++ = ( ( char* ) data ) [ ntscmap_ch1[ n ] + 1 ]; /* LSB */
00864                 *s++ = ( ( char* ) data ) [ ntscmap_ch1[ n ] ];     /* MSB */
00865                 *s++ = ( ( char* ) data ) [ ntscmap_ch2[ n ] + 1 ]; /* LSB */
00866                 *s++ = ( ( char* ) data ) [ ntscmap_ch2[ n ] ];     /* MSB */
00867             }
00868         }
00869         break;
00870 
00871         /* we can't handle any other format in the moment */
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 /* Linear Blend filter - C version contributed by Rogerio Brito.
00901    This algorithm has the same interface as the other functions.
00902 
00903    The destination "screen" (pdst) is constructed from the source
00904    screen (psrc[0]) line by line.
00905 
00906    The i-th line of the destination screen is the average of 3 lines
00907    from the source screen: the (i-1)-th, i-th and (i+1)-th lines, with
00908    the i-th line having weight 2 in the computation.
00909 
00910    Remarks:
00911    * each line on pdst doesn't depend on previous lines;
00912    * due to the way the algorithm is defined, the first & last lines of the
00913      screen aren't deinterlaced.
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;      /* target line */
00922     l1 = psrc;      /* 1st source line */
00923     l2 = l1 + stride;   /* 2nd source line = line that follows l1 */
00924     l3 = l2 + stride;   /* 3rd source line = line that follows l2 */
00925 
00926     /* Copy the first line */
00927     memcpy( l0, l1, stride );
00928     l0 += stride;
00929 
00930     for (y = 1; y < height-1; ++y)
00931     {
00932         /* computes avg of: l1 + 2*l2 + l3 */
00933         for ( x = 0; x < stride; ++x )
00934             l0[x] = ( l1[ x ] + ( l2[ x ] << 1 ) + l3[ x ] ) >> 2;
00935 
00936         /* updates the line pointers */
00937         l1 = l2;
00938         l2 = l3;
00939         l3 += stride;
00940         l0 += stride;
00941     }
00942 
00943     /* Copy the last line */
00944     memcpy( l0, l1, stride );
00945 }
00946 
00947 
00954 bool Frame::IsWide( void ) const
00955 {
00956     // Not using libdv due to libdv bug setting widescreen properly when encoding metadata
00957     // on SMPTE DV as encoded by ffmpeg.
00958     // return dv_format_wide( decoder ) > 0;
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 )   // PAL
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 // libavcodec.pix_fmt == PIX_FMT_YUV411P // NTSC
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         /* process two scanlines (one from each field, interleaved) */
01227         for ( int j = 0; j < w2; j++ )
01228         {
01229             /* packed YUV 422 is: Y[i] U[i] Y[i+1] V[i] */
01230             *( y++ ) = *( p++ );
01231             *( cb++ ) = *( p++ );
01232             *( y++ ) = *( p++ );
01233             *( cr++ ) = *( p++ );
01234         }
01235         /* process next two scanlines (one from each field, interleaved) */
01236         for ( int j = 0; j < w2; j++ )
01237         {
01238             /* skip every second line for U and V */
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             // Convert color space
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             // Encode
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             // Update this frame's metadata
01451             ExtractHeader();
01452 
01453             // Force the output to be IEC 61834
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     // The list of available frames
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 }

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