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 <string>
00026 #include <iostream>
00027 #include <sstream>
00028 #include <iomanip>
00029
00030 using std::cerr;
00031 using std::endl;
00032 using std::ostringstream;
00033 using std::setw;
00034 using std::setfill;
00035
00036 #include <signal.h>
00037 #include <unistd.h>
00038 #include <fcntl.h>
00039 #include <sys/stat.h>
00040 #include <assert.h>
00041 #include <time.h>
00042 #include <sys/time.h>
00043
00044 #include "filehandler.h"
00045 #include "error.h"
00046 #include "riff.h"
00047 #include "avi.h"
00048 #include "frame.h"
00049
00050 FileTracker *FileTracker::instance = NULL;
00051
00052 FileTracker::FileTracker( ) : mode( CAPTURE_MOVIE_APPEND )
00053 {
00054 cerr << ">> Constructing File Capture tracker" << endl;
00055 }
00056
00057 FileTracker::~FileTracker( )
00058 {
00059 cerr << ">> Destroying File Capture tracker" << endl;
00060 }
00061
00062 FileTracker &FileTracker::GetInstance( )
00063 {
00064 if ( instance == NULL )
00065 instance = new FileTracker();
00066
00067 return *instance;
00068 }
00069
00070 void FileTracker::SetMode( FileCaptureMode mode )
00071 {
00072 this->mode = mode;
00073 }
00074
00075 FileCaptureMode FileTracker::GetMode( )
00076 {
00077 return this->mode;
00078 }
00079
00080 char *FileTracker::Get( int index )
00081 {
00082 return list[ index ];
00083 }
00084
00085 void FileTracker::Add( const char *file )
00086 {
00087 if ( this->mode != CAPTURE_IGNORE )
00088 {
00089 cerr << ">>>> Registering " << file << " with the tracker" << endl;
00090 list.push_back( strdup( file ) );
00091 }
00092 }
00093
00094 unsigned int FileTracker::Size( )
00095 {
00096 return list.size();
00097 }
00098
00099 void FileTracker::Clear( )
00100 {
00101 while ( Size() > 0 )
00102 {
00103 free( list[ Size() - 1 ] );
00104 list.pop_back( );
00105 }
00106 this->mode = CAPTURE_MOVIE_APPEND;
00107 }
00108
00109 FileHandler::FileHandler() : done( false ), autoSplit( false ), maxFrameCount( 999999 ),
00110 framesWritten( 0 ), filename( "" )
00111 {
00112
00113 }
00114
00115
00116 FileHandler::~FileHandler()
00117 {
00118
00119 }
00120
00121
00122 bool FileHandler::GetAutoSplit() const
00123 {
00124 return autoSplit;
00125 }
00126
00127
00128 bool FileHandler::GetTimeStamp() const
00129 {
00130 return timeStamp;
00131 }
00132
00133
00134 string FileHandler::GetBaseName() const
00135 {
00136 return base;
00137 }
00138
00139
00140 string FileHandler::GetExtension() const
00141 {
00142 return extension;
00143 }
00144
00145
00146 int FileHandler::GetMaxFrameCount() const
00147 {
00148 return maxFrameCount;
00149 }
00150
00151 off_t FileHandler::GetMaxFileSize() const
00152 {
00153 return maxFileSize;
00154 }
00155
00156 string FileHandler::GetFilename() const
00157 {
00158 return filename;
00159 }
00160
00161
00162 void FileHandler::SetAutoSplit( bool flag )
00163 {
00164 autoSplit = flag;
00165 }
00166
00167
00168 void FileHandler::SetTimeStamp( bool flag )
00169 {
00170 timeStamp = flag;
00171 }
00172
00173
00174 void FileHandler::SetBaseName( const string& s )
00175 {
00176 base = s;
00177 }
00178
00179
00180 void FileHandler::SetMaxFrameCount( int count )
00181 {
00182 assert( count >= 0 );
00183 maxFrameCount = count;
00184 }
00185
00186
00187 void FileHandler::SetEveryNthFrame( int every )
00188 {
00189 assert ( every > 0 );
00190
00191 everyNthFrame = every;
00192 }
00193
00194
00195 void FileHandler::SetMaxFileSize( off_t size )
00196 {
00197 assert ( size >= 0 );
00198 maxFileSize = size;
00199 }
00200
00201
00202 void FileHandler::SetSampleFrame( const Frame& sample )
00203 {
00204
00205 }
00206
00207
00208 bool FileHandler::Done()
00209 {
00210 return done;
00211 }
00212
00213
00214 bool FileHandler::WriteFrame( const Frame& frame )
00215 {
00216 static TimeCode prevTimeCode = { 0, 0, -1, 0 };
00217 TimeCode timeCode;
00218
00219
00220
00221 frame.GetTimeCode( timeCode );
00222 int time_diff = timeCode.sec - prevTimeCode.sec;
00223 bool discontinuity = prevTimeCode.sec != -1 && ( time_diff > 1 || ( time_diff < 0 && time_diff > -59 ) );
00224 if ( FileIsOpen() && GetAutoSplit() == true && ( frame.IsNewRecording() || discontinuity ) )
00225 {
00226 Close();
00227 }
00228
00229 if ( FileIsOpen() == false )
00230 {
00231
00232 string filename;
00233 static int counter = 0;
00234
00235 if ( GetTimeStamp() == true )
00236 {
00237 ostringstream sb, sb2;
00238 struct tm date;
00239 string recDate;
00240
00241 if ( ! frame.GetRecordingDate( date ) )
00242 {
00243 struct timeval tv;
00244 struct timezone tz;
00245 gettimeofday( &tv, &tz );
00246 localtime_r( static_cast< const time_t * >( &tv.tv_sec ), &date );
00247 }
00248 sb << setfill( '0' )
00249 << setw( 4 ) << date.tm_year + 1900 << '.'
00250 << setw( 2 ) << date.tm_mon + 1 << '.'
00251 << setw( 2 ) << date.tm_mday << '_'
00252 << setw( 2 ) << date.tm_hour << '-'
00253 << setw( 2 ) << date.tm_min << '-'
00254 << setw( 2 ) << date.tm_sec;
00255 recDate = sb.str();
00256 sb2 << GetBaseName() << recDate << GetExtension();
00257 filename = sb2.str();
00258 cerr << ">>> Trying " << filename << endl;
00259 }
00260 else
00261 {
00262 struct stat stats;
00263 do
00264 {
00265 ostringstream sb;
00266 sb << GetBaseName() << setfill( '0' ) << setw( 3 ) << ++ counter << GetExtension();
00267 filename = sb.str();
00268 cerr << ">>> Trying " << filename << endl;
00269 }
00270 while ( stat( filename.c_str(), &stats ) == 0 );
00271 }
00272
00273 SetSampleFrame( frame );
00274 if ( Create( filename ) == false )
00275 {
00276 cerr << ">>> Error creating file!" << endl;
00277 return false;
00278 }
00279 framesWritten = 0;
00280 framesToSkip = 0;
00281 }
00282
00283
00284
00285 if ( framesToSkip == 0 )
00286 {
00287 if ( 0 > Write( frame ) )
00288 {
00289 cerr << ">>> Error writing frame!" << endl;
00290 return false;
00291 }
00292 framesToSkip = everyNthFrame;
00293 ++framesWritten;
00294 }
00295 framesToSkip--;
00296
00297
00298
00299
00300
00301 if ( ( GetMaxFrameCount() > 0 ) &&
00302 ( framesWritten >= GetMaxFrameCount() ) )
00303 {
00304 Close();
00305 done = !GetAutoSplit();
00306 }
00307
00308
00309
00310
00311
00312 if ( FileIsOpen() )
00313 {
00314 AudioInfo info;
00315 frame.GetAudioInfo( info );
00316 if ( ( GetFileSize() > 0 ) && ( GetMaxFileSize() > 0 ) &&
00317 ( GetFileSize() + frame.GetFrameSize() + info.samples * 4 + 12 )
00318 >= GetMaxFileSize() )
00319 {
00320 Close();
00321 done = !GetAutoSplit();
00322 }
00323 }
00324 prevTimeCode.sec = timeCode.sec;
00325 return true;
00326 }
00327
00328
00329 RawHandler::RawHandler() : fd( -1 )
00330 {
00331 extension = ".dv";
00332 }
00333
00334
00335 RawHandler::~RawHandler()
00336 {
00337 Close();
00338 }
00339
00340
00341 bool RawHandler::FileIsOpen()
00342 {
00343 return fd != -1;
00344 }
00345
00346
00347 bool RawHandler::Create( const string& filename )
00348 {
00349 fd = open( filename.c_str(), O_CREAT | O_TRUNC | O_RDWR | O_NONBLOCK, 0644 );
00350 if ( fd != -1 )
00351 {
00352 FileTracker::GetInstance().Add( filename.c_str() );
00353 this->filename = filename;
00354 }
00355 return ( fd != -1 );
00356 }
00357
00358
00359 int RawHandler::Write( const Frame& frame )
00360 {
00361 int result = write( fd, frame.data, frame.GetFrameSize() );
00362 return result;
00363 }
00364
00365
00366 int RawHandler::Close()
00367 {
00368 if ( fd != -1 )
00369 {
00370 close( fd );
00371 fd = -1;
00372 }
00373 return 0;
00374 }
00375
00376
00377 off_t RawHandler::GetFileSize()
00378 {
00379 struct stat file_status;
00380 fstat( fd, &file_status );
00381 return file_status.st_size;
00382 }
00383
00384 int RawHandler::GetTotalFrames()
00385 {
00386 return GetFileSize() / ( 480 * numBlocks );
00387 }
00388
00389
00390 bool RawHandler::Open( const char *s )
00391 {
00392 unsigned char data[ 4 ];
00393 assert( fd == -1 );
00394 fd = open( s, O_RDONLY | O_NONBLOCK );
00395 if ( fd < 0 )
00396 return false;
00397 if ( read( fd, data, 4 ) < 0 )
00398 return false;
00399 lseek( fd, 0, SEEK_SET );
00400 numBlocks = ( ( data[ 3 ] & 0x80 ) == 0 ) ? 250 : 300;
00401 filename = s;
00402 return true;
00403
00404 }
00405
00406 int RawHandler::GetFrame( Frame &frame, int frameNum )
00407 {
00408 assert( fd != -1 );
00409 int size = 480 * numBlocks;
00410 if ( frameNum < 0 )
00411 return -1;
00412 off_t offset = ( ( off_t ) frameNum * ( off_t ) size );
00413 fail_if( lseek( fd, offset, SEEK_SET ) == ( off_t ) - 1 );
00414 if ( read( fd, frame.data, size ) > 0 )
00415 {
00416 frame.ExtractHeader();
00417 return 0;
00418 }
00419 else
00420 return -1;
00421 }
00422
00423
00424
00425
00426 #define AVI_AUDIO_BUFFER_SECS (2)
00427
00428 AVIHandler::AVIHandler( int format ) : avi( NULL ), aviFormat( format ), isOpenDML( false ),
00429 fccHandler( make_fourcc( "dvsd" ) ), channels( 2 ), isFullyInitialized( false ),
00430 audioBuffer( NULL ), isInterleave1to1( true )
00431 {
00432 extension = ".avi";
00433 for ( int c = 0; c < 4; c++ )
00434 audioChannels[ c ] = NULL;
00435 }
00436
00437
00438 AVIHandler::~AVIHandler()
00439 {
00440 if ( audioBuffer != NULL )
00441 {
00442 delete[] audioBuffer;
00443 audioBuffer = NULL;
00444 }
00445 for ( int c = 0; c < 4; c++ )
00446 {
00447 if ( audioChannels[ c ] != NULL )
00448 {
00449 delete[] audioChannels[ c ];
00450 audioChannels[ c ] = NULL;
00451 }
00452 }
00453
00454 delete avi;
00455 }
00456
00457 void AVIHandler::SetSampleFrame( const Frame& sample )
00458 {
00459 Pack pack;
00460 sample.GetAudioInfo( audioInfo );
00461 sample.GetVideoInfo( videoInfo );
00462
00463 sample.GetAAUXPack( 0x50, pack );
00464 dvinfo.dwDVAAuxSrc = *( DWORD* ) ( pack.data + 1 );
00465 sample.GetAAUXPack( 0x51, pack );
00466 dvinfo.dwDVAAuxCtl = *( DWORD* ) ( pack.data + 1 );
00467
00468 sample.GetAAUXPack( 0x52, pack );
00469 dvinfo.dwDVAAuxSrc1 = *( DWORD* ) ( pack.data + 1 );
00470 sample.GetAAUXPack( 0x53, pack );
00471 dvinfo.dwDVAAuxCtl1 = *( DWORD* ) ( pack.data + 1 );
00472
00473 sample.GetVAUXPack( 0x60, pack );
00474 dvinfo.dwDVVAuxSrc = *( DWORD* ) ( pack.data + 1 );
00475 sample.GetVAUXPack( 0x61, pack );
00476 dvinfo.dwDVVAuxCtl = *( DWORD* ) ( pack.data + 1 );
00477
00478 #ifdef HAVE_LIBDV
00479 if ( sample.decoder->std == e_dv_std_smpte_314m )
00480 fccHandler = make_fourcc( "dv25" );
00481 #endif
00482 }
00483
00484
00485 bool AVIHandler::FileIsOpen()
00486 {
00487 return avi != NULL;
00488 }
00489
00490
00491 bool AVIHandler::Create( const string& filename )
00492 {
00493 assert( avi == NULL );
00494
00495 switch ( aviFormat )
00496 {
00497
00498 case AVI_DV1_FORMAT:
00499 fail_null( avi = new AVI1File );
00500 if ( avi->Create( filename.c_str() ) == false )
00501 return false;
00502 avi->Init( videoInfo.isPAL ? AVI_PAL : AVI_NTSC, audioInfo.frequency,
00503 AVI_LARGE_INDEX );
00504 break;
00505
00506 case AVI_DV2_FORMAT:
00507 fail_null( avi = new AVI2File );
00508 if ( avi->Create( filename.c_str() ) == false )
00509 return false;
00510 if ( GetOpenDML() )
00511 avi->Init( videoInfo.isPAL ? AVI_PAL : AVI_NTSC, audioInfo.frequency,
00512 ( AVI_SMALL_INDEX | AVI_LARGE_INDEX ) );
00513 else
00514 avi->Init( videoInfo.isPAL ? AVI_PAL : AVI_NTSC, audioInfo.frequency,
00515 ( AVI_SMALL_INDEX ) );
00516 break;
00517
00518 default:
00519 assert( aviFormat == AVI_DV1_FORMAT || aviFormat == AVI_DV2_FORMAT );
00520 }
00521
00522 avi->setDVINFO( dvinfo );
00523 avi->setFccHandler( make_fourcc( "iavs" ), fccHandler );
00524 avi->setFccHandler( make_fourcc( "vids" ), fccHandler );
00525 this->filename = filename;
00526 FileTracker::GetInstance().Add( filename.c_str() );
00527 return ( avi != NULL );
00528 }
00529
00530
00531 int AVIHandler::Write( const Frame& frame )
00532 {
00533 assert( avi != NULL );
00534 try
00535 {
00536 return avi->WriteFrame( frame ) ? 0 : -1;
00537 }
00538 catch (...)
00539 {
00540 return -1;
00541 }
00542 }
00543
00544
00545 int AVIHandler::Close()
00546 {
00547 if ( avi != NULL )
00548 {
00549 avi->WriteRIFF();
00550 delete avi;
00551 avi = NULL;
00552 }
00553 if ( audioBuffer != NULL )
00554 {
00555 delete audioBuffer;
00556 audioBuffer = NULL;
00557 }
00558 for ( int c = 0; c < 4; c++ )
00559 {
00560 if ( audioChannels[ c ] != NULL )
00561 {
00562 delete audioChannels[ c ];
00563 audioChannels[ c ] = NULL;
00564 }
00565 }
00566 isFullyInitialized = false;
00567 return 0;
00568 }
00569
00570 off_t AVIHandler::GetFileSize()
00571 {
00572 return avi->GetFileSize();
00573 }
00574
00575 int AVIHandler::GetTotalFrames()
00576 {
00577 return avi->GetTotalFrames();
00578 }
00579
00580
00581 bool AVIHandler::Open( const char *s )
00582 {
00583 assert( avi == NULL );
00584 fail_null( avi = new AVI1File );
00585 if ( avi->Open( s ) )
00586 {
00587 avi->ParseRIFF();
00588 if ( ! (
00589 avi->verifyStreamFormat( make_fourcc( "dvsd" ) ) ||
00590 avi->verifyStreamFormat( make_fourcc( "DVSD" ) ) ||
00591 avi->verifyStreamFormat( make_fourcc( "dvcs" ) ) ||
00592 avi->verifyStreamFormat( make_fourcc( "DVCS" ) ) ||
00593 avi->verifyStreamFormat( make_fourcc( "dvcp" ) ) ||
00594 avi->verifyStreamFormat( make_fourcc( "DVCP" ) ) ||
00595 avi->verifyStreamFormat( make_fourcc( "CDVC" ) ) ||
00596 avi->verifyStreamFormat( make_fourcc( "cdvc" ) ) ||
00597 avi->verifyStreamFormat( make_fourcc( "DV25" ) ) ||
00598 avi->verifyStreamFormat( make_fourcc( "dv25" ) ) ) )
00599 return false;
00600 avi->ReadIndex();
00601 if ( avi->verifyStream( make_fourcc( "auds" ) ) )
00602 {
00603 aviFormat = AVI_DV2_FORMAT;
00604 isInterleave1to1 = avi->isInterleave1to1();
00605 }
00606 else
00607 {
00608 aviFormat = AVI_DV1_FORMAT;
00609 }
00610 isOpenDML = avi->isOpenDML();
00611 filename = s;
00612 return true;
00613 }
00614 else
00615 return false;
00616
00617 }
00618
00619 int AVIHandler::GetFrame( Frame &frame, int frameNum )
00620 {
00621 int result = avi->GetDVFrame( frame, frameNum );
00622 if ( result == 0 )
00623 {
00624
00625 if ( aviFormat == AVI_DV2_FORMAT )
00626 {
00627 WAVEFORMATEX wav;
00628 FOURCC fccWav = make_fourcc( "01wb" );
00629
00630 if ( ! isFullyInitialized &&
00631 avi->getStreamFormat( ( void* ) &wav, make_fourcc( "auds" ) ) )
00632 {
00633 if ( channels > 0 && channels < 5 )
00634 {
00635
00636 audioBuffer = new int16_t[ wav.nSamplesPerSec * channels * AVI_AUDIO_BUFFER_SECS ];
00637
00638
00639 for ( int c = 0; c < channels; c++ )
00640 audioChannels[ c ] = new int16_t[ 2 * DV_AUDIO_MAX_SAMPLES ];
00641
00642
00643 audioInfo.channels = wav.nChannels;
00644 audioInfo.frequency = wav.nSamplesPerSec;
00645
00646
00647 isFullyInitialized = true;
00648 cerr << ">>> using audio from separate AVI audio stream" << endl;
00649 }
00650 }
00651
00652
00653 if ( isInterleave1to1 )
00654 {
00655 int n = avi->getFrame( audioBuffer, frameNum, fccWav );
00656 if ( n > 0 )
00657 {
00658
00659 int16_t * s = audioBuffer;
00660
00661
00662 audioInfo.samples = n / audioInfo.channels / sizeof( int16_t );
00663 if ( audioInfo.samples > DV_AUDIO_MAX_SAMPLES )
00664 audioInfo.samples = DV_AUDIO_MAX_SAMPLES;
00665
00666
00667 for ( int n = 0; n < audioInfo.samples; ++n )
00668 for ( int i = 0; i < audioInfo.channels; i++ )
00669 audioChannels[ i ][ n ] = *s++;
00670 }
00671 }
00672 else
00673 {
00674 int16_t* s;
00675 int availSamples = 0;
00676
00677
00678 if ( ( s = SeekAudioFrame( frame, frameNum, availSamples ) ) )
00679 {
00680 if ( availSamples < audioInfo.samples )
00681 {
00682
00683 int n;
00684
00685
00686 for ( n = 0; n < availSamples; ++n )
00687 for ( int i = 0; i < audioInfo.channels; i++ )
00688 audioChannels[ i ][ n ] = *s++;
00689
00690
00691 if ( ( s = SeekAudioFrame( frame, frameNum + 1, availSamples ) ) )
00692 {
00693
00694 for ( --n; n < audioInfo.samples; ++n )
00695 for ( int i = 0; i < audioInfo.channels; i++ )
00696 audioChannels[ i ][ n ] = *s++;
00697 }
00698 else if ( availSamples >= 0 )
00699 {
00700
00701 audioInfo.samples = availSamples;
00702 }
00703 }
00704 else
00705 {
00706
00707 for ( int n = 0; n < audioInfo.samples; ++n )
00708 for ( int i = 0; i < audioInfo.channels; i++ )
00709 audioChannels[ i ][ n ] = *s++;
00710 }
00711 }
00712
00713 if ( availSamples < 0 )
00714 return result;
00715 }
00716
00717 frame.EncodeAudio( audioInfo, audioChannels );
00718 }
00719
00720 frame.ExtractHeader();
00721 }
00722 return result;
00723 }
00724
00725
00726 int16_t* AVIHandler::SeekAudioFrame( Frame& frame, int frameNum, int& availableSize )
00727 {
00728
00729 FOURCC fccWav = make_fourcc( "01wb" );
00730 frame.ExtractHeader();
00731 off_t offsetBytes = off_t( 0.5 + (float) frameNum / frame.GetFrameRate() * audioInfo.frequency );
00732 offsetBytes *= audioInfo.channels * sizeof(int16_t);
00733
00734
00735 if ( offsetBytes < audioOffset || offsetBytes >= ( audioOffset + audioBufferSize ) )
00736 {
00737 int i = 0;
00738 off_t dummy;
00739
00740
00741 for ( audioOffset = 0; avi->GetFrameInfo( dummy, audioBufferSize, i, fccWav ) != -1; ++i )
00742 {
00743 if ( audioBufferSize <= 0 )
00744 {
00745 availableSize = -1;
00746 return 0;
00747 }
00748 if ( audioOffset + audioBufferSize > offsetBytes )
00749 break;
00750 audioOffset += audioBufferSize;
00751 }
00752
00753 if ( audioBufferSize > ( off_t( audioInfo.frequency ) * audioInfo.channels * sizeof(int16_t) * AVI_AUDIO_BUFFER_SECS ) ||
00754 !avi->getFrame( audioBuffer, i, fccWav ) )
00755 {
00756 return 0;
00757 }
00758 }
00759
00760 availableSize = ( audioBufferSize - int( offsetBytes - audioOffset ) ) >> 2;
00761
00762 audioInfo.samples = frame.CalculateNumberSamples( audioInfo.frequency, frameNum );
00763
00764 return audioBuffer + ( ( offsetBytes - audioOffset ) >> 1 );
00765 }
00766
00767
00768 void AVIHandler::SetOpenDML( bool flag )
00769 {
00770 isOpenDML = flag;
00771 }
00772
00773
00774 bool AVIHandler::GetOpenDML() const
00775 {
00776 return isOpenDML;
00777 }
00778
00779
00780
00781
00782 #ifdef HAVE_LIBQUICKTIME
00783
00784 QtHandler::QtHandler() : fd( NULL )
00785 {
00786 extension = ".mov";
00787 Init();
00788 }
00789
00790
00791 QtHandler::~QtHandler()
00792 {
00793 Close();
00794 }
00795
00796 void QtHandler::Init()
00797 {
00798 if ( fd != NULL )
00799 Close();
00800
00801 fd = NULL;
00802 samplingRate = 48000;
00803 samplesPerBuffer = 0;
00804 channels = 2;
00805 audioBuffer = NULL;
00806 audioChannelBuffer = NULL;
00807 isFullyInitialized = false;
00808 }
00809
00810
00811 bool QtHandler::FileIsOpen()
00812 {
00813 return fd != NULL;
00814 }
00815
00816
00817 bool QtHandler::Create( const string& filename )
00818 {
00819 Init();
00820
00821 if ( open( filename.c_str(), O_CREAT | O_TRUNC | O_RDWR | O_NONBLOCK, 0644 ) != -1 )
00822 {
00823 fd = quicktime_open( const_cast<char*>( filename.c_str() ), 0, 1 );
00824 if ( fd != NULL )
00825 FileTracker::GetInstance().Add( filename.c_str() );
00826 }
00827 else
00828 return false;
00829 this->filename = filename;
00830 return true;
00831 }
00832
00833 void QtHandler::AllocateAudioBuffers()
00834 {
00835 if ( channels > 0 && channels < 5 )
00836 {
00837 audioBufferSize = DV_AUDIO_MAX_SAMPLES * 2;
00838 audioBuffer = new int16_t[ audioBufferSize * channels ];
00839
00840 audioChannelBuffer = new short int * [ channels ];
00841 for ( int c = 0; c < channels; c++ )
00842 audioChannelBuffer[ c ] = new short int[ audioBufferSize ];
00843 isFullyInitialized = true;
00844 }
00845 }
00846
00847 inline void QtHandler::DeinterlaceStereo16( void* pInput, int iBytes,
00848 void* pLOutput, void* pROutput )
00849 {
00850 short int * piSampleInput = ( short int* ) pInput;
00851 short int* piSampleLOutput = ( short int* ) pLOutput;
00852 short int* piSampleROutput = ( short int* ) pROutput;
00853
00854 while ( ( char* ) piSampleInput < ( ( char* ) pInput + iBytes ) )
00855 {
00856 *piSampleLOutput++ = *piSampleInput++;
00857 *piSampleROutput++ = *piSampleInput++;
00858 }
00859 }
00860
00861 int QtHandler::Write( const Frame& frame )
00862 {
00863 if ( ! isFullyInitialized )
00864 {
00865 AudioInfo audio;
00866 const char* fourcc = frame.IsPAL() ? "dvcp" : QUICKTIME_DV;
00867
00868 if ( frame.GetAudioInfo( audio ) )
00869 {
00870 channels = 2;
00871 samplingRate = audio.frequency;
00872 quicktime_set_audio( fd, channels, audio.frequency, 16, QUICKTIME_TWOS );
00873 }
00874 else
00875 {
00876 channels = 0;
00877 }
00878
00879 quicktime_set_video( fd, 1, 720, frame.IsPAL() ? 576 : 480,
00880 frame.GetFrameRate(), const_cast<char*>( fourcc ) );
00881 AllocateAudioBuffers();
00882 }
00883
00884 int result = quicktime_write_frame( fd, const_cast<unsigned char*>( frame.data ),
00885 frame.GetFrameSize(), 0 );
00886
00887 if ( channels > 0 )
00888 {
00889 AudioInfo audio;
00890 if ( frame.GetAudioInfo( audio ) && ( unsigned int ) audio.samples < audioBufferSize )
00891 {
00892 long bytesRead = frame.ExtractAudio( audioBuffer );
00893
00894 if ( bytesRead )
00895 {
00896 DeinterlaceStereo16( audioBuffer, bytesRead,
00897 audioChannelBuffer[ 0 ],
00898 audioChannelBuffer[ 1 ] );
00899 }
00900 else
00901 {
00902
00903
00904 audio.samples = int( (float)samplingRate / frame.GetFrameRate() );
00905 memset( audioChannelBuffer[0], 0, audio.samples * sizeof(int16_t) );
00906 memset( audioChannelBuffer[1], 0, audio.samples * sizeof(int16_t) );
00907 }
00908 quicktime_encode_audio( fd, audioChannelBuffer, NULL, audio.samples );
00909 }
00910 }
00911 return result;
00912 }
00913
00914
00915 int QtHandler::Close()
00916 {
00917 if ( fd != NULL )
00918 {
00919 quicktime_close( fd );
00920 fd = NULL;
00921 }
00922 if ( audioBuffer != NULL )
00923 {
00924 delete[] audioBuffer;
00925 audioBuffer = NULL;
00926 }
00927 if ( audioChannelBuffer != NULL )
00928 {
00929 for ( int c = 0; c < channels; c++ )
00930 delete[] audioChannelBuffer[ c ];
00931 delete[] audioChannelBuffer;
00932 audioChannelBuffer = NULL;
00933 }
00934 return 0;
00935 }
00936
00937
00938 off_t QtHandler::GetFileSize()
00939 {
00940 struct stat file_status;
00941 stat( filename.c_str(), &file_status );
00942 return file_status.st_size;
00943 }
00944
00945
00946 int QtHandler::GetTotalFrames()
00947 {
00948 return ( int ) quicktime_video_length( fd, 0 );
00949 }
00950
00951
00952 bool QtHandler::Open( const char *s )
00953 {
00954 Init();
00955
00956 fd = quicktime_open( ( char * ) s, 1, 0 );
00957 if ( fd == NULL )
00958 {
00959 fprintf( stderr, "Error opening: %s\n", s );
00960 return false;
00961 }
00962
00963 if ( quicktime_has_video( fd ) <= 0 )
00964 {
00965 fprintf( stderr, "There must be at least one video track in the input file (%s).\n",
00966 s );
00967 Close();
00968 return false;
00969 }
00970 const char* fourcc = quicktime_video_compressor( fd, 0 );
00971 if ( strncmp( fourcc, QUICKTIME_DV, 4 ) != 0 &&
00972 strncmp( fourcc, "dv25", 4 ) != 0 &&
00973 strncmp( fourcc, "dvsd", 4 ) != 0 &&
00974 strncmp( fourcc, "dvcp", 4 ) != 0 &&
00975 strncmp( fourcc, "AVdv", 4 ) != 0 )
00976 {
00977 fprintf( stderr, "Video in input file (%s) must be in DV format.\n", s );
00978 Close();
00979 return false;
00980 }
00981 if ( quicktime_has_audio( fd ) )
00982 channels = quicktime_track_channels( fd, 0 );
00983 filename = s;
00984 return true;
00985 }
00986
00987 int QtHandler::GetFrame( Frame &frame, int frameNum )
00988 {
00989 assert( fd != NULL );
00990
00991 quicktime_set_video_position( fd, frameNum, 0 );
00992 frame.bytesInFrame = quicktime_read_frame( fd, frame.data, 0 );
00993
00994 if ( quicktime_has_audio( fd ) )
00995 {
00996 AudioInfo info;
00997 double samples;
00998
00999 if ( ! isFullyInitialized )
01000 {
01001 cerr << ">>> using audio from separarate Quicktime audio track" << endl;
01002 AllocateAudioBuffers();
01003 }
01004
01005 info.channels = channels;
01006 info.frequency = quicktime_sample_rate( fd, 0 );
01007 samples = info.frequency / quicktime_frame_rate( fd, 0 );
01008 info.samples = (int) samples;
01009 for ( int i = 0; i < channels; i++ )
01010 {
01011 quicktime_set_audio_position( fd, ( int64_t )( frameNum * samples ), 0 );
01012 quicktime_decode_audio( fd, audioChannelBuffer[ i ], NULL, (long) samples, i );
01013 }
01014 frame.EncodeAudio( info, audioChannelBuffer );
01015 }
01016 frame.ExtractHeader();
01017 return 0;
01018 }
01019 #endif