diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/Ac3Decoder.cpp | 193 | ||||
-rw-r--r-- | core/Ac3Decoder.h | 46 | ||||
-rw-r--r-- | core/AviMuxer.cpp | 8 | ||||
-rw-r--r-- | core/Common.cpp | 70 | ||||
-rw-r--r-- | core/Common.h | 45 | ||||
-rw-r--r-- | core/DVDReader.cpp | 10 | ||||
-rw-r--r-- | core/Fifo.cpp | 5 | ||||
-rw-r--r-- | core/Manager.cpp | 399 | ||||
-rw-r--r-- | core/Manager.h | 11 | ||||
-rw-r--r-- | core/Mp3Encoder.cpp | 172 | ||||
-rw-r--r-- | core/Mp3Encoder.h | 19 | ||||
-rw-r--r-- | core/Mpeg2Decoder.cpp | 119 | ||||
-rw-r--r-- | core/Mpeg2Decoder.h | 13 | ||||
-rw-r--r-- | core/Mpeg4Encoder.cpp | 114 | ||||
-rw-r--r-- | core/Mpeg4Encoder.h | 15 | ||||
-rw-r--r-- | core/MpegDemux.cpp | 230 | ||||
-rw-r--r-- | core/MpegDemux.h | 19 | ||||
-rw-r--r-- | core/Resizer.cpp | 122 | ||||
-rw-r--r-- | core/Resizer.h | 23 | ||||
-rw-r--r-- | core/Scanner.cpp | 66 | ||||
-rw-r--r-- | core/Thread.cpp | 73 | ||||
-rw-r--r-- | core/Thread.h | 11 | ||||
-rw-r--r-- | core/Worker.cpp | 150 | ||||
-rw-r--r-- | core/Worker.h | 27 |
24 files changed, 1246 insertions, 714 deletions
diff --git a/core/Ac3Decoder.cpp b/core/Ac3Decoder.cpp index 12eed05df..95030d810 100644 --- a/core/Ac3Decoder.cpp +++ b/core/Ac3Decoder.cpp @@ -1,4 +1,4 @@ -/* $Id: Ac3Decoder.cpp,v 1.12 2003/09/30 14:38:15 titer Exp $ +/* $Id: Ac3Decoder.cpp,v 1.20 2003/10/13 10:58:24 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -13,101 +13,160 @@ extern "C" { } HBAc3Decoder::HBAc3Decoder( HBManager * manager, HBAudio * audio ) - : HBThread( "ac3decoder" ) { - fManager = manager; - fAudio = audio; + fManager = manager; + fAudio = audio; + fLock = new HBLock(); + fUsed = false; + + /* Init liba52 */ + fState = a52_init( 0 ); + fInFlags = 0; + fOutFlags = A52_STEREO; + + /* Lame wants samples from -32768 to 32768 */ + fSampleLevel = 32768.0; + /* Max size for a A52 frame is 3840 bytes */ - fAc3Frame = new HBBuffer( 3840 ); - fAc3Buffer = NULL; - fPosInBuffer = 0; - fPosition = 0; + fAc3Frame = new HBBuffer( 3840 ); + fAc3Frame->fSize = 0; + fAc3Buffer = NULL; + fPosInBuffer = 0; + fRawBuffer = NULL; } HBAc3Decoder::~HBAc3Decoder() { + if( fRawBuffer ) delete fRawBuffer; + if( fAc3Buffer ) delete fAc3Buffer; delete fAc3Frame; + a52_free( fState ); + delete fLock; } -void HBAc3Decoder::DoWork() +bool HBAc3Decoder::Work() { - /* Init liba52 */ - a52_state_t * state = a52_init( 0 ); - int inFlags = 0; - int outFlags = A52_STEREO; - - /* Lame wants samples from -32768 to 32768 */ - float sampleLevel = 32768; - - int frameSize; - HBBuffer * rawBuffer; - sample_t * samples; - - /* Main loop */ + if( !Lock() ) + { + return false; + } + + bool didSomething = false; + + sample_t * samples; for( ;; ) { - while( fSuspend ) + /* Try to push the latest decoded buffer */ + if( fRawBuffer ) { - Snooze( 10000 ); + if( fAudio->fRawFifo->Push( fRawBuffer ) ) + { + fRawBuffer = NULL; + } + else + { + break; + } } - fAc3Frame->fSize = 0; - - /* Get a frame header (7 bytes) */ - if( !( GetBytes( 7 ) ) ) + /* Get a new frame */ + if( fAc3Frame->fSize < 7 ) { - break; - } - - /* Get the size of the current frame */ - frameSize = a52_syncinfo( fAc3Frame->fData, &inFlags, - &fAudio->fInSampleRate, - &fAudio->fInBitrate ); + /* Get a frame header (7 bytes) */ + if( !( GetBytes( 7 ) ) ) + { + break; + } - if( !frameSize ) - { - Log( "HBAc3Decoder : a52_syncinfo failed" ); - fManager->Error(); - break; + /* Get the size of the current frame */ + fFrameSize = a52_syncinfo( fAc3Frame->fData, &fInFlags, + &fAudio->fInSampleRate, + &fAudio->fInBitrate ); + if( !fFrameSize ) + { + Log( "HBAc3Decoder : a52_syncinfo failed" ); + fManager->Error( HB_ERROR_A52_SYNC ); + return false; + } } - /* Get the whole frame */ - if( !( GetBytes( (uint32_t) frameSize ) ) ) + /* In case the audio should start later than the video, + insert some silence */ + if( fAudio->fDelay > 3 * 256 * 1000 / fAudio->fInSampleRate ) { - break; + fRawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) ); + for( uint32_t i = 0; i < 12 * 256; i++ ) + { + ((float*)fRawBuffer->fData)[i] = 0; + } + fAudio->fDelay -= 6 * 256 * 1000 / fAudio->fInSampleRate; + continue; } + + if( fAc3Frame->fSize >= 7 ) + { + /* Get the whole frame */ + if( !( GetBytes( (uint32_t) fFrameSize ) ) ) + { + break; + } - /* Feed liba52 */ - a52_frame( state, fAc3Frame->fData, &outFlags, &sampleLevel, 0 ); + /* Feed liba52 */ + a52_frame( fState, fAc3Frame->fData, &fOutFlags, + &fSampleLevel, 0 ); - /* 6 blocks per frame, 256 samples per block */ - rawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) ); - rawBuffer->fPosition = fPosition; - for( int i = 0; i < 6; i++ ) - { - /* Decode a block */ - a52_block( state ); + /* 6 blocks per frame, 256 samples per block */ + fRawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) ); + fRawBuffer->fPosition = fPosition; + for( int i = 0; i < 6; i++ ) + { + /* Decode a block */ + a52_block( fState ); - /* Get a pointer to the raw data */ - samples = a52_samples( state ); + /* Get a pointer to the raw data */ + samples = a52_samples( fState ); - /* Copy left channel data */ - memcpy( (float*) rawBuffer->fData + i * 256, - samples, - 256 * sizeof( float ) ); + /* Copy left channel data */ + memcpy( (float*) fRawBuffer->fData + i * 256, + samples, + 256 * sizeof( float ) ); - /* Copy right channel data */ - memcpy( (float*) rawBuffer->fData + ( 6 + i ) * 256, - samples + 256, - 256 * sizeof( float ) ); - } + /* Copy right channel data */ + memcpy( (float*) fRawBuffer->fData + ( 6 + i ) * 256, + samples + 256, + 256 * sizeof( float ) ); + } - if( !Push( fAudio->fRawFifo, rawBuffer ) ) - { - break; + fAc3Frame->fSize = 0; + + didSomething = true; } } + + Unlock(); + + return didSomething; +} + +bool HBAc3Decoder::Lock() +{ + fLock->Lock(); + if( fUsed ) + { + fLock->Unlock(); + return false; + } + fUsed = true; + fLock->Unlock(); + return true; +} + +void HBAc3Decoder::Unlock() +{ + fLock->Lock(); + fUsed = false; + fLock->Unlock(); } /* GetBytes() : pops buffers from the AC3 fifo until fAc3Frame @@ -118,7 +177,7 @@ bool HBAc3Decoder::GetBytes( uint32_t size ) { if( !fAc3Buffer ) { - if( !( fAc3Buffer = Pop( fAudio->fAc3Fifo ) ) ) + if( !( fAc3Buffer = fAudio->fAc3Fifo->Pop() ) ) { return false; } diff --git a/core/Ac3Decoder.h b/core/Ac3Decoder.h index 8226bb365..41ac48395 100644 --- a/core/Ac3Decoder.h +++ b/core/Ac3Decoder.h @@ -1,4 +1,4 @@ -/* $Id: Ac3Decoder.h,v 1.6 2003/09/30 14:38:15 titer Exp $ +/* $Id: Ac3Decoder.h,v 1.10 2003/10/07 20:58:12 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,26 +8,40 @@ #define HB_AC3_DECODER_H #include "Common.h" -#include "Thread.h" -class HBAc3Decoder : public HBThread +class HBAc3Decoder { public: - HBAc3Decoder( HBManager * manager, - HBAudio * audio ); - ~HBAc3Decoder(); + HBAc3Decoder( HBManager * manager, + HBAudio * audio ); + ~HBAc3Decoder(); + bool Work(); private: - void DoWork(); - bool GetBytes( uint32_t size ); - - HBManager * fManager; - HBAudio * fAudio; - - HBBuffer * fAc3Frame; - HBBuffer * fAc3Buffer; - uint32_t fPosInBuffer; - float fPosition; + bool Lock(); + void Unlock(); + bool GetBytes( uint32_t size ); + + HBManager * fManager; + HBAudio * fAudio; + + HBLock * fLock; + bool fUsed; + + /* liba52 */ + a52_state_t * fState; + int fInFlags; + int fOutFlags; + float fSampleLevel; + + /* buffers */ + HBBuffer * fAc3Frame; + HBBuffer * fAc3Buffer; + uint32_t fPosInBuffer; + HBBuffer * fRawBuffer; + + float fPosition; + int fFrameSize; }; #endif diff --git a/core/AviMuxer.cpp b/core/AviMuxer.cpp index 3b77b9c53..4a84fe8b8 100644 --- a/core/AviMuxer.cpp +++ b/core/AviMuxer.cpp @@ -1,4 +1,4 @@ -/* $Id: AviMuxer.cpp,v 1.14 2003/09/30 14:38:15 titer Exp $ +/* $Id: AviMuxer.cpp,v 1.17 2003/10/09 23:33:36 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -149,7 +149,7 @@ void HBAviIndex::WriteInt32( uint32_t val ) HBAviMuxer::HBAviMuxer( HBManager * manager, HBTitle * title, HBAudio * audio1, HBAudio * audio2, char * fileName ) - : HBThread( "avimuxer" ) + : HBThread( "avimuxer", HB_NORMAL_PRIORITY ) { fManager = manager; fTitle = title; @@ -163,6 +163,8 @@ HBAviMuxer::HBAviMuxer( HBManager * manager, HBTitle * title, fRiffBytesCount = 2040; fMoviBytesCount = 4; + + Run(); } void HBAviMuxer::DoWork() @@ -171,7 +173,7 @@ void HBAviMuxer::DoWork() if( !( fFile = fopen( fFileName, "w" ) ) ) { Log( "HBAviMuxer: fopen failed" ); - fManager->Error(); + fManager->Error( HB_ERROR_AVI_WRITE ); return; } diff --git a/core/Common.cpp b/core/Common.cpp index b9bb3e062..4087a001d 100644 --- a/core/Common.cpp +++ b/core/Common.cpp @@ -1,4 +1,4 @@ -/* $Id: Common.cpp,v 1.29 2003/09/30 21:21:32 titer Exp $ +/* $Id: Common.cpp,v 1.31 2003/10/07 22:48:31 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -92,6 +92,74 @@ uint64_t GetDate() return( (uint64_t) tv.tv_sec * 1000000 + (uint64_t) tv.tv_usec ); } +int GetCPUCount() +{ + int CPUCount = 1; + +#if defined( SYS_BEOS ) + system_info info; + get_system_info( &info ); + CPUCount = info.cpu_count; + +#elif defined( SYS_MACOSX ) + FILE * info; + char buffer[256]; + + if( ( info = popen( "/usr/sbin/sysctl hw.ncpu", "r" ) ) ) + { + if( fgets( buffer, 256, info ) ) + { + int count; + if( sscanf( buffer, "hw.ncpu: %d", &count ) == 1 ) + { + CPUCount = count; + } + else + { + Log( "GetCPUCount: sscanf() failed" ); + } + } + else + { + Log( "GetCPUCount: fgets() failed" ); + } + fclose( info ); + } + else + { + Log( "GetCPUCount: popen() failed" ); + } + +#elif defined( SYS_LINUX ) + FILE * info; + char buffer[256]; + + if( ( info = fopen( "/proc/cpuinfo", "r" ) ) ) + { + int count = 0; + while( fgets( buffer, 256, info ) ) + { + if( !memcmp( buffer, "processor", + sizeof( "processor" ) - 1 ) ) + { + count++; + } + } + CPUCount = count; + fclose( info ); + } + else + { + Log( "GetCPUCount: fopen() failed" ); + } + +#endif + CPUCount = MAX( 1, CPUCount ); + CPUCount = MIN( CPUCount, 8 ); + + return CPUCount; +} + #define HBLIST_DEFAULT_SIZE 20 HBList::HBList() diff --git a/core/Common.h b/core/Common.h index f4d40c8bd..3c138e2a1 100644 --- a/core/Common.h +++ b/core/Common.h @@ -1,4 +1,4 @@ -/* $Id: Common.h,v 1.28 2003/10/03 16:18:08 titer Exp $ +/* $Id: Common.h,v 1.34 2003/10/13 17:49:58 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -16,6 +16,8 @@ typedef uint8_t byte_t; /* Misc structures */ +typedef struct a52_state_s a52_state_t; +typedef struct lame_global_struct lame_global_flags; typedef struct dvdplay_s * dvdplay_ptr; typedef struct mpeg2dec_s mpeg2dec_t; typedef struct AVPicture AVPicture; @@ -43,6 +45,7 @@ class HBScanner; class HBStatus; class HBThread; class HBTitle; +class HBWorker; /* Handy macros */ #ifndef MIN @@ -61,22 +64,36 @@ void Snooze( uint64_t time ); void Log( char * log, ... ); char * LanguageForCode( int code ); uint64_t GetDate(); +int GetCPUCount(); /* Possible states */ typedef enum { - HB_MODE_UNDEF = 0000, - HB_MODE_NEED_VOLUME = 0001, - HB_MODE_SCANNING = 0002, - HB_MODE_INVALID_VOLUME = 0004, - HB_MODE_READY_TO_RIP = 0010, - HB_MODE_ENCODING = 0020, - HB_MODE_SUSPENDED = 0040, - HB_MODE_DONE = 0100, - HB_MODE_CANCELED = 0200, - HB_MODE_ERROR = 0400 + HB_MODE_UNDEF = 00000, + HB_MODE_NEED_VOLUME = 00001, + HB_MODE_SCANNING = 00002, + HB_MODE_INVALID_VOLUME = 00004, + HB_MODE_READY_TO_RIP = 00010, + HB_MODE_ENCODING = 00020, + HB_MODE_SUSPENDED = 00040, + HB_MODE_STOPPING = 00100, + HB_MODE_DONE = 00200, + HB_MODE_CANCELED = 00400, + HB_MODE_ERROR = 01000 } HBMode; +/* Possible errors */ +typedef enum +{ + HB_ERROR_A52_SYNC = 0, + HB_ERROR_AVI_WRITE, + HB_ERROR_DVD_OPEN, + HB_ERROR_DVD_READ, + HB_ERROR_MP3_INIT, + HB_ERROR_MP3_ENCODE, + HB_ERROR_MPEG4_INIT +} HBError; + class HBStatus { public: @@ -96,6 +113,9 @@ class HBStatus uint64_t fStartDate; uint32_t fRemainingTime; /* in seconds */ uint64_t fSuspendDate; + + /* HB_MODE_ERROR */ + HBError fError; }; class HBList @@ -130,6 +150,8 @@ class HBAudio int fInBitrate; int fOutBitrate; + int64_t fDelay; /* in ms */ + /* Fifos */ HBFifo * fAc3Fifo; HBFifo * fRawFifo; @@ -187,6 +209,7 @@ class HBTitle HBResizer * fResizer; HBMpeg4Encoder * fMpeg4Encoder; HBAviMuxer * fAviMuxer; + HBWorker * fWorkers[4]; }; #endif diff --git a/core/DVDReader.cpp b/core/DVDReader.cpp index 27c20d08a..8f7835f51 100644 --- a/core/DVDReader.cpp +++ b/core/DVDReader.cpp @@ -1,4 +1,4 @@ -/* $Id: DVDReader.cpp,v 1.12 2003/10/03 16:49:19 titer Exp $ +/* $Id: DVDReader.cpp,v 1.17 2003/10/09 23:33:36 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -15,10 +15,12 @@ #include <dvdplay/nav.h> HBDVDReader::HBDVDReader( HBManager * manager, HBTitle * title ) - : HBThread( "dvdreader" ) + : HBThread( "dvdreader", HB_NORMAL_PRIORITY ) { fManager = manager; fTitle = title; + + Run(); } void HBDVDReader::DoWork() @@ -29,7 +31,7 @@ void HBDVDReader::DoWork() if( !vmg ) { Log( "HBDVDReader: dvdplay_open() failed" ); - fManager->Error(); + fManager->Error( HB_ERROR_DVD_OPEN ); return; } @@ -69,7 +71,7 @@ void HBDVDReader::DoWork() { Log( "HBDVDReader: could not dvdplay_read()" ); delete dvdBuffer; - fManager->Error(); + fManager->Error( HB_ERROR_DVD_READ ); break; } diff --git a/core/Fifo.cpp b/core/Fifo.cpp index 35bcb0449..d1d051c33 100644 --- a/core/Fifo.cpp +++ b/core/Fifo.cpp @@ -1,4 +1,4 @@ -/* $Id: Fifo.cpp,v 1.14 2003/10/02 15:44:52 titer Exp $ +/* $Id: Fifo.cpp,v 1.15 2003/10/13 14:12:18 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -51,7 +51,8 @@ HBFifo::HBFifo( int capacity ) HBFifo::~HBFifo() { - Log( "HBFifo::~HBFifo : trashing %d buffers", Size() ); + Log( "HBFifo::~HBFifo: trashing %d buffer%s", + Size(), Size() ? "s" : "" ); /* Empty the fifo */ while( fWhereToPush != fWhereToPop ) diff --git a/core/Manager.cpp b/core/Manager.cpp index 583bda36a..826ceea58 100644 --- a/core/Manager.cpp +++ b/core/Manager.cpp @@ -1,72 +1,103 @@ -/* $Id: Manager.cpp,v 1.47 2003/10/05 14:28:40 titer Exp $ +/* $Id: Manager.cpp,v 1.68 2003/10/13 23:42:03 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. It may be used under the terms of the GNU General Public License. */ -#include "Manager.h" -#include "Fifo.h" -#include "Scanner.h" +#include "Ac3Decoder.h" +#include "AviMuxer.h" #include "DVDReader.h" -#include "MpegDemux.h" +#include "Fifo.h" +#include "Manager.h" +#include "Mp3Encoder.h" #include "Mpeg2Decoder.h" #include "Mpeg4Encoder.h" -#include "Ac3Decoder.h" -#include "Mp3Encoder.h" -#include "AviMuxer.h" +#include "MpegDemux.h" #include "Resizer.h" +#include "Scanner.h" +#include "Worker.h" #include <ffmpeg/avcodec.h> /* Public methods */ -HBManager::HBManager( bool debug ) - : HBThread( "manager" ) +HBManager::HBManager( bool debug, int cpuCount ) + : HBThread( "manager", HB_NORMAL_PRIORITY ) { - fPid = 0; - - fStopScan = false; - fStopRip = false; - fRipDone = false; - fError = false; - - fScanner = NULL; - - fStatus.fMode = HB_MODE_NEED_VOLUME; - fNeedUpdate = true; - /* See Log() in Common.cpp */ if( debug ) { - setenv( "HB_DEBUG", "1", 1 ); + putenv( "HB_DEBUG=1" ); + } + + /* Check CPU count */ + if( !cpuCount ) + { + fCPUCount = GetCPUCount(); + Log( "HBManager::HBManager: %d CPU%s detected", fCPUCount, + ( fCPUCount > 1 ) ? "s" : "" ); } else { - unsetenv( "HB_DEBUG" ); + fCPUCount = cpuCount; + if( fCPUCount < 1 ) + { + Log( "HBManager::HBManager: invalid CPU count (%d), " + "using 1", fCPUCount ); + fCPUCount = 1; + } + else if( fCPUCount > 8 ) + { + Log( "HBManager::HBManager: invalid CPU count (%d), " + "using 8", fCPUCount ); + fCPUCount = 8; + } + Log( "HBManager::HBManager: user specified %d CPU%s", + fCPUCount, ( fCPUCount > 1 ) ? "s" : "" ); } - fCurTitle = NULL; - fCurAudio1 = NULL; - fCurAudio2 = NULL; - /* Init ffmpeg's libavcodec */ avcodec_init(); // register_avcodec( &mpeg4_encoder ); avcodec_register_all(); + /* Initialization */ + fStopScan = false; + fStopRip = false; + fRipDone = false; + fError = false; + + fScanner = NULL; + + fStatusLock = new HBLock(); + fStatus.fMode = HB_MODE_NEED_VOLUME; + fNeedUpdate = true; + + fCurTitle = NULL; + fCurAudio1 = NULL; + fCurAudio2 = NULL; + Run(); } HBManager::~HBManager() { /* Stop ripping if needed */ - StopRip(); - while( fStopRip ) + fStatusLock->Lock(); + if( fStatus.fMode == HB_MODE_ENCODING ) { - Snooze( 10000 ); - } + fStatusLock->Unlock(); - Stop(); + StopRip(); + while( fStopRip ) + { + Snooze( 10000 ); + } + } + else + { + fStatusLock->Unlock(); + } /* Stop scanning if needed */ if( fScanner ) @@ -76,24 +107,24 @@ HBManager::~HBManager() /* Remove temp files */ char command[1024]; memset( command, 0, 1024 ); - sprintf( command, "rm -f /tmp/HB.%d.*", fPid ); + sprintf( command, "rm -f /tmp/HB.%d.*", GetPid() ); system( command ); + + delete fStatusLock; } void HBManager::DoWork() { - fPid = (int) getpid(); - while( !fDie ) { - /* Terminate dying threads */ if( fStopScan ) { - fStopScan = false; - + /* Destroy the thread */ delete fScanner; fScanner = NULL; + /* Update interface */ + fStatusLock->Lock(); if( fStatus.fTitleList && fStatus.fTitleList->CountItems() ) { fStatus.fMode = HB_MODE_READY_TO_RIP; @@ -103,83 +134,47 @@ void HBManager::DoWork() fStatus.fMode = HB_MODE_INVALID_VOLUME; } fNeedUpdate = true; + fStatusLock->Unlock(); + + fStopScan = false; } - if( fStopRip || fError ) + if( fStopRip || fError || fRipDone ) { - delete fCurTitle->fDVDReader; - delete fCurTitle->fMpegDemux; - delete fCurTitle->fMpeg2Decoder; - delete fCurTitle->fResizer; - delete fCurTitle->fMpeg4Encoder; - delete fCurTitle->fAviMuxer; - - if( fCurAudio1 ) + if( fRipDone ) { - delete fCurAudio1->fAc3Decoder; - delete fCurAudio1->fMp3Encoder; + /* Wait a bit to avoid trashing frames in fifos - + That's kinda ugly */ + while( fCurTitle->fPSFifo->Size() || + ( fCurTitle->fMpeg2Fifo->Size() && + ( !fCurAudio1 || fCurAudio1->fAc3Fifo->Size() ) && + ( !fCurAudio2 || fCurAudio2->fAc3Fifo->Size() ) ) ) + { + Snooze( 10000 ); + } + Snooze( 500000 ); } - - if( fCurAudio2 ) - { - delete fCurAudio2->fAc3Decoder; - delete fCurAudio2->fMp3Encoder; - } - - delete fCurTitle->fPSFifo; - delete fCurTitle->fMpeg2Fifo; - delete fCurTitle->fRawFifo; - delete fCurTitle->fResizedFifo; - delete fCurTitle->fMpeg4Fifo; - - if( fCurAudio1 ) - { - delete fCurAudio1->fAc3Fifo; - delete fCurAudio1->fRawFifo; - delete fCurAudio1->fMp3Fifo; - } - - if( fCurAudio2 ) - { - delete fCurAudio2->fAc3Fifo; - delete fCurAudio2->fRawFifo; - delete fCurAudio2->fMp3Fifo; - } - - fStatus.fMode = fError ? HB_MODE_ERROR : HB_MODE_CANCELED; - fStopRip = false; - fError = false; - fNeedUpdate = true; - } - - if( fRipDone ) - { - /* This is UGLY ! */ - while( fCurTitle->fPSFifo->Size() || - fCurTitle->fMpeg2Fifo->Size() || - fCurTitle->fRawFifo->Size() || - fCurTitle->fResizedFifo->Size() || - ( fCurAudio1 && fCurAudio1->fAc3Fifo->Size() ) || - ( fCurAudio1 && fCurAudio1->fRawFifo->Size() ) || - ( fCurAudio2 && fCurAudio2->fAc3Fifo->Size() ) || - ( fCurAudio2 && fCurAudio2->fRawFifo->Size() ) ) + else { - Snooze( 10000 ); + fStatusLock->Lock(); + fStatus.fMode = HB_MODE_STOPPING; + fNeedUpdate = true; + fStatusLock->Unlock(); } - - while( fCurTitle->fMpeg4Fifo->Size() && - ( !fCurAudio1 || fCurAudio1->fMp3Fifo->Size() ) && - ( !fCurAudio2 || fCurAudio2->fMp3Fifo->Size() ) ) + + /* Stop threads */ + delete fCurTitle->fDVDReader; + delete fCurTitle->fAviMuxer; + for( int i = 0; i < fCPUCount; i++ ) { - Snooze( 10000 ); + delete fCurTitle->fWorkers[i]; } - delete fCurTitle->fDVDReader; + /* Clean up */ delete fCurTitle->fMpegDemux; delete fCurTitle->fMpeg2Decoder; delete fCurTitle->fResizer; delete fCurTitle->fMpeg4Encoder; - delete fCurTitle->fAviMuxer; if( fCurAudio1 ) { @@ -193,6 +188,7 @@ void HBManager::DoWork() delete fCurAudio2->fMp3Encoder; } + /* Destroy fifos */ delete fCurTitle->fPSFifo; delete fCurTitle->fMpeg2Fifo; delete fCurTitle->fRawFifo; @@ -213,9 +209,16 @@ void HBManager::DoWork() delete fCurAudio2->fMp3Fifo; } - fStatus.fMode = HB_MODE_DONE; - fRipDone = false; + /* Update interface */ + fStatusLock->Lock(); + fStatus.fMode = fStopRip ? HB_MODE_CANCELED : + ( fError ? HB_MODE_ERROR : HB_MODE_DONE ); fNeedUpdate = true; + fStatusLock->Unlock(); + + fStopRip = false; + fError = false; + fRipDone = false; } Snooze( 10000 ); @@ -224,23 +227,25 @@ void HBManager::DoWork() bool HBManager::NeedUpdate() { + fStatusLock->Lock(); if( fNeedUpdate ) { fNeedUpdate = false; + fStatusLock->Unlock(); return true; } - + fStatusLock->Unlock(); + return false; } HBStatus HBManager::GetStatus() { - return fStatus; -} - -int HBManager::GetPid() -{ - return fPid; + fStatusLock->Lock(); + HBStatus status = fStatus; + fStatusLock->Unlock(); + + return status; } void HBManager::ScanVolumes( char * device ) @@ -254,12 +259,13 @@ void HBManager::ScanVolumes( char * device ) } fScanner = new HBScanner( this, device ); - fScanner->Run(); + fStatusLock->Lock(); fStatus.fMode = HB_MODE_SCANNING; fStatus.fScannedVolume = strdup( device ); fStatus.fScannedTitle = 0; fNeedUpdate = true; + fStatusLock->Unlock(); } void HBManager::StartRip( HBTitle * title, HBAudio * audio1, @@ -282,86 +288,77 @@ void HBManager::StartRip( HBTitle * title, HBAudio * audio1, FixPictureSettings( title ); - Log( "HBManager::StartRip : device: %s, title: %d", - title->fDevice, title->fIndex ); - Log( " - video : %dx%d -> %dx%d, bitrate = %d, 2-pass = %s", + Log( "HBManager::StartRip:" ); + Log( "- device: %s, title: %d", title->fDevice, title->fIndex ); + Log( "- video: %dx%d->%dx%d, bitrate=%d, 2-pass=%s, deinterlace=%s", title->fInWidth, title->fInHeight, title->fOutWidth, title->fOutHeight, - title->fBitrate, title->fTwoPass ? "yes" : "no" ); - Log( " - cropping: top=%d, bottom=%d, left=%d, right=%d", + title->fBitrate, title->fTwoPass ? "yes" : "no", + title->fDeinterlace ? "yes" : "no" ); + Log( "- cropping: top=%d, bottom=%d, left=%d, right=%d", title->fTopCrop, title->fBottomCrop, title->fLeftCrop, title->fRightCrop ); if( audio1 ) { - Log( " - audio 1: lang = %s (%x), bitrate = %d", - audio1->fDescription, audio1->fId, audio1->fOutBitrate ); + Log( "- audio 1: lang = %s (%x), bitrate = %d", + audio1->fDescription, audio1->fId, audio1->fOutBitrate ); } if( audio2 ) { - Log( " - audio 2: lang = %s (%x), bitrate = %d", - audio2->fDescription, audio1->fId, audio2->fOutBitrate ); + Log( "- audio 2: lang = %s (%x), bitrate = %d", + audio2->fDescription, audio2->fId, audio2->fOutBitrate ); } - /* Create fifos & threads */ - - title->fPSFifo = new HBFifo(); - title->fMpeg2Fifo = new HBFifo(); - title->fRawFifo = new HBFifo(); - title->fResizedFifo = new HBFifo(); - title->fMpeg4Fifo = new HBFifo(); + /* Create fifos */ + title->fPSFifo = new HBFifo( 256 ); + title->fMpeg2Fifo = new HBFifo( 256 ); + title->fRawFifo = new HBFifo( 4 ); + title->fResizedFifo = new HBFifo( 4 ); + title->fMpeg4Fifo = new HBFifo( 4 ); + if( audio1 ) + { + audio1->fAc3Fifo = new HBFifo( 256 ); + audio1->fRawFifo = new HBFifo( 4 ); + audio1->fMp3Fifo = new HBFifo( 4 ); + } + if( audio2 ) + { + audio2->fAc3Fifo = new HBFifo( 256 ); + audio2->fRawFifo = new HBFifo( 4 ); + audio2->fMp3Fifo = new HBFifo( 4 ); + } - title->fDVDReader = new HBDVDReader( this, title ); + /* Create decoders & encoders objects */ title->fMpegDemux = new HBMpegDemux( this, title, audio1, audio2 ); title->fMpeg2Decoder = new HBMpeg2Decoder( this, title ); title->fResizer = new HBResizer( this, title ); title->fMpeg4Encoder = new HBMpeg4Encoder( this, title ); - title->fAviMuxer = new HBAviMuxer( this, title, audio1, audio2, - file ); - if( audio1 ) { - audio1->fAc3Fifo = new HBFifo(); - audio1->fRawFifo = new HBFifo(); - audio1->fMp3Fifo = new HBFifo(); audio1->fAc3Decoder = new HBAc3Decoder( this, audio1 ); audio1->fMp3Encoder = new HBMp3Encoder( this, audio1 ); } - if( audio2 ) { - audio2->fAc3Fifo = new HBFifo(); - audio2->fRawFifo = new HBFifo(); - audio2->fMp3Fifo = new HBFifo(); audio2->fAc3Decoder = new HBAc3Decoder( this, audio2 ); audio2->fMp3Encoder = new HBMp3Encoder( this, audio2 ); } - /* Launch the threads */ - - title->fDVDReader->Run(); - title->fMpegDemux->Run(); - title->fMpeg2Decoder->Run(); - title->fResizer->Run(); - title->fMpeg4Encoder->Run(); - title->fAviMuxer->Run(); - - if( audio1 ) - { - audio1->fAc3Decoder->Run(); - audio1->fMp3Encoder->Run(); - } - - if( audio2 ) + /* Create and launch the threads */ + title->fDVDReader = new HBDVDReader( this, title ); + title->fAviMuxer = new HBAviMuxer( this, title, audio1, audio2, + file ); + for( int i = 0; i < fCPUCount; i++ ) { - audio2->fAc3Decoder->Run(); - audio2->fMp3Encoder->Run(); + title->fWorkers[i] = new HBWorker( title, audio1, audio2 ); } - + fCurTitle = title; fCurAudio1 = audio1; fCurAudio2 = audio2; + fStatusLock->Lock(); fStatus.fMode = HB_MODE_ENCODING; fStatus.fPosition = 0; fStatus.fFrameRate = 0; @@ -370,6 +367,7 @@ void HBManager::StartRip( HBTitle * title, HBAudio * audio1, fStatus.fRemainingTime = 0; fStatus.fSuspendDate = 0; fNeedUpdate = true; + fStatusLock->Unlock(); } void HBManager::SuspendRip() @@ -382,27 +380,17 @@ void HBManager::SuspendRip() } fCurTitle->fDVDReader->Suspend(); - fCurTitle->fMpegDemux->Suspend(); - fCurTitle->fMpeg2Decoder->Suspend(); - fCurTitle->fResizer->Suspend(); - fCurTitle->fMpeg4Encoder->Suspend(); fCurTitle->fAviMuxer->Suspend(); - - if( fCurAudio1 ) + for( int i = 0; i < fCPUCount; i++ ) { - fCurAudio1->fAc3Decoder->Suspend(); - fCurAudio1->fMp3Encoder->Suspend(); - } - - if( fCurAudio2 ) - { - fCurAudio2->fAc3Decoder->Suspend(); - fCurAudio2->fMp3Encoder->Suspend(); + fCurTitle->fWorkers[i]->Suspend(); } + fStatusLock->Lock(); fStatus.fMode = HB_MODE_SUSPENDED; fStatus.fSuspendDate = GetDate(); fNeedUpdate = true; + fStatusLock->Unlock(); } void HBManager::ResumeRip() @@ -415,27 +403,17 @@ void HBManager::ResumeRip() } fCurTitle->fDVDReader->Resume(); - fCurTitle->fMpegDemux->Resume(); - fCurTitle->fMpeg2Decoder->Resume(); - fCurTitle->fResizer->Resume(); - fCurTitle->fMpeg4Encoder->Resume(); fCurTitle->fAviMuxer->Resume(); - - if( fCurAudio1 ) - { - fCurAudio1->fAc3Decoder->Resume(); - fCurAudio1->fMp3Encoder->Resume(); - } - - if( fCurAudio2 ) + for( int i = 0; i < fCPUCount; i++ ) { - fCurAudio2->fAc3Decoder->Resume(); - fCurAudio2->fMp3Encoder->Resume(); + fCurTitle->fWorkers[i]->Resume(); } + fStatusLock->Lock(); fStatus.fMode = HB_MODE_ENCODING; fStatus.fStartDate += GetDate() - fStatus.fSuspendDate; fNeedUpdate = true; + fStatusLock->Unlock(); } void HBManager::StopRip() @@ -448,25 +426,6 @@ void HBManager::StopRip() } /* Stop the threads */ - - fCurTitle->fDVDReader->Stop(); - fCurTitle->fMpegDemux->Stop(); - fCurTitle->fMpeg2Decoder->Stop(); - fCurTitle->fMpeg4Encoder->Stop(); - fCurTitle->fAviMuxer->Stop(); - - if( fCurAudio1 ) - { - fCurAudio1->fAc3Decoder->Stop(); - fCurAudio1->fMp3Encoder->Stop(); - } - - if( fCurAudio2 ) - { - fCurAudio2->fAc3Decoder->Stop(); - fCurAudio2->fMp3Encoder->Stop(); - } - fStopRip = true; } @@ -545,7 +504,7 @@ uint8_t * HBManager::GetPreview( HBTitle * title, uint32_t image ) /* Get the original image from the temp file */ char fileName[1024]; memset( fileName, 0, 1024 ); - sprintf( fileName, "/tmp/HB.%d.%x.%d", fPid, (uint32_t) title, + sprintf( fileName, "/tmp/HB.%d.%x.%d", GetPid(), (uint32_t) title, image); FILE * file = fopen( fileName, "r" ); fread( buf1, 3 * fInWidth * fInHeight / 2, 1, file ); @@ -632,10 +591,12 @@ uint8_t * HBManager::GetPreview( HBTitle * title, uint32_t image ) void HBManager::Scanning( char * volume, int title ) { + fStatusLock->Lock(); fStatus.fMode = HB_MODE_SCANNING; fStatus.fScannedVolume = volume; fStatus.fScannedTitle = title; fNeedUpdate = true; + fStatusLock->Unlock(); } void HBManager::ScanDone( HBList * titleList ) @@ -650,34 +611,14 @@ void HBManager::Done() fRipDone = true; } -void HBManager::Error() +void HBManager::Error( HBError error ) { if( fStatus.fMode != HB_MODE_ENCODING ) { return; } - /* Stop the threads */ - - fCurTitle->fDVDReader->Stop(); - fCurTitle->fMpegDemux->Stop(); - fCurTitle->fMpeg2Decoder->Stop(); - fCurTitle->fResizer->Stop(); - fCurTitle->fMpeg4Encoder->Stop(); - fCurTitle->fAviMuxer->Stop(); - - if( fCurAudio1 ) - { - fCurAudio1->fAc3Decoder->Stop(); - fCurAudio1->fMp3Encoder->Stop(); - } - - if( fCurAudio2 ) - { - fCurAudio2->fAc3Decoder->Stop(); - fCurAudio2->fMp3Encoder->Stop(); - } - + fStatus.fError = error; fError = true; } @@ -695,6 +636,7 @@ void HBManager::SetPosition( float pos ) return; } + fStatusLock->Lock(); fStatus.fPosition = pos; fStatus.fFrameRate = (float) fStatus.fFrames / ( ( (float) ( GetDate() - fStatus.fStartDate ) ) / 1000000 ) ; @@ -703,5 +645,6 @@ void HBManager::SetPosition( float pos ) ( 1 - fStatus.fPosition ) / ( 1000000 * fStatus.fPosition ) ); fNeedUpdate = true; + fStatusLock->Unlock(); } diff --git a/core/Manager.h b/core/Manager.h index 8aa6cec3a..dc885e5f5 100644 --- a/core/Manager.h +++ b/core/Manager.h @@ -1,4 +1,4 @@ -/* $Id: Manager.h,v 1.27 2003/09/30 21:21:32 titer Exp $ +/* $Id: Manager.h,v 1.32 2003/10/08 22:20:36 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -13,7 +13,8 @@ class HBManager : public HBThread { public: - HBManager( bool debug = false ); + HBManager( bool debug = false, + int cpuCount = 0 ); ~HBManager(); void DoWork(); @@ -29,17 +30,17 @@ class HBManager : public HBThread uint8_t * GetPreview( HBTitle * title, uint32_t image ); /* Methods called by the working threads */ - int GetPid(); void Scanning( char * volume, int title ); void ScanDone( HBList * titleList ); void Done(); - void Error(); + void Error( HBError error ); void SetPosition( float pos ); private: void FixPictureSettings( HBTitle * title ); int fPid; + int fCPUCount; /* Booleans used in DoWork() */ bool fStopScan; @@ -51,8 +52,10 @@ class HBManager : public HBThread HBScanner * fScanner; /* Status infos */ + HBLock * fStatusLock; bool fNeedUpdate; HBStatus fStatus; + HBTitle * fCurTitle; HBAudio * fCurAudio1; HBAudio * fCurAudio2; diff --git a/core/Mp3Encoder.cpp b/core/Mp3Encoder.cpp index b4e9fe860..06d96af29 100644 --- a/core/Mp3Encoder.cpp +++ b/core/Mp3Encoder.cpp @@ -1,4 +1,4 @@ -/* $Id: Mp3Encoder.cpp,v 1.7 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mp3Encoder.cpp,v 1.13 2003/10/08 15:00:20 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -11,113 +11,153 @@ #include <lame/lame.h> HBMp3Encoder::HBMp3Encoder( HBManager * manager, HBAudio * audio ) - : HBThread( "mp3encoder" ) { - fManager = manager; - fAudio = audio; + fManager = manager; + fAudio = audio; + + fLock = new HBLock(); + fUsed = false; fRawBuffer = NULL; fPosInBuffer = 0; + fSamplesNb = 0; fLeftSamples = NULL; fRightSamples = NULL; fPosition = 0; + fInitDone = false; + fMp3Buffer = NULL; } -void HBMp3Encoder::DoWork() +bool HBMp3Encoder::Work() { - /* Wait a first buffer so we are sure that - fAudio->fInSampleRate (set the AC3 decoder) is not garbage */ - while( !fDie && !fAudio->fRawFifo->Size() ) + if( !Lock() ) { - Snooze( 5000 ); + return false; } - - if( fDie ) + + if( !fInitDone ) { - return; - } + /* Wait for a first buffer so we know fAudio->fInSampleRate + is correct */ + if( !fAudio->fRawFifo->Size() ) + { + Unlock(); + return false; + } + + /* The idea is to have exactly one mp3 frame (i.e. 1152 samples) by + output buffer. As we are resampling from fInSampleRate to + fOutSampleRate, we will give ( 1152 * fInSampleRate ) / + ( 2 * fOutSampleRate ) to libmp3lame so we are sure we will + never get more than 1 frame at a time */ + fCount = ( 1152 * fAudio->fInSampleRate ) / + ( 2 * fAudio->fOutSampleRate ); + + /* Init libmp3lame */ + fGlobalFlags = lame_init(); + lame_set_in_samplerate( fGlobalFlags, fAudio->fInSampleRate ); + lame_set_out_samplerate( fGlobalFlags, fAudio->fOutSampleRate ); + lame_set_brate( fGlobalFlags, fAudio->fOutBitrate ); + + if( lame_init_params( fGlobalFlags ) == -1 ) + { + Log( "HBMp3Encoder: lame_init_params() failed" ); + fManager->Error( HB_ERROR_MP3_INIT ); + return false; + } - /* The idea is to have exactly one mp3 frame (i.e. 1152 samples) by - output buffer. As we are resampling from fInSampleRate to - fOutSampleRate, we will give ( 1152 * fInSampleRate ) / - ( 2 * fOutSampleRate ) to libmp3lame so we are sure we will - never get more than 1 frame at a time */ - uint32_t count = ( 1152 * fAudio->fInSampleRate ) / - ( 2 * fAudio->fOutSampleRate ); - - /* Init libmp3lame */ - lame_global_flags * globalFlags = lame_init(); - lame_set_in_samplerate( globalFlags, fAudio->fInSampleRate ); - lame_set_out_samplerate( globalFlags, fAudio->fOutSampleRate ); - lame_set_brate( globalFlags, fAudio->fOutBitrate ); - - if( lame_init_params( globalFlags ) == -1 ) - { - Log( "HBMp3Encoder::DoWork() : lame_init_params() failed" ); - fManager->Error(); - return; - } + fLeftSamples = (float*) malloc( fCount * sizeof( float ) ); + fRightSamples = (float*) malloc( fCount * sizeof( float ) ); - fLeftSamples = (float*) malloc( count * sizeof( float ) ); - fRightSamples = (float*) malloc( count * sizeof( float ) ); + fInitDone = true; + } - HBBuffer * mp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER ); + bool didSomething = false; - int ret; for( ;; ) { - while( fSuspend ) + if( fMp3Buffer ) { - Snooze( 10000 ); + if( fAudio->fMp3Fifo->Push( fMp3Buffer ) ) + { + fMp3Buffer = NULL; + } + else + { + break; + } } - + /* Get new samples */ - if( !GetSamples( count ) ) + if( !GetSamples() ) { break; } - ret = lame_encode_buffer_float( globalFlags, - fLeftSamples, fRightSamples, - count, mp3Buffer->fData, - mp3Buffer->fSize ); + int ret; + fMp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER ); + ret = lame_encode_buffer_float( fGlobalFlags, fLeftSamples, + fRightSamples, fCount, + fMp3Buffer->fData, + fMp3Buffer->fSize ); if( ret < 0 ) { /* Something wrong happened */ - Log( "HBMp3Encoder : lame_encode_buffer_float() failed (%d)", ret ); - fManager->Error(); - break; + Log( "HBMp3Encoder : lame_encode_buffer_float() failed " + "(%d)", ret ); + fManager->Error( HB_ERROR_MP3_ENCODE ); + return false; } else if( ret > 0 ) { /* We got something, send it to the muxer */ - mp3Buffer->fSize = ret; - mp3Buffer->fKeyFrame = true; - mp3Buffer->fPosition = fPosition; - Push( fAudio->fMp3Fifo, mp3Buffer ); - mp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER ); + fMp3Buffer->fSize = ret; + fMp3Buffer->fKeyFrame = true; + fMp3Buffer->fPosition = fPosition; } + else + { + delete fMp3Buffer; + fMp3Buffer = NULL; + } + fSamplesNb = 0; + + didSomething = true; } - /* Clean up */ - delete mp3Buffer; - free( fLeftSamples ); - free( fRightSamples ); + Unlock(); + return didSomething; +} - lame_close( globalFlags ); +bool HBMp3Encoder::Lock() +{ + fLock->Lock(); + if( fUsed ) + { + fLock->Unlock(); + return false; + } + fUsed = true; + fLock->Unlock(); + return true; } -bool HBMp3Encoder::GetSamples( uint32_t count ) +void HBMp3Encoder::Unlock() { - uint32_t samplesNb = 0; + fLock->Lock(); + fUsed = false; + fLock->Unlock(); +} - while( samplesNb < count ) +bool HBMp3Encoder::GetSamples() +{ + while( fSamplesNb < fCount ) { if( !fRawBuffer ) { - if( !( fRawBuffer = Pop( fAudio->fRawFifo ) ) ) + if( !( fRawBuffer = fAudio->fRawFifo->Pop() ) ) { return false; } @@ -126,16 +166,16 @@ bool HBMp3Encoder::GetSamples( uint32_t count ) fPosition = fRawBuffer->fPosition; } - int willCopy = MIN( count - samplesNb, 6 * 256 - fPosInBuffer ); + int willCopy = MIN( fCount - fSamplesNb, 6 * 256 - fPosInBuffer ); - memcpy( fLeftSamples + samplesNb, + memcpy( fLeftSamples + fSamplesNb, (float*) fRawBuffer->fData + fPosInBuffer, willCopy * sizeof( float ) ); - memcpy( fRightSamples + samplesNb, + memcpy( fRightSamples + fSamplesNb, (float*) fRawBuffer->fData + 6 * 256 + fPosInBuffer, willCopy * sizeof( float ) ); - samplesNb += willCopy; + fSamplesNb += willCopy; fPosInBuffer += willCopy; if( fPosInBuffer == 6 * 256 ) diff --git a/core/Mp3Encoder.h b/core/Mp3Encoder.h index 67b8647d5..fb8348961 100644 --- a/core/Mp3Encoder.h +++ b/core/Mp3Encoder.h @@ -1,4 +1,4 @@ -/* $Id: Mp3Encoder.h,v 1.5 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mp3Encoder.h,v 1.9 2003/10/07 22:48:31 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,27 +8,36 @@ #define HB_MP3_ENCODER_H #include "Common.h" -#include "Thread.h" -class HBMp3Encoder : public HBThread +class HBMp3Encoder { public: HBMp3Encoder( HBManager * manager, HBAudio * audio ); + bool Work(); private: - void DoWork(); - bool GetSamples( uint32_t count ); + bool Lock(); + void Unlock(); + bool GetSamples(); HBManager * fManager; HBAudio * fAudio; + HBLock * fLock; + bool fUsed; + HBBuffer * fRawBuffer; uint32_t fPosInBuffer; /* in samples */ + uint32_t fSamplesNb; float * fLeftSamples; float * fRightSamples; float fPosition; + lame_global_flags * fGlobalFlags; + bool fInitDone; + HBBuffer * fMp3Buffer; + uint32_t fCount; }; #endif diff --git a/core/Mpeg2Decoder.cpp b/core/Mpeg2Decoder.cpp index 1ba4945bc..3149931e8 100644 --- a/core/Mpeg2Decoder.cpp +++ b/core/Mpeg2Decoder.cpp @@ -1,4 +1,4 @@ -/* $Id: Mpeg2Decoder.cpp,v 1.14 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mpeg2Decoder.cpp,v 1.21 2003/10/09 14:21:21 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -14,55 +14,91 @@ extern "C" { #include <ffmpeg/avcodec.h> HBMpeg2Decoder::HBMpeg2Decoder( HBManager * manager, HBTitle * title ) - : HBThread( "mpeg2decoder" ) { - fManager = manager; - fTitle = title; + fManager = manager; + fTitle = title; + + fLock = new HBLock(); + fUsed = false; + + fPass = 42; + fRawBuffer = NULL; + fRawBufferList = new HBList(); + fHandle = NULL; } -void HBMpeg2Decoder::DoWork() +bool HBMpeg2Decoder::Work() { - if( !( fMpeg2Buffer = Pop( fTitle->fMpeg2Fifo ) ) ) + fLock->Lock(); + if( fUsed ) { - return; + fLock->Unlock(); + return true; } + fUsed = true; + fLock->Unlock(); - fPass = fMpeg2Buffer->fPass; - Init(); - - do + bool didSomething = false; + + for( ;; ) { - while( fSuspend ) + /* Push decoded buffers */ + while( ( fRawBuffer = + (HBBuffer*) fRawBufferList->ItemAt( 0 ) ) ) + { + if( fTitle->fRawFifo->Push( fRawBuffer ) ) + { + fRawBufferList->RemoveItem( fRawBuffer ); + } + else + { + break; + } + } + + if( fRawBufferList->CountItems() ) { - Snooze( 10000 ); + break; + } + + /* Get a new buffer to decode */ + if( !( fMpeg2Buffer = fTitle->fMpeg2Fifo->Pop() ) ) + { + break; } + /* (Re)init if needed */ if( fMpeg2Buffer->fPass != fPass ) { - Close(); fPass = fMpeg2Buffer->fPass; Init(); } + /* Do the job */ DecodeBuffer(); + + didSomething = true; } - while( ( fMpeg2Buffer = Pop( fTitle->fMpeg2Fifo ) ) ); + + fLock->Lock(); + fUsed = false; + fLock->Unlock(); + + return didSomething; } void HBMpeg2Decoder::Init() { + if( fHandle ) + { + mpeg2_close( fHandle ); + } + fLateField = false; - /* Init libmpeg2 */ fHandle = mpeg2_init(); } -void HBMpeg2Decoder::Close() -{ - /* Close libmpeg2 */ - mpeg2_close( fHandle ); -} - void HBMpeg2Decoder::DecodeBuffer() { const mpeg2_info_t * info = mpeg2_info( fHandle ); @@ -83,55 +119,52 @@ void HBMpeg2Decoder::DecodeBuffer() else if( ( state == STATE_SLICE || state == STATE_END ) && info->display_fbuf ) { - HBBuffer * rawBuffer = new HBBuffer( 3 * fTitle->fInWidth * - fTitle->fInHeight / 2 ); + fRawBuffer = new HBBuffer( 3 * fTitle->fInWidth * + fTitle->fInHeight / 2 ); /* TODO : make libmpeg2 write directly in our buffer */ - memcpy( rawBuffer->fData, + memcpy( fRawBuffer->fData, info->display_fbuf->buf[0], fTitle->fInWidth * fTitle->fInHeight ); - memcpy( rawBuffer->fData + fTitle->fInWidth * + memcpy( fRawBuffer->fData + fTitle->fInWidth * fTitle->fInHeight, info->display_fbuf->buf[1], fTitle->fInWidth * fTitle->fInHeight / 4 ); - memcpy( rawBuffer->fData + fTitle->fInWidth * + memcpy( fRawBuffer->fData + fTitle->fInWidth * fTitle->fInHeight + fTitle->fInWidth * fTitle->fInHeight / 4, info->display_fbuf->buf[2], fTitle->fInWidth * fTitle->fInHeight / 4 ); - rawBuffer->fPosition = fMpeg2Buffer->fPosition; - rawBuffer->fPass = fPass; + fRawBuffer->fPosition = fMpeg2Buffer->fPosition; + fRawBuffer->fPass = fMpeg2Buffer->fPass; + + fRawBufferList->AddItem( fRawBuffer ); /* NTSC pulldown kludge */ if( info->display_picture->nb_fields == 3 ) { if( fLateField ) { - HBBuffer * buffer = - new HBBuffer( rawBuffer->fSize ); - buffer->fPosition = rawBuffer->fPosition; - buffer->fPass = rawBuffer->fPass; - memcpy( buffer->fData, rawBuffer->fData, - buffer->fSize ); - Push( fTitle->fRawFifo, buffer ); + HBBuffer * pulldownBuffer; + pulldownBuffer = new HBBuffer( fRawBuffer->fSize ); + pulldownBuffer->fPosition = fRawBuffer->fPosition; + pulldownBuffer->fPass = fRawBuffer->fPass; + memcpy( pulldownBuffer->fData, fRawBuffer->fData, + pulldownBuffer->fSize ); + fRawBufferList->AddItem( pulldownBuffer ); } fLateField = !fLateField; } - - /* Send it to the encoder */ - if( !( Push( fTitle->fRawFifo, rawBuffer ) ) ) - { - break; - } } else if( state == STATE_INVALID ) { /* Shouldn't happen on a DVD */ - Log( "HBMpeg2Decoder : STATE_INVALID" ); + Log( "HBMpeg2Decoder: STATE_INVALID" ); } } delete fMpeg2Buffer; + fMpeg2Buffer = NULL; } diff --git a/core/Mpeg2Decoder.h b/core/Mpeg2Decoder.h index 2e1a46b3d..9d1f27f8f 100644 --- a/core/Mpeg2Decoder.h +++ b/core/Mpeg2Decoder.h @@ -1,4 +1,4 @@ -/* $Id: Mpeg2Decoder.h,v 1.10 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mpeg2Decoder.h,v 1.15 2003/10/09 14:21:21 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,25 +8,28 @@ #define HB_MPEG2_DECODER_H #include "Common.h" -#include "Thread.h" -class HBMpeg2Decoder : public HBThread +class HBMpeg2Decoder { public: HBMpeg2Decoder( HBManager * manager, HBTitle * title ); + bool Work(); private: - void DoWork(); void Init(); - void Close(); void DecodeBuffer(); HBManager * fManager; HBTitle * fTitle; + HBLock * fLock; + bool fUsed; + uint32_t fPass; HBBuffer * fMpeg2Buffer; + HBBuffer * fRawBuffer; + HBList * fRawBufferList; mpeg2dec_t * fHandle; bool fLateField; }; diff --git a/core/Mpeg4Encoder.cpp b/core/Mpeg4Encoder.cpp index 42fb38b9e..4ef0a4c3f 100644 --- a/core/Mpeg4Encoder.cpp +++ b/core/Mpeg4Encoder.cpp @@ -1,4 +1,4 @@ -/* $Id: Mpeg4Encoder.cpp,v 1.15 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mpeg4Encoder.cpp,v 1.23 2003/10/09 13:24:48 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -11,49 +11,97 @@ #include <ffmpeg/avcodec.h> HBMpeg4Encoder::HBMpeg4Encoder( HBManager * manager, HBTitle * title ) - : HBThread( "mpeg4encoder" ) { fManager = manager; fTitle = title; + + fLock = new HBLock(); + fUsed = false; + + fPass = 42; + fMpeg4Buffer = NULL; + fFile = NULL; + fFrame = avcodec_alloc_frame(); + fLog = NULL; } -void HBMpeg4Encoder::DoWork() +bool HBMpeg4Encoder::Work() { - if( !( fResizedBuffer = Pop( fTitle->fResizedFifo ) ) ) + if( !Lock() ) { - return; + return false; } - fPass = fResizedBuffer->fPass; - Init(); + bool didSomething = false; - do + for( ;; ) { - while( fSuspend ) + if( fMpeg4Buffer ) { - Snooze( 10000 ); + if( fTitle->fMpeg4Fifo->Push( fMpeg4Buffer ) ) + { + fMpeg4Buffer = NULL; + } + else + { + break; + } + } + + if( !( fResizedBuffer = fTitle->fResizedFifo->Pop() ) ) + { + break; } if( fResizedBuffer->fPass != fPass ) { - Close(); fPass = fResizedBuffer->fPass; Init(); } fManager->SetPosition( fResizedBuffer->fPosition ); EncodeBuffer(); + + didSomething = true; + } + + Unlock(); + return didSomething; +} + +bool HBMpeg4Encoder::Lock() +{ + fLock->Lock(); + if( fUsed ) + { + fLock->Unlock(); + return false; } - while( ( fResizedBuffer = Pop( fTitle->fResizedFifo ) ) ); + fUsed = true; + fLock->Unlock(); + return true; +} + +void HBMpeg4Encoder::Unlock() +{ + fLock->Lock(); + fUsed = false; + fLock->Unlock(); } void HBMpeg4Encoder::Init() { + /* Clean up if needed */ + if( fFile ) + { + fclose( fFile ); + } + AVCodec * codec = avcodec_find_encoder( CODEC_ID_MPEG4 ); if( !codec ) { Log( "HBMpeg4Encoder: avcodec_find_encoder() failed" ); - fManager->Error(); + fManager->Error( HB_ERROR_MPEG4_INIT ); return; } @@ -94,19 +142,9 @@ void HBMpeg4Encoder::Init() if( avcodec_open( fContext, codec ) < 0 ) { Log( "HBMpeg4Encoder: avcodec_open() failed" ); - fManager->Error(); + fManager->Error( HB_ERROR_MPEG4_INIT ); return; } - - fFrame = avcodec_alloc_frame(); -} - -void HBMpeg4Encoder::Close() -{ - if( fPass == 1 ) - { - fclose( fFile ); - } } void HBMpeg4Encoder::EncodeBuffer() @@ -120,31 +158,27 @@ void HBMpeg4Encoder::EncodeBuffer() fFrame->linesize[1] = fTitle->fOutWidth / 2; fFrame->linesize[2] = fTitle->fOutWidth / 2; - HBBuffer * mpeg4Buffer; - mpeg4Buffer = new HBBuffer( 3 * fTitle->fOutWidth * + fMpeg4Buffer = new HBBuffer( 3 * fTitle->fOutWidth * fTitle->fOutHeight / 2 ); /* Should be really too much... */ - mpeg4Buffer->fPosition = fResizedBuffer->fPosition; - mpeg4Buffer->fSize = - avcodec_encode_video( fContext, mpeg4Buffer->fData, - mpeg4Buffer->fAllocSize, fFrame ); - mpeg4Buffer->fKeyFrame = ( fContext->coded_frame->key_frame != 0 ); - - delete fResizedBuffer; + fMpeg4Buffer->fPosition = fResizedBuffer->fPosition; + fMpeg4Buffer->fSize = + avcodec_encode_video( fContext, fMpeg4Buffer->fData, + fMpeg4Buffer->fAllocSize, fFrame ); + fMpeg4Buffer->fKeyFrame = ( fContext->coded_frame->key_frame != 0 ); - if( fPass == 1 ) + if( fResizedBuffer->fPass == 1 ) { if( fContext->stats_out ) { fprintf( fFile, "%s", fContext->stats_out ); } - delete mpeg4Buffer; - } - else - { - /* Mux it */ - Push( fTitle->fMpeg4Fifo, mpeg4Buffer ); + delete fMpeg4Buffer; + fMpeg4Buffer = NULL; } + + delete fResizedBuffer; + fResizedBuffer = NULL; } diff --git a/core/Mpeg4Encoder.h b/core/Mpeg4Encoder.h index 1bdb29434..3d20f315a 100644 --- a/core/Mpeg4Encoder.h +++ b/core/Mpeg4Encoder.h @@ -1,4 +1,4 @@ -/* $Id: Mpeg4Encoder.h,v 1.8 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mpeg4Encoder.h,v 1.11 2003/10/08 11:56:40 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,29 +8,34 @@ #define HB_MPEG4_ENCODER_H #include "Common.h" -#include "Thread.h" -class HBMpeg4Encoder : public HBThread +class HBMpeg4Encoder { public: HBMpeg4Encoder( HBManager * manager, HBTitle * title ); + bool Work(); private: - void DoWork(); + bool Lock(); + void Unlock(); + void Init(); - void Close(); void EncodeBuffer(); HBManager * fManager; HBTitle * fTitle; + HBLock * fLock; + bool fUsed; + uint32_t fPass; HBBuffer * fResizedBuffer; AVCodecContext * fContext; AVFrame * fFrame; FILE * fFile; char * fLog; + HBBuffer * fMpeg4Buffer; }; #endif diff --git a/core/MpegDemux.cpp b/core/MpegDemux.cpp index d3fd6b089..c01647a3a 100644 --- a/core/MpegDemux.cpp +++ b/core/MpegDemux.cpp @@ -1,4 +1,4 @@ -/* $Id: MpegDemux.cpp,v 1.10 2003/10/04 12:12:48 titer Exp $ +/* $Id: MpegDemux.cpp,v 1.18 2003/10/13 15:14:01 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -14,146 +14,176 @@ extern "C" { HBMpegDemux::HBMpegDemux( HBManager * manager, HBTitle * title, HBAudio * audio1, HBAudio * audio2 ) - : HBThread( "mpegdemux" ) { - fManager = manager; - fTitle = title; - fAudio1 = audio1; - fAudio2 = audio2; + fManager = manager; + fTitle = title; + fAudio1 = audio1; + fAudio2 = audio2; - fPSBuffer = NULL; - fESBuffer = NULL; - fESBufferList = NULL; + fLock = new HBLock(); + fUsed = false; + + fPSBuffer = NULL; + fESBuffer = NULL; + fESBufferList = NULL; fFirstVideoPTS = -1; fFirstAudio1PTS = -1; fFirstAudio2PTS = -1; } -void HBMpegDemux::DoWork() +HBMpegDemux::~HBMpegDemux() { - for( ;; ) + /* Free memory */ + if( fESBufferList ) { - while( fSuspend ) - { - Snooze( 10000 ); - } - - /* Get a PS packet */ - if( !( fPSBuffer = Pop( fTitle->fPSFifo ) ) ) + while( ( fESBuffer = (HBBuffer*) fESBufferList->ItemAt( 0 ) ) ) { - break; + fESBufferList->RemoveItem( fESBuffer ); + delete fESBuffer; } + } + delete fLock; +} - /* Get the ES data in it */ - PStoES( fPSBuffer, &fESBufferList ); - - if( !fESBufferList ) - { - continue; - } +bool HBMpegDemux::Work() +{ + if( !Lock() ) + { + return false; + } + + bool didSomething = false; - while( ( fESBuffer = (HBBuffer*) fESBufferList->ItemAt( 0 ) ) ) + for( ;; ) + { + /* If we have buffers waiting, try to push them */ + if( fESBufferList ) { - fESBufferList->RemoveItem( fESBuffer ); - - if( fESBuffer->fPass == 1 && fESBuffer->fStreamId != 0xE0 ) + for( uint32_t i = 0; i < fESBufferList->CountItems(); ) { - delete fESBuffer; - continue; - } + fESBuffer = (HBBuffer*) fESBufferList->ItemAt( i ); + + if( fESBuffer->fPass == 1 && fESBuffer->fStreamId != 0xE0 ) + { + fESBufferList->RemoveItem( fESBuffer ); + delete fESBuffer; + continue; + } - /* Look for a decoder for this ES */ - if( fESBuffer->fStreamId == 0xE0 ) - { - if( fFirstVideoPTS < 0 ) + /* Look for a decoder for this ES */ + + if( fESBuffer->fStreamId == 0xE0 ) { - fFirstVideoPTS = fESBuffer->fPTS; + if( fFirstVideoPTS < 0 ) + { + fFirstVideoPTS = fESBuffer->fPTS; + Log( "HBMpegDemux: got first 0xE0 packet (%lld)", + fFirstVideoPTS ); + } + if( fTitle->fMpeg2Fifo->Push( fESBuffer ) ) + { + fESBufferList->RemoveItem( fESBuffer ); + } + else + { + i++; + } } - Push( fTitle->fMpeg2Fifo, fESBuffer ); - } - else if( fAudio1 && - fESBuffer->fStreamId == fAudio1->fId ) - { - /* If the audio track starts later than the video, - repeat the first frame as long as needed */ - if( fFirstAudio1PTS < 0 ) + else if( fAudio1 && + fESBuffer->fStreamId == fAudio1->fId ) { - fFirstAudio1PTS = fESBuffer->fPTS; + if( fFirstAudio1PTS < 0 ) + { + fFirstAudio1PTS = fESBuffer->fPTS; + Log( "HBMpegDemux: got first 0x%x packet (%lld)", + fAudio1->fId, fFirstAudio1PTS ); - if( fFirstAudio1PTS > fFirstVideoPTS ) + fAudio1->fDelay = + ( fFirstAudio1PTS - fFirstVideoPTS ) / 90; + } + if( fAudio1->fAc3Fifo->Push( fESBuffer ) ) + { + fESBufferList->RemoveItem( fESBuffer ); + } + else { - Log( "HBMpegDemux::DoWork() : audio track %x " - "is late (%lld)", fAudio1->fId, - fFirstAudio1PTS - fFirstVideoPTS ); - InsertSilence( fFirstAudio1PTS - fFirstVideoPTS, - fAudio1->fAc3Fifo, - fESBuffer ); + i++; } } - Push( fAudio1->fAc3Fifo, fESBuffer ); - } - else if( fAudio2 && - fESBuffer->fStreamId == fAudio2->fId ) - { - if( fFirstAudio2PTS < 0 ) + else if( fAudio2 && + fESBuffer->fStreamId == fAudio2->fId ) { - fFirstAudio2PTS = fESBuffer->fPTS; + if( fFirstAudio2PTS < 0 ) + { + fFirstAudio2PTS = fESBuffer->fPTS; + Log( "HBMpegDemux: got first 0x%x packet (%lld)", + fAudio2->fId, fFirstAudio2PTS ); - if( fFirstAudio2PTS > fFirstVideoPTS ) + fAudio2->fDelay = + ( fFirstAudio2PTS - fFirstVideoPTS ) / 90; + } + if( fAudio2->fAc3Fifo->Push( fESBuffer ) ) { - Log( "HBMpegDemux::DoWork() : audio track %x " - "is late (%lld)", fAudio2->fId, - fFirstAudio2PTS - fFirstVideoPTS ); - InsertSilence( fFirstAudio2PTS - fFirstVideoPTS, - fAudio2->fAc3Fifo, - fESBuffer ); + fESBufferList->RemoveItem( fESBuffer ); } + else + { + i++; + } + } + else + { + fESBufferList->RemoveItem( fESBuffer ); + delete fESBuffer; } - Push( fAudio2->fAc3Fifo, fESBuffer ); + } + + if( !fESBufferList->CountItems() ) + { + delete fESBufferList; + fESBufferList = NULL; } else { - delete fESBuffer; + break; } } - delete fESBufferList; - } -} -void HBMpegDemux::InsertSilence( int64_t time, HBFifo * fifo, - HBBuffer * buffer ) -{ - int flags = 0; - int sampleRate = 0; - int bitrate = 0; - int frameSize = a52_syncinfo( buffer->fData, &flags, - &sampleRate, &bitrate ); - - if( !frameSize ) - { - Log( "HBMpegDemux::InsertSilence() : a52_syncinfo() failed" ); - return; - } + /* Get a PS packet */ + if( !( fPSBuffer = fTitle->fPSFifo->Pop() ) ) + { + break; + } - uint32_t frames = ( ( sampleRate * time / 90000 ) + ( 3 * 256 ) ) - / ( 6 * 256 ); + /* Get the ES data in it */ + PStoES( fPSBuffer, &fESBufferList ); - if( !frames ) - { - return; + didSomething = true; } - Log( "HBMpegDemux::InsertSilence() : adding %d frames", frames ); + Unlock(); + return didSomething; +} - HBBuffer * buffer2; - for( uint32_t i = 0; i < frames; i++ ) +bool HBMpegDemux::Lock() +{ + fLock->Lock(); + if( fUsed ) { - buffer2 = new HBBuffer( frameSize ); - buffer2->fPosition = buffer->fPosition; - memcpy( buffer2->fData, buffer->fData, frameSize ); - Push( fifo, buffer2 ); - } + fLock->Unlock(); + return false; + } + fUsed = true; + fLock->Unlock(); + return true; +} + +void HBMpegDemux::Unlock() +{ + fLock->Lock(); + fUsed = false; + fLock->Unlock(); } bool PStoES( HBBuffer * psBuffer, HBList ** _esBufferList ) diff --git a/core/MpegDemux.h b/core/MpegDemux.h index ef5b1b3d9..187a08de9 100644 --- a/core/MpegDemux.h +++ b/core/MpegDemux.h @@ -1,4 +1,4 @@ -/* $Id: MpegDemux.h,v 1.6 2003/10/04 12:12:48 titer Exp $ +/* $Id: MpegDemux.h,v 1.11 2003/10/09 13:24:48 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,26 +8,29 @@ #define HB_MPEG_DEMUX_H #include "Common.h" -#include "Thread.h" bool PStoES( HBBuffer * psBuffer, HBList ** _esBufferList ); -class HBMpegDemux : public HBThread +class HBMpegDemux { public: - HBMpegDemux( HBManager * manager, HBTitle * title, - HBAudio * audio1, HBAudio * audio2 ); + HBMpegDemux( HBManager * manager, HBTitle * title, + HBAudio * audio1, HBAudio * audio2 ); + ~HBMpegDemux(); + bool Work(); private: - void DoWork(); - void InsertSilence( int64_t time, HBFifo * fifo, - HBBuffer * buffer ); + bool Lock(); + void Unlock(); HBManager * fManager; HBTitle * fTitle; HBAudio * fAudio1; HBAudio * fAudio2; + HBLock * fLock; + bool fUsed; + HBBuffer * fPSBuffer; HBBuffer * fESBuffer; HBList * fESBufferList; diff --git a/core/Resizer.cpp b/core/Resizer.cpp index e3cae3986..0b9c794db 100644 --- a/core/Resizer.cpp +++ b/core/Resizer.cpp @@ -1,4 +1,4 @@ -/* $Id: Resizer.cpp,v 1.3 2003/09/30 14:38:15 titer Exp $ +/* $Id: Resizer.cpp,v 1.8 2003/10/09 13:24:48 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -11,79 +11,131 @@ #include <ffmpeg/avcodec.h> HBResizer::HBResizer( HBManager * manager, HBTitle * title ) - : HBThread( "resizer" ) { - fManager = manager; - fTitle = title; -} + fManager = manager; + fTitle = title; + + /* Lock */ + fLock = new HBLock(); + fUsed = false; -void HBResizer::DoWork() -{ /* Init libavcodec */ - ImgReSampleContext * resampleContext = + fResampleContext = img_resample_full_init( fTitle->fOutWidth, fTitle->fOutHeight, fTitle->fInWidth, fTitle->fInHeight, fTitle->fTopCrop, fTitle->fBottomCrop, fTitle->fLeftCrop, fTitle->fRightCrop ); /* Buffers & pictures */ - HBBuffer * rawBuffer, * deinterlacedBuffer, * resizedBuffer; - AVPicture rawPicture, deinterlacedPicture, resizedPicture; - - deinterlacedBuffer = new HBBuffer( 3 * fTitle->fInWidth * - fTitle->fInHeight / 2 ); - avpicture_fill( &deinterlacedPicture, deinterlacedBuffer->fData, + fRawBuffer = NULL; + fDeinterlacedBuffer = new HBBuffer( 3 * fTitle->fInWidth * + fTitle->fInHeight / 2 ); + fResizedBuffer = NULL; + fRawPicture = (AVPicture*) malloc( sizeof( AVPicture ) ); + fDeinterlacedPicture = (AVPicture*) malloc( sizeof( AVPicture ) ); + fResizedPicture = (AVPicture*) malloc( sizeof( AVPicture ) ); + + avpicture_fill( fDeinterlacedPicture, fDeinterlacedBuffer->fData, PIX_FMT_YUV420P, fTitle->fInWidth, fTitle->fInHeight ); +} + +HBResizer::~HBResizer() +{ + /* Free memory */ + free( fResizedPicture ); + free( fDeinterlacedPicture ); + free( fRawPicture ); + if( fResizedBuffer ) delete fResizedBuffer; + delete fDeinterlacedBuffer; + img_resample_close( fResampleContext ); + delete fLock; +} +bool HBResizer::Work() +{ + if( !Lock() ) + { + return false; + } + + bool didSomething = false; + for( ;; ) { - while( fSuspend ) + /* Push the latest resized buffer */ + if( fResizedBuffer ) { - Snooze( 10000 ); + if( fTitle->fResizedFifo->Push( fResizedBuffer ) ) + { + fResizedBuffer = NULL; + } + else + { + break; + } } - - if( !( rawBuffer = Pop( fTitle->fRawFifo ) ) ) + + /* Get a new raw picture */ + if( !( fRawBuffer = fTitle->fRawFifo->Pop() ) ) { break; } - avpicture_fill( &rawPicture, rawBuffer->fData, + /* Do the job */ + avpicture_fill( fRawPicture, fRawBuffer->fData, PIX_FMT_YUV420P, fTitle->fInWidth, fTitle->fInHeight ); - resizedBuffer = new HBBuffer( 3 * fTitle->fOutWidth * + fResizedBuffer = new HBBuffer( 3 * fTitle->fOutWidth * fTitle->fOutHeight / 2 ); - resizedBuffer->fPosition = rawBuffer->fPosition; - resizedBuffer->fPass = rawBuffer->fPass; - avpicture_fill( &resizedPicture, resizedBuffer->fData, + fResizedBuffer->fPosition = fRawBuffer->fPosition; + fResizedBuffer->fPass = fRawBuffer->fPass; + avpicture_fill( fResizedPicture, fResizedBuffer->fData, PIX_FMT_YUV420P, fTitle->fOutWidth, fTitle->fOutHeight ); - if( fTitle->fDeinterlace ) { - avpicture_deinterlace( &deinterlacedPicture, &rawPicture, + avpicture_deinterlace( fDeinterlacedPicture, fRawPicture, PIX_FMT_YUV420P, fTitle->fInWidth, fTitle->fInHeight ); - img_resample( resampleContext, &resizedPicture, - &deinterlacedPicture ); + img_resample( fResampleContext, fResizedPicture, + fDeinterlacedPicture ); } else { - img_resample( resampleContext, &resizedPicture, - &rawPicture ); + img_resample( fResampleContext, fResizedPicture, + fRawPicture ); } + delete fRawBuffer; + fRawBuffer = NULL; - Push( fTitle->fResizedFifo, resizedBuffer ); - delete rawBuffer; + didSomething = true; } - /* Free memory */ - delete deinterlacedBuffer; + Unlock(); + return didSomething; +} - /* Close libavcodec */ - img_resample_close( resampleContext ); +bool HBResizer::Lock() +{ + fLock->Lock(); + if( fUsed ) + { + fLock->Unlock(); + return false; + } + fUsed = true; + fLock->Unlock(); + return true; +} + +void HBResizer::Unlock() +{ + fLock->Lock(); + fUsed = false; + fLock->Unlock(); } diff --git a/core/Resizer.h b/core/Resizer.h index 1fdde85d3..f6d4a4568 100644 --- a/core/Resizer.h +++ b/core/Resizer.h @@ -1,4 +1,4 @@ -/* $Id: Resizer.h,v 1.2 2003/09/30 14:38:15 titer Exp $ +/* $Id: Resizer.h,v 1.5 2003/10/07 22:48:31 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,18 +8,31 @@ #define HB_RESIZER_H #include "Common.h" -#include "Thread.h" -class HBResizer : public HBThread +class HBResizer { public: HBResizer( HBManager * manager, HBTitle * title ); + ~HBResizer(); + bool Work(); private: - void DoWork(); - + bool Lock(); + void Unlock(); + HBManager * fManager; HBTitle * fTitle; + + HBLock * fLock; + bool fUsed; + + ImgReSampleContext * fResampleContext; + HBBuffer * fRawBuffer; + HBBuffer * fDeinterlacedBuffer; + HBBuffer * fResizedBuffer; + AVPicture * fRawPicture; + AVPicture * fDeinterlacedPicture; + AVPicture * fResizedPicture; }; #endif diff --git a/core/Scanner.cpp b/core/Scanner.cpp index 575b25573..44ff6be3a 100644 --- a/core/Scanner.cpp +++ b/core/Scanner.cpp @@ -1,4 +1,4 @@ -/* $Id: Scanner.cpp,v 1.18 2003/10/04 12:12:48 titer Exp $ +/* $Id: Scanner.cpp,v 1.23 2003/10/13 14:12:18 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -20,21 +20,23 @@ extern "C" { } HBScanner::HBScanner( HBManager * manager, char * device ) - : HBThread( "scanner" ) + : HBThread( "scanner", HB_NORMAL_PRIORITY ) { fManager = manager; fDevice = strdup( device ); + + Run(); } void HBScanner::DoWork() { - Log( "HBScanner::DoWork() : opening device %s", fDevice ); + Log( "HBScanner: opening device %s", fDevice ); dvdplay_ptr vmg; vmg = dvdplay_open( fDevice, NULL, NULL ); if( !vmg ) { - Log( "HBScanner::DoWork() : dvdplay_open() failed (%s)", + Log( "HBScanner: dvdplay_open() failed (%s)", fDevice ); fManager->ScanDone( NULL ); return; @@ -50,7 +52,7 @@ void HBScanner::DoWork() break; } - Log( "HBScanner::DoWork() : scanning title %d", i + 1 ); + Log( "HBScanner: scanning title %d", i + 1 ); fManager->Scanning( fDevice, i + 1 ); title = new HBTitle( fDevice, i + 1 ); @@ -61,12 +63,12 @@ void HBScanner::DoWork() } else { - Log( "HBScanner::DoWork() : ignoring title %d", i + 1 ); + Log( "HBScanner: ignoring title %d", i + 1 ); delete title; } } - Log( "HBScanner::DoWork() : closing device %s", fDevice ); + Log( "HBScanner: closing device %s", fDevice ); dvdplay_close( vmg ); fManager->ScanDone( titleList ); @@ -78,7 +80,7 @@ bool HBScanner::ScanTitle( HBTitle * title, dvdplay_ptr vmg ) /* Length */ title->fLength = dvdplay_title_time( vmg ); - Log( "HBScanner::ScanTitle() : title length is %lld seconds", + Log( "HBScanner::ScanTitle: title length is %lld seconds", title->fLength ); /* Discard titles under 10 seconds */ @@ -101,20 +103,46 @@ bool HBScanner::ScanTitle( HBTitle * title, dvdplay_ptr vmg ) } int id = dvdplay_audio_id( vmg, i ); - if( id > 0 ) + + if( id < 1 ) { - if( ( id & 0xFF ) != 0xBD ) + continue; + } + + if( ( id & 0xFF ) != 0xBD ) + { + Log( "HBScanner::ScanTitle: non-AC3 audio track " + "detected, ignoring" ); + continue; + } + + /* Check if we don't already found an track with the same id */ + audio = NULL; + for( uint32_t j = 0; j < title->fAudioList->CountItems(); j++ ) + { + audio = (HBAudio*) title->fAudioList->ItemAt( j ); + if( (uint32_t) id == audio->fId ) + { + break; + } + else { - Log( "HBScanner::ScanTitle() : non-AC3 audio track " - "detected, ignoring" ); - continue; + audio = NULL; } - attr = dvdplay_audio_attr( vmg, i ); - audio = new HBAudio( id, LanguageForCode( attr->lang_code ) ); - Log( "HBScanner::ScanTitle() : new language (%x, %s)", - id, audio->fDescription ); - title->fAudioList->AddItem( audio ); } + + if( audio ) + { + Log( "HBScanner::ScanTitle: discarding duplicate track %x", + id ); + continue; + } + + attr = dvdplay_audio_attr( vmg, i ); + audio = new HBAudio( id, LanguageForCode( attr->lang_code ) ); + Log( "HBScanner::ScanTitle: new language (%x, %s)", + id, audio->fDescription ); + title->fAudioList->AddItem( audio ); } /* Discard titles with no audio tracks */ @@ -206,7 +234,7 @@ bool HBScanner::DecodeFrame( HBTitle * title, dvdplay_ptr vmg, int i ) if( dvdplay_read( vmg, psBuffer->fData, 1 ) != 1 || !PStoES( psBuffer, &esBufferList ) ) { - Log( "HBScanner::DecodeFrame : failed to get " + Log( "HBScanner::DecodeFrame: failed to get " "a valid PS packet" ); mpeg2_close( handle ); fclose( file ); diff --git a/core/Thread.cpp b/core/Thread.cpp index 43f058cad..8f7e6c971 100644 --- a/core/Thread.cpp +++ b/core/Thread.cpp @@ -1,4 +1,4 @@ -/* $Id: Thread.cpp,v 1.19 2003/10/01 21:17:17 titer Exp $ +/* $Id: Thread.cpp,v 1.23 2003/10/09 23:33:36 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -34,61 +34,35 @@ HBThread::~HBThread() pthread_join( fThread, NULL ); #endif - Log( "Thread %d stopped (\"%s\")", fThread, fName ); + Log( "HBThread: thread %d stopped (\"%s\")", fThread, fName ); free( fName ); } -void HBThread::Run() +void HBThread::Suspend() { -#if defined( SYS_BEOS ) - fThread = spawn_thread( (int32 (*)(void *)) ThreadFunc, - fName, fPriority, this ); - resume_thread( fThread ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) - pthread_create( &fThread, NULL, - (void * (*)(void *)) ThreadFunc, this ); -#if 0 -#if defined( SYS_MACOSX ) - int policy; - struct sched_param param; - memset( ¶m, 0, sizeof( struct sched_param ) ); - if( fPriority < 0 ) - { - param.sched_priority = (-1) * fPriority; - policy = SCHED_OTHER; - } - else - { - param.sched_priority = fPriority; - policy = SCHED_RR; - } - if ( pthread_setschedparam( fThread, policy, ¶m ) ) - { - Log( "HBThread::Run : couldn't set thread priority" ); - } -#endif -#endif -#endif - - Log( "Thread %d started (\"%s\")", fThread, fName ); + fSuspend = true; } -void HBThread::Stop() +void HBThread::Resume() { - Log( "Stopping thread %d (\"%s\")", fThread, fName ); - - fDie = true; fSuspend = false; } -void HBThread::Suspend() +int HBThread::GetPid() { - fSuspend = true; + return fPid; } -void HBThread::Resume() +void HBThread::Run() { - fSuspend = false; +#if defined( SYS_BEOS ) + fThread = spawn_thread( (int32 (*)(void *)) ThreadFunc, + fName, fPriority, this ); + resume_thread( fThread ); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_create( &fThread, NULL, + (void * (*)(void *)) ThreadFunc, this ); +#endif } bool HBThread::Push( HBFifo * fifo, HBBuffer * buffer ) @@ -126,6 +100,21 @@ HBBuffer * HBThread::Pop( HBFifo * fifo ) void HBThread::ThreadFunc( HBThread * _this ) { +#if defined( SYS_MACOSX ) + struct sched_param param; + memset( ¶m, 0, sizeof( struct sched_param ) ); + param.sched_priority = _this->fPriority; + if ( pthread_setschedparam( _this->fThread, SCHED_OTHER, ¶m ) ) + { + Log( "HBThread: couldn't set thread priority" ); + } +#endif + + _this->fPid = (int) getpid(); + + Log( "HBThread: thread %d started (\"%s\")", + _this->fThread, _this->fName ); + _this->DoWork(); } diff --git a/core/Thread.h b/core/Thread.h index 6afd59f53..0a09fabc9 100644 --- a/core/Thread.h +++ b/core/Thread.h @@ -1,4 +1,4 @@ -/* $Id: Thread.h,v 1.16 2003/10/01 21:17:17 titer Exp $ +/* $Id: Thread.h,v 1.19 2003/10/09 16:03:51 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -13,8 +13,8 @@ # define HB_LOW_PRIORITY 5 # define HB_NORMAL_PRIORITY 10 #elif defined( SYS_MACOSX ) -# define HB_LOW_PRIORITY (-47) -# define HB_NORMAL_PRIORITY (-47) /* FIXME */ +# define HB_LOW_PRIORITY 0 +# define HB_NORMAL_PRIORITY 31 #elif defined( SYS_LINUX ) /* Actually unused */ # define HB_LOW_PRIORITY 0 @@ -27,12 +27,12 @@ class HBThread HBThread( char * name, int priority = HB_LOW_PRIORITY ); virtual ~HBThread(); - void Run(); - void Stop(); void Suspend(); void Resume(); + int GetPid(); protected: + void Run(); bool Push( HBFifo * fifo, HBBuffer * buffer ); HBBuffer * Pop( HBFifo * fifo ); @@ -51,6 +51,7 @@ class HBThread #elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) pthread_t fThread; #endif + int fPid; }; #if defined( SYS_BEOS ) diff --git a/core/Worker.cpp b/core/Worker.cpp new file mode 100644 index 000000000..5f1352026 --- /dev/null +++ b/core/Worker.cpp @@ -0,0 +1,150 @@ +/* $Id: Worker.cpp,v 1.9 2003/10/13 17:59:40 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://beos.titer.org/handbrake/>. + It may be used under the terms of the GNU General Public License. */ + +#include "Ac3Decoder.h" +#include "Mp3Encoder.h" +#include "Mpeg2Decoder.h" +#include "Mpeg4Encoder.h" +#include "MpegDemux.h" +#include "Resizer.h" +#include "Worker.h" + +HBWorker::HBWorker( HBTitle * title, HBAudio * audio1, + HBAudio * audio2 ) + : HBThread( "worker") +{ + fTitle = title; + fAudio1 = audio1; + fAudio2 = audio2; + + Run(); +} + +void HBWorker::DoWork() +{ + bool didSomething; + uint64_t mpegDemux = 0; + uint64_t mpeg2Decoder = 0; + uint64_t resizer = 0; + uint64_t mpeg4Encoder = 0; + uint64_t ac3Decoder1 = 0; + uint64_t mp3Encoder1 = 0; + uint64_t ac3Decoder2 = 0; + uint64_t mp3Encoder2 = 0; + uint64_t tmpDate; + + while( !fDie ) + { + didSomething = false; + + tmpDate = GetDate(); + if( fTitle->fMpegDemux->Work() ) + { + mpegDemux += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + tmpDate = GetDate(); + if( fTitle->fMpeg2Decoder->Work() ) + { + mpeg2Decoder += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + tmpDate = GetDate(); + if( fTitle->fResizer->Work() ) + { + resizer += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + tmpDate = GetDate(); + if( fTitle->fMpeg4Encoder->Work() ) + { + mpeg4Encoder += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + if( fAudio1 ) + { + tmpDate = GetDate(); + if( fAudio1->fAc3Decoder->Work() ) + { + ac3Decoder1 += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + tmpDate = GetDate(); + if( fAudio1->fMp3Encoder->Work() ) + { + mp3Encoder1 += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + } + + if( fAudio2 ) + { + tmpDate = GetDate(); + if( fAudio2->fAc3Decoder->Work() ) + { + ac3Decoder2 += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + tmpDate = GetDate(); + if( fAudio2->fMp3Encoder->Work() ) + { + mp3Encoder2 += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + } + + if( !didSomething ) + { + Snooze( 10000 ); + } + + while( fSuspend ) + { + Snooze( 10000 ); + } + } + + tmpDate = mpegDemux + mpeg2Decoder + resizer + mpeg4Encoder + + ac3Decoder1 + mp3Encoder1 + ac3Decoder2 + mp3Encoder2; + Log( "HBWorker stopped. CPU utilization:" ); + Log( "- MPEG demuxer: %.2f %%", 100 * (float) mpegDemux / tmpDate ); + Log( "- MPEG-2 decoder: %.2f %%", 100 * (float) mpeg2Decoder / tmpDate ); + Log( "- Resizer: %.2f %%", 100 * (float) resizer / tmpDate ); + Log( "- MPEG-4 encoder: %.2f %%", 100 * (float) mpeg4Encoder / tmpDate ); + if( fAudio1 ) + { + Log( "- AC3 decoder 1: %.2f %%", 100 * (float) ac3Decoder1 / tmpDate ); + Log( "- MP3 encoder 1: %.2f %%", 100 * (float) mp3Encoder1 / tmpDate ); + } + if( fAudio2 ) + { + Log( "- AC3 decoder 2: %.2f %%", 100 * (float) ac3Decoder2 / tmpDate ); + Log( "- MP3 encoder 2: %.2f %%", 100 * (float) mp3Encoder2 / tmpDate ); + } +} + diff --git a/core/Worker.h b/core/Worker.h new file mode 100644 index 000000000..d2d0324d8 --- /dev/null +++ b/core/Worker.h @@ -0,0 +1,27 @@ +/* $Id: Worker.h,v 1.1 2003/10/07 17:40:06 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://beos.titer.org/handbrake/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_WORKER_H +#define HB_WORKER_H + +#include "Common.h" +#include "Thread.h" + +class HBWorker : public HBThread +{ + public: + HBWorker( HBTitle * title, HBAudio * audio1, + HBAudio * audio2 ); + + private: + void DoWork(); + + HBTitle * fTitle; + HBAudio * fAudio1; + HBAudio * fAudio2; +}; + +#endif |