summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/Ac3Dec.c219
-rw-r--r--core/Ac3Dec.h15
-rw-r--r--core/Ac3Decoder.cpp204
-rw-r--r--core/Ac3Decoder.h47
-rw-r--r--core/AviMux.c640
-rw-r--r--core/AviMux.h15
-rw-r--r--core/AviMuxer.cpp481
-rw-r--r--core/AviMuxer.h153
-rw-r--r--core/Common.cpp288
-rw-r--r--core/Common.h215
-rw-r--r--core/DVDRead.c328
-rw-r--r--core/DVDRead.h16
-rw-r--r--core/DVDReader.cpp99
-rw-r--r--core/DVDReader.h25
-rw-r--r--core/FfmpegEnc.c230
-rw-r--r--core/FfmpegEnc.h15
-rw-r--r--core/Fifo.c105
-rw-r--r--core/Fifo.cpp120
-rw-r--r--core/Fifo.h100
-rw-r--r--core/HandBrake.c767
-rw-r--r--core/HandBrake.h55
-rw-r--r--core/HandBrakeInternal.h35
-rw-r--r--core/Languages.h6
-rw-r--r--core/MadDec.c9
-rw-r--r--core/MadDec.h15
-rw-r--r--core/Manager.cpp652
-rw-r--r--core/Manager.h64
-rw-r--r--core/Mp3Enc.c281
-rw-r--r--core/Mp3Enc.h15
-rw-r--r--core/Mp3Encoder.cpp185
-rw-r--r--core/Mp3Encoder.h43
-rw-r--r--core/Mpeg2Dec.c195
-rw-r--r--core/Mpeg2Dec.h15
-rw-r--r--core/Mpeg2Decoder.cpp175
-rw-r--r--core/Mpeg2Decoder.h40
-rw-r--r--core/Mpeg4Encoder.cpp181
-rw-r--r--core/Mpeg4Encoder.h41
-rw-r--r--core/MpegDemux.cpp308
-rw-r--r--core/MpegDemux.h43
-rw-r--r--core/Resizer.cpp138
-rw-r--r--core/Resizer.h38
-rw-r--r--core/Scale.c139
-rw-r--r--core/Scale.h15
-rw-r--r--core/Scan.c395
-rw-r--r--core/Scan.h15
-rw-r--r--core/Scanner.cpp303
-rw-r--r--core/Scanner.h27
-rw-r--r--core/Thread.c138
-rw-r--r--core/Thread.cpp160
-rw-r--r--core/Thread.h81
-rw-r--r--core/Utils.c352
-rw-r--r--core/Utils.h213
-rw-r--r--core/Work.c187
-rw-r--r--core/Work.h27
-rw-r--r--core/Worker.cpp150
-rw-r--r--core/Worker.h28
-rw-r--r--core/XvidEnc.c170
-rw-r--r--core/XvidEnc.h15
58 files changed, 4743 insertions, 4288 deletions
diff --git a/core/Ac3Dec.c b/core/Ac3Dec.c
new file mode 100644
index 000000000..d5430d49e
--- /dev/null
+++ b/core/Ac3Dec.c
@@ -0,0 +1,219 @@
+/* $Id: Ac3Dec.c,v 1.4 2003/11/04 20:16:44 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "Ac3Dec.h"
+#include "Fifo.h"
+#include "Work.h"
+
+#include <a52dec/a52.h>
+
+/* Local prototypes */
+static int Ac3DecWork( HBWork * );
+static int GetBytes( HBAc3Dec *, int );
+
+struct HBAc3Dec
+{
+ HB_WORK_COMMON_MEMBERS
+
+ HBHandle * handle;
+ HBAudio * audio;
+
+ /* liba52 stuff */
+ a52_state_t * state;
+ int inFlags;
+ int outFlags;
+ float sampleLevel;
+
+ /* Buffers */
+ uint8_t ac3Frame[3840]; /* Max size of a A52 frame */
+ int ac3FrameSize; /* In bytes */
+ HBBuffer * ac3Buffer;
+ int ac3BufferPos; /* In bytes */
+ int nextFrameSize; /* In bytes */
+ float position;
+ HBBuffer * rawBuffer;
+};
+
+HBAc3Dec * HBAc3DecInit( HBHandle * handle, HBAudio * audio )
+{
+ HBAc3Dec * a;
+ if( !( a = malloc( sizeof( HBAc3Dec ) ) ) )
+ {
+ HBLog( "HBAc3DecInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ a->name = strdup( "Ac3Dec" );
+ a->work = Ac3DecWork;
+
+ a->handle = handle;
+ a->audio = audio;
+
+ /* Init liba52 */
+ a->state = a52_init( 0 );
+ a->inFlags = 0;
+
+ /* Let it do the downmixing */
+ a->outFlags = A52_STEREO;
+
+ /* Lame wants samples from -32768 to 32768 */
+ a->sampleLevel = 32768.0;
+
+ a->ac3FrameSize = 0;
+ a->ac3Buffer = NULL;
+ a->ac3BufferPos = 0;
+ a->nextFrameSize = 0;
+ a->position = 0.0;
+ a->rawBuffer = NULL;
+
+ return a;
+}
+
+void HBAc3DecClose( HBAc3Dec ** _a )
+{
+ HBAc3Dec * a = *_a;
+
+ if( a->ac3Buffer ) HBBufferClose( &a->ac3Buffer );
+ if( a->rawBuffer ) HBBufferClose( &a->rawBuffer );
+ a52_free( a->state );
+ free( a->name );
+ free( a );
+
+ *_a = NULL;
+}
+
+static int Ac3DecWork( HBWork * w )
+{
+ HBAc3Dec * a = (HBAc3Dec*) w;
+ HBAudio * audio = a->audio;
+
+ int didSomething = 0;
+
+ /* Push decoded buffer */
+ if( a->rawBuffer )
+ {
+ if( HBFifoPush( audio->rawFifo, &a->rawBuffer ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+ }
+
+ /* Get a frame header (7 bytes) */
+ if( a->ac3FrameSize < 7 )
+ {
+ if( GetBytes( a, 7 ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+
+ a->nextFrameSize = a52_syncinfo( a->ac3Frame, &a->inFlags,
+ &audio->inSampleRate,
+ &audio->inBitrate );
+
+ if( !a->nextFrameSize )
+ {
+ HBLog( "HBAc3Dec: a52_syncinfo() failed" );
+ HBErrorOccured( a->handle, HB_ERROR_A52_SYNC );
+ return didSomething;
+ }
+ }
+
+ /* Get the whole frame */
+ if( a->ac3FrameSize >= 7 )
+ {
+ sample_t * samples;
+ HBBuffer * rawBuffer;
+ int i;
+
+ if( GetBytes( a, a->nextFrameSize ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+
+ /* Feed liba52 */
+ a52_frame( a->state, a->ac3Frame, &a->outFlags,
+ &a->sampleLevel, 0 );
+ a->ac3FrameSize = 0;
+
+ /* 6 blocks per frame, 256 samples per block, 2 channels */
+ rawBuffer = HBBufferInit( 12 * 256 * sizeof( float ) );
+ rawBuffer->position = a->position;
+
+ for( i = 0; i < 6; i++ )
+ {
+ /* Decode a block */
+ a52_block( a->state );
+
+ /* Get a pointer to the raw data */
+ samples = a52_samples( a->state );
+
+ /* Copy left channel data */
+ memcpy( rawBuffer->data + i * 256 * sizeof( float ),
+ samples,
+ 256 * sizeof( float ) );
+
+ /* Copy right channel data */
+ memcpy( rawBuffer->data + ( 6 + i ) * 256 * sizeof( float ),
+ samples + 256,
+ 256 * sizeof( float ) );
+ }
+
+ a->rawBuffer = rawBuffer;
+ }
+
+ return didSomething;
+}
+
+static int GetBytes( HBAc3Dec * a, int size )
+{
+ int i;
+
+ while( a->ac3FrameSize < size )
+ {
+ if( !a->ac3Buffer )
+ {
+ if( !( a->ac3Buffer = HBFifoPop( a->audio->ac3Fifo ) ) )
+ {
+ return 0;
+ }
+ a->ac3BufferPos = 0;
+ a->position = a->ac3Buffer->position;
+
+ if( a->ac3Buffer->last )
+ {
+ HBDone( a->handle );
+ }
+ }
+
+ i = MIN( size - a->ac3FrameSize,
+ a->ac3Buffer->size - a->ac3BufferPos );
+ memcpy( a->ac3Frame + a->ac3FrameSize,
+ a->ac3Buffer->data + a->ac3BufferPos,
+ i );
+ a->ac3FrameSize += i;
+ a->ac3BufferPos += i;
+
+ if( a->ac3BufferPos == a->ac3Buffer->size )
+ {
+ HBBufferClose( &a->ac3Buffer );
+ }
+ }
+
+ return 1;
+}
+
diff --git a/core/Ac3Dec.h b/core/Ac3Dec.h
new file mode 100644
index 000000000..a1ecaff66
--- /dev/null
+++ b/core/Ac3Dec.h
@@ -0,0 +1,15 @@
+/* $Id: Ac3Dec.h,v 1.1 2003/11/03 12:08:00 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_AC3_DEC_H
+#define HB_AC3_DEC_H
+
+#include "HandBrakeInternal.h"
+
+HBAc3Dec * HBAc3DecInit( HBHandle *, HBAudio * );
+void HBAc3DecClose( HBAc3Dec ** );
+
+#endif
diff --git a/core/Ac3Decoder.cpp b/core/Ac3Decoder.cpp
deleted file mode 100644
index 663184e40..000000000
--- a/core/Ac3Decoder.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/* $Id: Ac3Decoder.cpp,v 1.21 2003/10/14 14:35:20 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 "Fifo.h"
-#include "Manager.h"
-
-extern "C" {
-#include <a52dec/a52.h>
-}
-
-HBAc3Decoder::HBAc3Decoder( HBManager * manager, HBAudio * 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 );
- fAc3Frame->fSize = 0;
- fAc3Buffer = NULL;
- fPosInAc3Buffer = 0;
- fRawBuffer = NULL;
-}
-
-HBAc3Decoder::~HBAc3Decoder()
-{
- if( fRawBuffer ) delete fRawBuffer;
- if( fAc3Buffer ) delete fAc3Buffer;
- delete fAc3Frame;
- a52_free( fState );
- delete fLock;
-}
-
-bool HBAc3Decoder::Work()
-{
- if( !Lock() )
- {
- return false;
- }
-
- /* Push the latest decoded buffer */
- if( fRawBuffer )
- {
- if( fAudio->fRawFifo->Push( fRawBuffer ) )
- {
- fRawBuffer = NULL;
- }
- else
- {
- Unlock();
- return false;
- }
- }
-
- /* Get a frame header (7 bytes) */
- if( fAc3Frame->fSize < 7 )
- {
- if( GetBytes( 7 ) )
- {
- /* Get the size of the coming 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;
- }
- }
- else
- {
- Unlock();
- return false;
- }
- }
-
- /* In case the audio should start later than the video,
- insert some silence */
- if( fAudio->fDelay > 3 * 256 * 1000 / fAudio->fInSampleRate )
- {
- 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;
-
- Unlock();
- return true;
- }
-
- if( fAc3Frame->fSize >= 7 )
- {
- /* Get the whole frame */
- if( GetBytes( (uint32_t) fFrameSize ) )
- {
- /* Feed liba52 */
- a52_frame( fState, fAc3Frame->fData, &fOutFlags,
- &fSampleLevel, 0 );
- fAc3Frame->fSize = 0;
-
- /* 6 blocks per frame, 256 samples per block */
- fRawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) );
- fRawBuffer->fPosition = fPosition;
-
- sample_t * samples;
- for( int i = 0; i < 6; i++ )
- {
- /* Decode a block */
- a52_block( fState );
-
- /* Get a pointer to the raw data */
- samples = a52_samples( fState );
-
- /* Copy left channel data */
- memcpy( (float*) fRawBuffer->fData + i * 256,
- samples,
- 256 * sizeof( float ) );
-
- /* Copy right channel data */
- memcpy( (float*) fRawBuffer->fData + ( 6 + i ) * 256,
- samples + 256,
- 256 * sizeof( float ) );
- }
- }
- else
- {
- Unlock();
- return false;
- }
- }
-
- Unlock();
- return true;
-}
-
-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
- contains <size> bytes */
-bool HBAc3Decoder::GetBytes( uint32_t size )
-{
- while( fAc3Frame->fSize < size )
- {
- if( !fAc3Buffer )
- {
- if( !( fAc3Buffer = fAudio->fAc3Fifo->Pop() ) )
- {
- return false;
- }
- fPosInAc3Buffer = 0;
- fPosition = fAc3Buffer->fPosition;
- }
-
- int willCopy = MIN( size - fAc3Frame->fSize,
- fAc3Buffer->fSize - fPosInAc3Buffer );
- memcpy( fAc3Frame->fData + fAc3Frame->fSize,
- fAc3Buffer->fData + fPosInAc3Buffer,
- willCopy );
- fAc3Frame->fSize += willCopy;
- fPosInAc3Buffer += willCopy;
-
- if( fAc3Buffer->fSize == fPosInAc3Buffer )
- {
- delete fAc3Buffer;
- fAc3Buffer = NULL;
- }
- }
-
- return true;
-}
diff --git a/core/Ac3Decoder.h b/core/Ac3Decoder.h
deleted file mode 100644
index f63206b12..000000000
--- a/core/Ac3Decoder.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* $Id: Ac3Decoder.h,v 1.11 2003/10/14 14:35:20 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_AC3_DECODER_H
-#define HB_AC3_DECODER_H
-
-#include "Common.h"
-
-class HBAc3Decoder
-{
- public:
- HBAc3Decoder( HBManager * manager,
- HBAudio * audio );
- ~HBAc3Decoder();
- bool Work();
-
- private:
- 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 fPosInAc3Buffer;
- HBBuffer * fRawBuffer;
-
- float fPosition;
- int fFrameSize;
-};
-
-#endif
diff --git a/core/AviMux.c b/core/AviMux.c
new file mode 100644
index 000000000..bd0551217
--- /dev/null
+++ b/core/AviMux.c
@@ -0,0 +1,640 @@
+/* $Id: AviMux.c,v 1.5 2003/11/06 18:35:53 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "AviMux.h"
+#include "Fifo.h"
+#include "Thread.h"
+
+/* Local structures */
+typedef struct AviMainHeader AviMainHeader;
+typedef struct AviStreamHeader AviStreamHeader;
+typedef struct BitmapInfo BitmapInfo;
+typedef struct WaveFormatEx WaveFormatEx;
+
+/* Local prototypes */
+static void AviMuxThread( void * );
+static void InitAviHeaders( HBAviMux * );
+static void AddChunk( HBAviMux *, HBBuffer **, uint32_t,
+ AviStreamHeader * );
+static void AddIndex( HBAviMux * );
+static void WriteInt8( FILE *, uint8_t );
+static void WriteInt16( FILE *, uint16_t );
+static void WriteInt32( FILE *, uint32_t );
+static void WriteBuffer( FILE *, HBBuffer * );
+static void WriteMainHeader( FILE *, AviMainHeader * );
+static void WriteStreamHeader( FILE *, AviStreamHeader * );
+static void WriteBitmapInfo( FILE *, BitmapInfo * );
+static void WriteWaveFormatEx( FILE *, WaveFormatEx * );
+static void IndexAddInt32( HBBuffer * buffer, uint32_t );
+static HBBuffer * Pop( HBAviMux *, HBFifo * );
+
+#define AVIF_HASINDEX 0x10
+#define AVIIF_KEYFRAME 0x10
+#define FOURCC(a) ((a[3]<<24)|(a[2]<<16)|(a[1]<<8)|a[0])
+
+/* Structures definitions */
+struct __attribute__((__packed__)) AviMainHeader
+{
+ uint32_t FourCC;
+ uint32_t BytesCount;
+ uint32_t MicroSecPerFrame;
+ uint32_t MaxBytesPerSec;
+ uint32_t PaddingGranularity;
+ uint32_t Flags;
+ uint32_t TotalFrames;
+ uint32_t InitialFrames;
+ uint32_t Streams;
+ uint32_t SuggestedBufferSize;
+ uint32_t Width;
+ uint32_t Height;
+ uint32_t Reserved[4];
+};
+
+struct __attribute__((__packed__)) AviStreamHeader
+{
+ uint32_t FourCC;
+ uint32_t BytesCount;
+ uint32_t Type;
+ uint32_t Handler;
+ uint32_t Flags;
+ uint16_t Priority;
+ uint16_t Language;
+ uint32_t InitialFrames;
+ uint32_t Scale;
+ uint32_t Rate;
+ uint32_t Start;
+ uint32_t Length;
+ uint32_t SuggestedBufferSize;
+ uint32_t Quality;
+ uint32_t SampleSize;
+ int16_t Left;
+ int16_t Top;
+ int16_t Right;
+ int16_t Bottom;
+};
+
+struct __attribute__((__packed__)) BitmapInfo
+{
+ uint32_t FourCC;
+ uint32_t BytesCount;
+ uint32_t Size;
+ uint32_t Width;
+ uint32_t Height;
+ uint16_t Planes;
+ uint16_t BitCount;
+ uint32_t Compression;
+ uint32_t SizeImage;
+ uint32_t XPelsPerMeter;
+ uint32_t YPelsPerMeter;
+ uint32_t ClrUsed;
+ uint32_t ClrImportant;
+ uint8_t Blue;
+ uint8_t Green;
+ uint8_t Red;
+ uint8_t Reserved;
+};
+
+struct __attribute__((__packed__)) WaveFormatEx
+{
+ uint32_t FourCC;
+ uint32_t BytesCount;
+ uint16_t FormatTag;
+ uint16_t Channels;
+ uint32_t SamplesPerSec;
+ uint32_t AvgBytesPerSec;
+ uint16_t BlockAlign;
+ uint16_t BitsPerSample;
+ uint16_t Size;
+
+ /* mp3 specific */
+ uint16_t Id;
+ uint32_t Flags;
+ uint16_t BlockSize;
+ uint16_t FramesPerBlock;
+ uint16_t CodecDelay;
+};
+
+struct HBAviMux
+{
+ HBHandle * handle;
+ HBTitle * title;
+ HBAudio * audio;
+ HBAudio * optAudio;
+
+ AviMainHeader mainHeader;
+ AviStreamHeader videoHeader;
+ BitmapInfo videoFormat;
+ AviStreamHeader audioHeader;
+ WaveFormatEx audioFormat;
+ AviStreamHeader optAudioHeader;
+ WaveFormatEx optAudioFormat;
+
+ /* Data size in bytes, not including headers */
+ unsigned size;
+ FILE * file;
+ HBBuffer * index;
+
+ int die;
+ HBThread * thread;
+};
+
+HBAviMux * HBAviMuxInit( HBHandle * handle, HBTitle * title,
+ HBAudio * audio, HBAudio * optAudio )
+{
+ HBAviMux * a;
+ if( !( a = malloc( sizeof( HBAviMux ) ) ) )
+ {
+ HBLog( "HBAviMuxInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ a->handle = handle;
+ a->title = title;
+ a->audio = audio;
+ a->optAudio = optAudio;
+
+ a->size = 0;
+ a->file = NULL;
+ a->index = HBBufferInit( 1024 * 1024 );
+ a->index->size = 0;
+
+ a->die = 0;
+ a->thread = HBThreadInit( "avi muxer", AviMuxThread, a,
+ HB_NORMAL_PRIORITY );
+ return a;
+}
+
+void HBAviMuxClose( HBAviMux ** _a )
+{
+ HBAviMux * a = *_a;
+
+ a->die = 1;
+ HBThreadClose( &a->thread );
+ free( a );
+
+ *_a = NULL;
+}
+
+static void AviMuxThread( void * _a )
+{
+ HBAviMux * a = (HBAviMux*) _a;
+ HBTitle * title = a->title;
+ HBAudio * audio = a->audio;
+ HBAudio * optAudio = a->optAudio;
+
+ HBBuffer * videoBuffer = NULL;
+ HBBuffer * audioBuffer = NULL;
+ HBBuffer * optAudioBuffer = NULL;
+
+ /* Open destination file */
+ HBLog( "HBAviMux: opening %s", title->file );
+ if( !( a->file = fopen( title->file, "w" ) ) )
+ {
+ HBLog( "HBAviMux: fopen() failed" );
+ HBErrorOccured( a->handle, HB_ERROR_AVI_WRITE );
+ return;
+ }
+
+ /* Get a buffer for each track */
+ videoBuffer = Pop( a, title->mpeg4Fifo );
+ audioBuffer = Pop( a, audio->mp3Fifo );
+ if( optAudio )
+ {
+ optAudioBuffer = Pop( a, optAudio->mp3Fifo );
+ }
+
+ /* Failed ? Then forget it */
+ if( !videoBuffer || !audioBuffer ||
+ ( optAudio && !optAudioBuffer ) )
+ {
+ fclose( a->file );
+ a->file = NULL;
+
+ HBLog( "HBAviMux: deleting %s", title->file );
+ unlink( title->file );
+ return;
+ }
+
+ InitAviHeaders( a );
+
+ for( ;; )
+ {
+ /* Get a buffer for each track */
+ if( !videoBuffer )
+ {
+ videoBuffer = Pop( a, title->mpeg4Fifo );
+ }
+ if( !audioBuffer )
+ {
+ audioBuffer = Pop( a, audio->mp3Fifo );
+ }
+ if( optAudio && !optAudioBuffer )
+ {
+ optAudioBuffer = Pop( a, optAudio->mp3Fifo );
+ }
+
+ if( !videoBuffer && !audioBuffer && !optAudioBuffer )
+ {
+ /* Couldn't get anything -> must exit NOW */
+ break;
+ }
+
+ /* Interleave frames in the same order than they were in the
+ original MPEG stream */
+ if( videoBuffer &&
+ ( !audioBuffer ||
+ videoBuffer->position < audioBuffer->position ) &&
+ ( !optAudioBuffer ||
+ videoBuffer->position < optAudioBuffer->position ) )
+ {
+ AddChunk( a, &videoBuffer, FOURCC( "00dc" ),
+ &a->videoHeader );
+ }
+ else if( audioBuffer &&
+ ( !optAudioBuffer ||
+ audioBuffer->position < optAudioBuffer->position ) )
+ {
+ AddChunk( a, &audioBuffer, FOURCC( "01wb" ),
+ &a->audioHeader );
+ }
+ else
+ {
+ AddChunk( a, &optAudioBuffer, FOURCC( "02wb" ),
+ &a->optAudioHeader );
+ }
+ }
+
+ AddIndex( a );
+
+ HBLog( "HBAviMux: closing %s", title->file );
+ fclose( a->file );
+}
+
+static void InitAviHeaders( HBAviMux * a )
+{
+ HBTitle * title = a->title;
+ HBAudio * audio = a->audio;
+ HBAudio * optAudio = a->optAudio;
+ AviMainHeader * mainHeader = &a->mainHeader;
+ AviStreamHeader * videoHeader = &a->videoHeader;
+ BitmapInfo * videoFormat = &a->videoFormat;
+ AviStreamHeader * audioHeader = &a->audioHeader;
+ WaveFormatEx * audioFormat = &a->audioFormat;
+ AviStreamHeader * optAudioHeader = &a->optAudioHeader;
+ WaveFormatEx * optAudioFormat = &a->optAudioFormat;
+ FILE * file = a->file;
+ int hdrlBytes;
+ int i;
+
+ /* AVI main header */
+ memset( mainHeader, 0, sizeof( AviMainHeader ) );
+ mainHeader->FourCC = FOURCC( "avih" );
+ mainHeader->BytesCount = sizeof( AviMainHeader ) - 8;
+ mainHeader->MicroSecPerFrame = (uint64_t) 1000000 *
+ title->rateBase / title->rate;
+ mainHeader->Streams = optAudio ? 3 : 2;
+ mainHeader->Width = title->outWidth;
+ mainHeader->Height = title->outHeight;
+
+ /* Video stream header */
+ memset( videoHeader, 0, sizeof( AviStreamHeader ) );
+ videoHeader->FourCC = FOURCC( "strh" );
+ videoHeader->BytesCount = sizeof( AviStreamHeader ) - 8;
+ videoHeader->Type = FOURCC( "vids" );
+
+ if( title->codec == HB_CODEC_FFMPEG )
+ videoHeader->Handler = FOURCC( "divx" );
+ else if( title->codec == HB_CODEC_XVID )
+ videoHeader->Handler = FOURCC( "xvid" );
+
+ videoHeader->Scale = title->rateBase;
+ videoHeader->Rate = title->rate;
+
+ /* Video stream format */
+ memset( videoFormat, 0, sizeof( BitmapInfo ) );
+ videoFormat->FourCC = FOURCC( "strf" );
+ videoFormat->BytesCount = sizeof( BitmapInfo ) - 8;
+ videoFormat->Size = sizeof( BitmapInfo ) - 8;
+ videoFormat->Width = title->outWidth;
+ videoFormat->Height = title->outHeight;
+ videoFormat->Planes = 1;
+ videoFormat->BitCount = 24;
+ if( title->codec == HB_CODEC_FFMPEG )
+ videoFormat->Compression = FOURCC( "DX50" );
+ else if( title->codec == HB_CODEC_XVID )
+ videoFormat->Compression = FOURCC( "XVID" );
+
+ /* Audio stream header */
+ memset( audioHeader, 0, sizeof( AviStreamHeader ) );
+ audioHeader->FourCC = FOURCC( "strh" );
+ audioHeader->BytesCount = sizeof( AviStreamHeader ) - 8;
+ audioHeader->Type = FOURCC( "auds" );
+ audioHeader->InitialFrames = 1;
+ audioHeader->Scale = 1152;
+ audioHeader->Rate = audio->outSampleRate;
+ audioHeader->Quality = 0xFFFFFFFF;
+
+ /* Audio stream format */
+ memset( audioFormat, 0, sizeof( WaveFormatEx ) );
+ audioFormat->FourCC = FOURCC( "strf" );
+ audioFormat->BytesCount = sizeof( WaveFormatEx ) - 8;
+ audioFormat->FormatTag = 0x55;
+ audioFormat->Channels = 2;
+ audioFormat->SamplesPerSec = audio->outSampleRate;
+ audioFormat->AvgBytesPerSec = audio->outBitrate * 1024 / 8;
+ audioFormat->BlockAlign = 1152;
+ audioFormat->Size = 12;
+ audioFormat->Id = 1;
+ audioFormat->Flags = 2;
+ audioFormat->BlockSize = 1152;
+ audioFormat->FramesPerBlock = 1;
+ audioFormat->CodecDelay = 1393;
+
+ if( optAudio )
+ {
+ /* optAudio stream header */
+ memset( optAudioHeader, 0, sizeof( AviStreamHeader ) );
+ optAudioHeader->FourCC = FOURCC( "strh" );
+ optAudioHeader->BytesCount = sizeof( AviStreamHeader ) - 8;
+ optAudioHeader->Type = FOURCC( "auds" );
+ optAudioHeader->InitialFrames = 1;
+ optAudioHeader->Scale = 1152;
+ optAudioHeader->Rate = optAudio->outSampleRate;
+ optAudioHeader->Quality = 0xFFFFFFFF;
+
+ /* optAudio stream format */
+ memset( optAudioFormat, 0, sizeof( WaveFormatEx ) );
+ optAudioFormat->FourCC = FOURCC( "strf" );
+ optAudioFormat->BytesCount = sizeof( WaveFormatEx ) - 8;
+ optAudioFormat->FormatTag = 0x55;
+ optAudioFormat->Channels = 2;
+ optAudioFormat->SamplesPerSec = optAudio->outSampleRate;
+ optAudioFormat->AvgBytesPerSec = optAudio->outBitrate * 1024 / 8;
+ optAudioFormat->BlockAlign = 1152;
+ optAudioFormat->Size = 12;
+ optAudioFormat->Id = 1;
+ optAudioFormat->Flags = 2;
+ optAudioFormat->BlockSize = 1152;
+ optAudioFormat->FramesPerBlock = 1;
+ optAudioFormat->CodecDelay = 1393;
+ }
+
+ hdrlBytes = 4 + sizeof( AviMainHeader ) +
+ ( optAudio ? 3 : 2 ) * ( 12 + sizeof( AviStreamHeader ) ) +
+ sizeof( BitmapInfo ) +
+ ( optAudio ? 2 : 1 ) * sizeof( WaveFormatEx );
+
+ /* Here we really start to write into the file */
+
+ WriteInt32( file, FOURCC( "RIFF" ) );
+ WriteInt32( file, 2040 );
+ WriteInt32( file, FOURCC( "AVI " ) );
+ WriteInt32( file, FOURCC( "LIST" ) );
+ WriteInt32( file, hdrlBytes );
+ WriteInt32( file, FOURCC( "hdrl" ) );
+ WriteMainHeader( file, mainHeader );
+ WriteInt32( file, FOURCC( "LIST" ) );
+ WriteInt32( file, 4 + sizeof( AviStreamHeader ) +
+ sizeof( BitmapInfo ) );
+ WriteInt32( file, FOURCC( "strl" ) );
+ WriteStreamHeader( file, videoHeader );
+ WriteBitmapInfo( file, videoFormat );
+ WriteInt32( file, FOURCC( "LIST" ) );
+ WriteInt32( file, 4 + sizeof( AviStreamHeader ) +
+ sizeof( WaveFormatEx ) );
+ WriteInt32( file, FOURCC( "strl" ) );
+ WriteStreamHeader( file, audioHeader );
+ WriteWaveFormatEx( file, audioFormat );
+ if( optAudio )
+ {
+ WriteInt32( file, FOURCC( "LIST" ) );
+ WriteInt32( file, 4 + sizeof( AviStreamHeader ) +
+ sizeof( WaveFormatEx ) );
+ WriteInt32( file, FOURCC( "strl" ) );
+ WriteStreamHeader( file, optAudioHeader );
+ WriteWaveFormatEx( file, optAudioFormat );
+ }
+ WriteInt32( file, FOURCC( "JUNK" ) );
+ WriteInt32( file, 2008 - hdrlBytes );
+ for( i = 0; i < 2008 - hdrlBytes; i++ )
+ {
+ WriteInt8( file, 0 );
+ }
+ WriteInt32( file, FOURCC( "LIST" ) );
+ WriteInt32( file, 4 );
+ WriteInt32( file, FOURCC( "movi" ) );
+}
+
+static void AddChunk( HBAviMux * a, HBBuffer ** _buffer,
+ uint32_t fourCC, AviStreamHeader * header )
+{
+ HBBuffer * buffer = *_buffer;
+
+ /* Update index */
+ IndexAddInt32( a->index, fourCC );
+ IndexAddInt32( a->index, buffer->keyFrame ? AVIIF_KEYFRAME : 0 );
+ IndexAddInt32( a->index, 4 + a->size );
+ IndexAddInt32( a->index, buffer->size );
+
+ /* Write the chunk to the file */
+ fseek( a->file, 0, SEEK_END );
+ WriteInt32( a->file, fourCC );
+ WriteInt32( a->file, buffer->size );
+ WriteBuffer( a->file, buffer );
+
+ /* Chunks must be 2-bytes aligned */
+ if( buffer->size & 1 )
+ {
+ WriteInt8( a->file, 0 );
+ }
+
+ /* Update headers */
+ a->size += 8 + EVEN( buffer->size );
+ header->Length++;
+
+ /* RIFF size */
+ fseek( a->file, 4, SEEK_SET );
+ WriteInt32( a->file, 2040 + a->size );
+
+ /* AviStreamHeader's length */
+ fseek( a->file, 140, SEEK_SET );
+ WriteInt32( a->file, a->videoHeader.Length );
+ fseek( a->file, 268, SEEK_SET );
+ WriteInt32( a->file, a->audioHeader.Length );
+ if( a->optAudio )
+ {
+ fseek( a->file, 382, SEEK_SET );
+ WriteInt32( a->file, a->optAudioHeader.Length );
+ }
+
+ /* movi size */
+ fseek( a->file, 2040, SEEK_SET );
+ WriteInt32( a->file, 4 + a->size );
+
+ HBBufferClose( _buffer );
+}
+
+static void AddIndex( HBAviMux * a )
+{
+ fseek( a->file, 0, SEEK_END );
+
+ WriteInt32( a->file, FOURCC( "idx1" ) );
+ WriteInt32( a->file, a->index->size );
+ WriteBuffer( a->file, a->index );
+
+ a->size += 8 + a->index->size;
+ fseek( a->file, 4, SEEK_SET );
+ WriteInt32( a->file, 2040 + a->size );
+ a->mainHeader.Flags |= AVIF_HASINDEX;
+ fseek( a->file, 24, SEEK_SET );
+ WriteMainHeader( a->file, &a->mainHeader );
+}
+
+static void WriteInt8( FILE * file, uint8_t val )
+{
+ fputc( val, file );
+}
+
+static void WriteInt16( FILE * file, uint16_t val )
+{
+ fputc( val & 0xFF, file );
+ fputc( val >> 8, file );
+}
+
+static void WriteInt32( FILE * file, uint32_t val )
+{
+ fputc( val & 0xFF, file );
+ fputc( ( val >> 8 ) & 0xFF, file );
+ fputc( ( val >> 16 ) & 0xFF, file );
+ fputc( val >> 24, file );
+}
+
+static void WriteBuffer( FILE * file, HBBuffer * buffer )
+{
+ fwrite( buffer->data, buffer->size, 1, file );
+}
+
+static void WriteBitmapInfo( FILE * file, BitmapInfo * bitmapInfo )
+{
+ WriteInt32( file, bitmapInfo->FourCC );
+ WriteInt32( file, bitmapInfo->BytesCount );
+ WriteInt32( file, bitmapInfo->Size );
+ WriteInt32( file, bitmapInfo->Width );
+ WriteInt32( file, bitmapInfo->Height );
+ WriteInt16( file, bitmapInfo->Planes );
+ WriteInt16( file, bitmapInfo->BitCount );
+ WriteInt32( file, bitmapInfo->Compression );
+ WriteInt32( file, bitmapInfo->SizeImage );
+ WriteInt32( file, bitmapInfo->XPelsPerMeter );
+ WriteInt32( file, bitmapInfo->YPelsPerMeter );
+ WriteInt32( file, bitmapInfo->ClrUsed );
+ WriteInt32( file, bitmapInfo->ClrImportant );
+ WriteInt8( file, bitmapInfo->Blue );
+ WriteInt8( file, bitmapInfo->Green );
+ WriteInt8( file, bitmapInfo->Red );
+ WriteInt8( file, bitmapInfo->Reserved );
+}
+
+static void WriteWaveFormatEx( FILE * file, WaveFormatEx * waveFormatEx )
+{
+ WriteInt32( file, waveFormatEx->FourCC );
+ WriteInt32( file, waveFormatEx->BytesCount );
+ WriteInt16( file, waveFormatEx->FormatTag );
+ WriteInt16( file, waveFormatEx->Channels );
+ WriteInt32( file, waveFormatEx->SamplesPerSec );
+ WriteInt32( file, waveFormatEx->AvgBytesPerSec );
+ WriteInt16( file, waveFormatEx->BlockAlign );
+ WriteInt16( file, waveFormatEx->BitsPerSample );
+ WriteInt16( file, waveFormatEx->Size );
+ WriteInt16( file, waveFormatEx->Id );
+ WriteInt32( file, waveFormatEx->Flags );
+ WriteInt16( file, waveFormatEx->BlockSize );
+ WriteInt16( file, waveFormatEx->FramesPerBlock );
+ WriteInt16( file, waveFormatEx->CodecDelay );
+}
+
+static void WriteMainHeader( FILE * file, AviMainHeader * mainHeader )
+{
+ WriteInt32( file, mainHeader->FourCC );
+ WriteInt32( file, mainHeader->BytesCount );
+ WriteInt32( file, mainHeader->MicroSecPerFrame );
+ WriteInt32( file, mainHeader->MaxBytesPerSec );
+ WriteInt32( file, mainHeader->PaddingGranularity );
+ WriteInt32( file, mainHeader->Flags );
+ WriteInt32( file, mainHeader->TotalFrames );
+ WriteInt32( file, mainHeader->InitialFrames );
+ WriteInt32( file, mainHeader->Streams );
+ WriteInt32( file, mainHeader->SuggestedBufferSize );
+ WriteInt32( file, mainHeader->Width );
+ WriteInt32( file, mainHeader->Height );
+ WriteInt32( file, mainHeader->Reserved[0] );
+ WriteInt32( file, mainHeader->Reserved[1] );
+ WriteInt32( file, mainHeader->Reserved[2] );
+ WriteInt32( file, mainHeader->Reserved[3] );
+}
+
+static void WriteStreamHeader( FILE * file, AviStreamHeader * streamHeader )
+{
+ WriteInt32( file, streamHeader->FourCC );
+ WriteInt32( file, streamHeader->BytesCount );
+ WriteInt32( file, streamHeader->Type );
+ WriteInt32( file, streamHeader->Handler );
+ WriteInt32( file, streamHeader->Flags );
+ WriteInt16( file, streamHeader->Priority );
+ WriteInt16( file, streamHeader->Language );
+ WriteInt32( file, streamHeader->InitialFrames );
+ WriteInt32( file, streamHeader->Scale );
+ WriteInt32( file, streamHeader->Rate );
+ WriteInt32( file, streamHeader->Start );
+ WriteInt32( file, streamHeader->Length );
+ WriteInt32( file, streamHeader->SuggestedBufferSize );
+ WriteInt32( file, streamHeader->Quality );
+ WriteInt32( file, streamHeader->SampleSize );
+ WriteInt16( file, streamHeader->Left );
+ WriteInt16( file, streamHeader->Top );
+ WriteInt16( file, streamHeader->Right );
+ WriteInt16( file, streamHeader->Bottom );
+}
+
+static void IndexAddInt32( HBBuffer * b, uint32_t val )
+{
+ if( b->size + 16 > b->alloc )
+ {
+ HBLog( "HBAviMux: reallocing index (%d MB)",
+ 1 + b->alloc / 1024 / 1024 );
+ HBBufferReAlloc( b, b->alloc + 1024 + 1024 );
+ }
+
+ b->data[b->size++] = val & 0xFF;
+ b->data[b->size++] = ( val >> 8 ) & 0xFF;
+ b->data[b->size++] = ( val >> 16 ) & 0xFF;
+ b->data[b->size++] = val >> 24;
+}
+
+static HBBuffer * Pop( HBAviMux * a, HBFifo * fifo )
+{
+ HBBuffer * buffer;
+
+ for( ;; )
+ {
+ HBCheckPaused( a->handle );
+
+ if( ( buffer = HBFifoPop( fifo ) ) )
+ {
+ return buffer;
+ }
+
+ if( a->die )
+ {
+ break;
+ }
+
+ HBSnooze( 10000 );
+ }
+
+ return NULL;
+}
+
diff --git a/core/AviMux.h b/core/AviMux.h
new file mode 100644
index 000000000..1fccbe971
--- /dev/null
+++ b/core/AviMux.h
@@ -0,0 +1,15 @@
+/* $Id: AviMux.h,v 1.1 2003/11/03 12:08:00 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_AVI_MUX_H
+#define HB_AVI_MUX_H
+
+#include "HandBrakeInternal.h"
+
+HBAviMux * HBAviMuxInit( HBHandle *, HBTitle *, HBAudio *, HBAudio * );
+void HBAviMuxClose( HBAviMux ** );
+
+#endif
diff --git a/core/AviMuxer.cpp b/core/AviMuxer.cpp
deleted file mode 100644
index 4a84fe8b8..000000000
--- a/core/AviMuxer.cpp
+++ /dev/null
@@ -1,481 +0,0 @@
-/* $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/>.
- It may be used under the terms of the GNU General Public License. */
-
-#include "AviMuxer.h"
-#include "Manager.h"
-
-#define AVIF_HASINDEX 0x10
-#define AVIIF_KEYFRAME 0x10
-
-#define FOURCC(a) ( ( a[3] << 24 ) | ( a[2] << 16 ) | ( a[1] << 8 ) | a[0] )
-
-/* TODO : check return values from fputc/fwrite in case disk is full
- or something */
-
-void WriteInt8( FILE * file, uint8_t val )
-{
- fputc( val, file );
-}
-
-void WriteInt16( FILE * file, uint16_t val )
-{
- fputc( val & 0xFF, file );
- fputc( val >> 8, file );
-}
-
-void WriteInt32( FILE * file, uint32_t val )
-{
- fputc( val & 0xFF, file );
- fputc( ( val >> 8 ) & 0xFF, file );
- fputc( ( val >> 16 ) & 0xFF, file );
- fputc( val >> 24, file );
-}
-
-void WriteBuffer( FILE * file, HBBuffer * buffer )
-{
- fwrite( buffer->fData, buffer->fSize, 1, file );
-}
-
-void WriteBitmapInfo( FILE * file, BitmapInfo * bitmapInfo )
-{
- WriteInt32( file, bitmapInfo->FourCC );
- WriteInt32( file, bitmapInfo->BytesCount );
- WriteInt32( file, bitmapInfo->Size );
- WriteInt32( file, bitmapInfo->Width );
- WriteInt32( file, bitmapInfo->Height );
- WriteInt16( file, bitmapInfo->Planes );
- WriteInt16( file, bitmapInfo->BitCount );
- WriteInt32( file, bitmapInfo->Compression );
- WriteInt32( file, bitmapInfo->SizeImage );
- WriteInt32( file, bitmapInfo->XPelsPerMeter );
- WriteInt32( file, bitmapInfo->YPelsPerMeter );
- WriteInt32( file, bitmapInfo->ClrUsed );
- WriteInt32( file, bitmapInfo->ClrImportant );
- WriteInt8( file, bitmapInfo->Blue );
- WriteInt8( file, bitmapInfo->Green );
- WriteInt8( file, bitmapInfo->Red );
- WriteInt8( file, bitmapInfo->Reserved );
-}
-
-void WriteWaveFormatEx( FILE * file, WaveFormatEx * waveFormatEx )
-{
- WriteInt32( file, waveFormatEx->FourCC );
- WriteInt32( file, waveFormatEx->BytesCount );
- WriteInt16( file, waveFormatEx->FormatTag );
- WriteInt16( file, waveFormatEx->Channels );
- WriteInt32( file, waveFormatEx->SamplesPerSec );
- WriteInt32( file, waveFormatEx->AvgBytesPerSec );
- WriteInt16( file, waveFormatEx->BlockAlign );
- WriteInt16( file, waveFormatEx->BitsPerSample );
- WriteInt16( file, waveFormatEx->Size );
- WriteInt16( file, waveFormatEx->Id );
- WriteInt32( file, waveFormatEx->Flags );
- WriteInt16( file, waveFormatEx->BlockSize );
- WriteInt16( file, waveFormatEx->FramesPerBlock );
- WriteInt16( file, waveFormatEx->CodecDelay );
-}
-
-void WriteMainHeader( FILE * file, AviMainHeader * mainHeader )
-{
- WriteInt32( file, mainHeader->FourCC );
- WriteInt32( file, mainHeader->BytesCount );
- WriteInt32( file, mainHeader->MicroSecPerFrame );
- WriteInt32( file, mainHeader->MaxBytesPerSec );
- WriteInt32( file, mainHeader->PaddingGranularity );
- WriteInt32( file, mainHeader->Flags );
- WriteInt32( file, mainHeader->TotalFrames );
- WriteInt32( file, mainHeader->InitialFrames );
- WriteInt32( file, mainHeader->Streams );
- WriteInt32( file, mainHeader->SuggestedBufferSize );
- WriteInt32( file, mainHeader->Width );
- WriteInt32( file, mainHeader->Height );
- WriteInt32( file, mainHeader->Reserved[0] );
- WriteInt32( file, mainHeader->Reserved[1] );
- WriteInt32( file, mainHeader->Reserved[2] );
- WriteInt32( file, mainHeader->Reserved[3] );
-}
-
-void WriteStreamHeader( FILE * file, AviStreamHeader * streamHeader )
-{
- WriteInt32( file, streamHeader->FourCC );
- WriteInt32( file, streamHeader->BytesCount );
- WriteInt32( file, streamHeader->Type );
- WriteInt32( file, streamHeader->Handler );
- WriteInt32( file, streamHeader->Flags );
- WriteInt16( file, streamHeader->Priority );
- WriteInt16( file, streamHeader->Language );
- WriteInt32( file, streamHeader->InitialFrames );
- WriteInt32( file, streamHeader->Scale );
- WriteInt32( file, streamHeader->Rate );
- WriteInt32( file, streamHeader->Start );
- WriteInt32( file, streamHeader->Length );
- WriteInt32( file, streamHeader->SuggestedBufferSize );
- WriteInt32( file, streamHeader->Quality );
- WriteInt32( file, streamHeader->SampleSize );
- WriteInt16( file, streamHeader->Left );
- WriteInt16( file, streamHeader->Top );
- WriteInt16( file, streamHeader->Right );
- WriteInt16( file, streamHeader->Bottom );
-}
-
-HBAviIndex::HBAviIndex( uint32_t size )
- : HBBuffer( size )
-{
- fSize = 0;
-}
-
-void HBAviIndex::WriteInt32( uint32_t val )
-{
- if( fSize + 16 > fAllocSize )
- {
- /* Realloc if needed */
- Log( "HBAviIndex::WriteInt32() : reallocing index (%d -> %d MB)",
- fAllocSize / ( 1024 * 1024 ),
- 1 + fAllocSize / ( 1024 * 1024 ) );
- ReAlloc( fAllocSize + 1024 * 1024 );
- }
-
- fData[fSize] = val & 0xFF;
- fData[fSize + 1] = ( val >> 8 ) & 0xFF;
- fData[fSize + 2] = ( val >> 16 ) & 0xFF;
- fData[fSize + 3] = val >> 24;
-
- fSize += 4;
-}
-
-HBAviMuxer::HBAviMuxer( HBManager * manager, HBTitle * title,
- HBAudio * audio1, HBAudio * audio2,
- char * fileName )
- : HBThread( "avimuxer", HB_NORMAL_PRIORITY )
-{
- fManager = manager;
- fTitle = title;
- fAudio1 = audio1;
- fAudio2 = audio2;
- fFileName = strdup( fileName );
-
- fVideoBuffer = NULL;
- fAudio1Buffer = NULL;
- fAudio2Buffer = NULL;
-
- fRiffBytesCount = 2040;
- fMoviBytesCount = 4;
-
- Run();
-}
-
-void HBAviMuxer::DoWork()
-{
- /* Open the destination file */
- if( !( fFile = fopen( fFileName, "w" ) ) )
- {
- Log( "HBAviMuxer: fopen failed" );
- fManager->Error( HB_ERROR_AVI_WRITE );
- return;
- }
-
- /* Initializations */
- memset( &fMainHeader, 0, sizeof( AviMainHeader ) );
- memset( &fVideoStreamHeader, 0, sizeof( AviStreamHeader ) );
- memset( &fAudio1StreamHeader, 0, sizeof( AviStreamHeader ) );
- memset( &fAudio2StreamHeader, 0, sizeof( AviStreamHeader ) );
- memset( &fVideoStreamFormat, 0, sizeof( BitmapInfo ) );
- memset( &fAudio1StreamFormat, 0, sizeof( WaveFormatEx ) );
- memset( &fAudio2StreamFormat, 0, sizeof( WaveFormatEx ) );
-
- /* Alloc an 1 MB index (to be realloced later if needed) */
- fIndex = new HBAviIndex( 1024 * 1024 );
-
- /* Main loop */
- for( ;; )
- {
- while( fSuspend )
- {
- Snooze( 10000 );
- }
-
- if( !fVideoBuffer )
- {
- fVideoBuffer = Pop( fTitle->fMpeg4Fifo );
- }
- if( fAudio1 && !fAudio1Buffer )
- {
- fAudio1Buffer = Pop( fAudio1->fMp3Fifo );
- }
- if( fAudio2 && !fAudio2Buffer )
- {
- fAudio2Buffer = Pop( fAudio2->fMp3Fifo );
- }
-
- if( !fVideoBuffer && !fAudio1Buffer && !fAudio2Buffer )
- {
- break;
- }
-
- if( fVideoBuffer &&
- ( !fAudio1Buffer ||
- fVideoBuffer->fPosition < fAudio1Buffer->fPosition ) &&
- ( !fAudio2Buffer ||
- fVideoBuffer->fPosition < fAudio2Buffer->fPosition ) )
- {
- AddVideoChunk();
- }
- else if( fAudio1Buffer &&
- ( !fAudio2Buffer ||
- fAudio1Buffer->fPosition < fAudio2Buffer->fPosition ) )
- {
- AddAudioChunk( 1 );
- }
- else
- {
- AddAudioChunk( 2 );
- }
- }
-
- /* Write the index */
- fseek( fFile, 0, SEEK_END );
- WriteInt32( fFile, FOURCC( "idx1" ) );
- WriteInt32( fFile, fIndex->fSize );
- WriteBuffer( fFile, fIndex );
-
- /* Update the headers */
- fRiffBytesCount += 8 + fIndex->fSize;
- fMainHeader.Flags |= AVIF_HASINDEX;
- UpdateMainHeader();
-
- delete fIndex;
-
- fclose( fFile );
-}
-
-bool HBAviMuxer::AddVideoChunk()
-{
- fRiffBytesCount += 8 + EVEN( fVideoBuffer->fSize );
- fMoviBytesCount += 8 + EVEN( fVideoBuffer->fSize );
-
- fMainHeader.MicroSecPerFrame = 1000000 * (uint64_t) fTitle->fScale /
- fTitle->fRate;
- fMainHeader.TotalFrames++;
- fMainHeader.Width = fTitle->fOutWidth;
- fMainHeader.Height = fTitle->fOutHeight;
-
- fVideoStreamHeader.FourCC = FOURCC( "strh" );
- fVideoStreamHeader.BytesCount = AVI_STREAM_HEADER_SIZE - 8;
- fVideoStreamHeader.Type = FOURCC( "vids" );
- fVideoStreamHeader.Handler = FOURCC( "DIVX" );
- fVideoStreamHeader.Scale = fTitle->fScale;
- fVideoStreamHeader.Rate = fTitle->fRate;
- fVideoStreamHeader.Length++;
-
- fVideoStreamFormat.FourCC = FOURCC( "strf" );
- fVideoStreamFormat.BytesCount = BITMAP_INFO_SIZE - 8;
- fVideoStreamFormat.Size = BITMAP_INFO_SIZE - 8;
- fVideoStreamFormat.Width = fTitle->fOutWidth;
- fVideoStreamFormat.Height = fTitle->fOutHeight;
- fVideoStreamFormat.Planes = 1;
- fVideoStreamFormat.BitCount = 24;
- fVideoStreamFormat.Compression = FOURCC( "DIVX" );;
-
- UpdateMainHeader();
-
- fseek( fFile, 0, SEEK_END );
-
- /* Update the index */
- fIndex->WriteInt32( FOURCC( "00dc" ) );
- fIndex->WriteInt32( fVideoBuffer->fKeyFrame ? AVIIF_KEYFRAME : 0 );
- fIndex->WriteInt32( ftell( fFile ) - 2044 );
- fIndex->WriteInt32( fVideoBuffer->fSize );
-
- /* Write the chunk */
- WriteInt32( fFile, FOURCC( "00dc" ) );
- WriteInt32( fFile, fVideoBuffer->fSize );
- WriteBuffer( fFile, fVideoBuffer );
-
- /* Chunks must be 2-bytes aligned */
- if( fVideoBuffer->fSize & 1 )
- {
- WriteInt8( fFile, 0 );
- }
-
- delete fVideoBuffer;
- fVideoBuffer = NULL;
-
- return true;
-}
-
-bool HBAviMuxer::AddAudioChunk( int track )
-{
- HBAudio * info;
- HBBuffer * buffer;
- AviStreamHeader * streamHeader;
- WaveFormatEx * streamFormat;
-
- if( track == 1 )
- {
- info = fAudio1;
- buffer = fAudio1Buffer;
- streamHeader = &fAudio1StreamHeader;
- streamFormat = &fAudio1StreamFormat;
- }
- else
- {
- info = fAudio2;
- buffer = fAudio2Buffer;
- streamHeader = &fAudio2StreamHeader;
- streamFormat = &fAudio2StreamFormat;
- }
-
- fRiffBytesCount += 8 + EVEN( buffer->fSize );
- fMoviBytesCount += 8 + EVEN( buffer->fSize );
-
- streamHeader->FourCC = FOURCC( "strh" );
- streamHeader->BytesCount = AVI_STREAM_HEADER_SIZE - 8;
- streamHeader->Type = FOURCC( "auds" );
- streamHeader->InitialFrames = 1;
- streamHeader->Scale = 1152;
- streamHeader->Rate = info->fOutSampleRate;
- streamHeader->Length++;
- streamHeader->Quality = 0xFFFFFFFF;
-
-
- streamFormat->FourCC = FOURCC( "strf" );
- streamFormat->BytesCount = WAVE_FORMAT_EX_SIZE - 8;
- streamFormat->FormatTag = 0x55;
- streamFormat->Channels = 2;
- streamFormat->SamplesPerSec = info->fOutSampleRate;
- streamFormat->AvgBytesPerSec = info->fOutBitrate * 1024 / 8;
- streamFormat->BlockAlign = 1152;
-
- /* stolen from libavformat/wav.c */
- streamFormat->Size = 12;
- streamFormat->Id = 1;
- streamFormat->Flags = 2;
- streamFormat->BlockSize = 1152;
- streamFormat->FramesPerBlock = 1;
- streamFormat->CodecDelay = 1393;
-
- UpdateMainHeader();
-
- fseek( fFile, 0, SEEK_END );
-
- /* Update the index */
- if( track == 1 )
- {
- fIndex->WriteInt32( FOURCC( "01wb" ) );
- }
- else
- {
- fIndex->WriteInt32( FOURCC( "02wb" ) );
- }
- fIndex->WriteInt32( buffer->fKeyFrame ? AVIIF_KEYFRAME : 0 );
- fIndex->WriteInt32( ftell( fFile ) - 2044 );
- fIndex->WriteInt32( buffer->fSize );
-
- /* Write the chunk */
- WriteInt32( fFile,
- ( track == 1 ) ? FOURCC( "01wb" ) : FOURCC( "02wb" ) );
- WriteInt32( fFile, buffer->fSize );
- WriteBuffer( fFile, buffer );
-
- /* Chunks must be 2-bytes aligned */
- if( buffer->fSize & 1 )
- {
- WriteInt8( fFile, 0 );
- }
-
- delete buffer;
- if( track == 1 )
- {
- fAudio1Buffer = NULL;
- }
- else
- {
- fAudio2Buffer = NULL;
- }
-
- return true;
-}
-
-void HBAviMuxer::UpdateMainHeader()
-{
- fMainHeader.FourCC = FOURCC( "avih" );
- fMainHeader.BytesCount = AVI_MAIN_HEADER_SIZE - 8;
- fMainHeader.Streams = 1 + ( fAudio1 ? 1 : 0 ) +
- ( fAudio2 ? 1 : 0 );
-
- fHdrlBytesCount = 4 + AVI_MAIN_HEADER_SIZE + 12 +
- AVI_STREAM_HEADER_SIZE + BITMAP_INFO_SIZE;
-
- if( fAudio1 )
- {
- fHdrlBytesCount += 12 + AVI_STREAM_HEADER_SIZE +
- WAVE_FORMAT_EX_SIZE;
- }
- if( fAudio2 )
- {
- fHdrlBytesCount += 12 + AVI_STREAM_HEADER_SIZE +
- WAVE_FORMAT_EX_SIZE;
- }
-
- fseek( fFile, 0, SEEK_SET );
- WriteInt32( fFile, FOURCC( "RIFF" ) );
- WriteInt32( fFile, fRiffBytesCount );
- WriteInt32( fFile, FOURCC( "AVI " ) );
- WriteInt32( fFile, FOURCC( "LIST" ) );
- WriteInt32( fFile, fHdrlBytesCount );
- WriteInt32( fFile, FOURCC( "hdrl" ) );
-
- WriteMainHeader( fFile, &fMainHeader );
-
- int strlSize;
- strlSize = 4 + AVI_STREAM_HEADER_SIZE + BITMAP_INFO_SIZE;
- WriteInt32( fFile, FOURCC( "LIST" ) );
- WriteInt32( fFile, strlSize );
- WriteInt32( fFile, FOURCC( "strl" ) );
-
- WriteStreamHeader( fFile, &fVideoStreamHeader );
- WriteBitmapInfo( fFile, &fVideoStreamFormat );
-
- if( fAudio1 )
- {
- strlSize = 4 + AVI_STREAM_HEADER_SIZE + WAVE_FORMAT_EX_SIZE;
- WriteInt32( fFile, FOURCC( "LIST" ) );
- WriteInt32( fFile, strlSize );
- WriteInt32( fFile, FOURCC( "strl" ) );
- WriteStreamHeader( fFile, &fAudio1StreamHeader );
- WriteWaveFormatEx( fFile, &fAudio1StreamFormat );
- }
-
- if( fAudio2 )
- {
- strlSize = 4 + AVI_STREAM_HEADER_SIZE + WAVE_FORMAT_EX_SIZE;
- WriteInt32( fFile, FOURCC( "LIST" ) );
- WriteInt32( fFile, strlSize );
- WriteInt32( fFile, FOURCC( "strl" ) );
- WriteStreamHeader( fFile, &fAudio2StreamHeader );
- WriteWaveFormatEx( fFile, &fAudio2StreamFormat );
- }
-
- /* a JUNK chunk to fill the free space.
- size = 2048 -/
- 12 ("RIFFxxxxAVI ") -
- 8 (hdrl's "LIS1Txxxx") -
- fHdrlBytesCount -
- 8 ("JUNKxxxx") -
- 12 ("LISTxxxxmovi) */
- int junkSize = 2008 - fHdrlBytesCount;
- WriteInt32( fFile, FOURCC( "JUNK" ) );
- WriteInt32( fFile, junkSize );
- for( uint32_t i = 0; i < 2008 - fHdrlBytesCount; i++ )
- {
- WriteInt8( fFile, 0 );
- }
-
- /* movi list */
- WriteInt32( fFile, FOURCC( "LIST" ) );
- WriteInt32( fFile, fMoviBytesCount );
- WriteInt32( fFile, FOURCC( "movi" ) );
-}
diff --git a/core/AviMuxer.h b/core/AviMuxer.h
deleted file mode 100644
index 842f7a87a..000000000
--- a/core/AviMuxer.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/* $Id: AviMuxer.h,v 1.10 2003/09/30 14:38:15 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_AVI_MUXER_H
-#define HB_AVI_MUXER_H
-
-#include "Common.h"
-#include "Fifo.h"
-#include "Thread.h"
-
-/* Misc structures used in AVI headers */
-#define BITMAP_INFO_SIZE 52
-typedef struct BitmapInfo
-{
- uint32_t FourCC;
- uint32_t BytesCount;
- uint32_t Size;
- uint32_t Width;
- uint32_t Height;
- uint16_t Planes;
- uint16_t BitCount;
- uint32_t Compression;
- uint32_t SizeImage;
- uint32_t XPelsPerMeter;
- uint32_t YPelsPerMeter;
- uint32_t ClrUsed;
- uint32_t ClrImportant;
- uint8_t Blue;
- uint8_t Green;
- uint8_t Red;
- uint8_t Reserved;
-} BitmapInfo;
-
-#define WAVE_FORMAT_EX_SIZE 38
-typedef struct WaveFormatEx
-{
- uint32_t FourCC;
- uint32_t BytesCount;
- uint16_t FormatTag;
- uint16_t Channels;
- uint32_t SamplesPerSec;
- uint32_t AvgBytesPerSec;
- uint16_t BlockAlign;
- uint16_t BitsPerSample;
- uint16_t Size;
-
- /* mp3 specific */
- uint16_t Id;
- uint32_t Flags;
- uint16_t BlockSize;
- uint16_t FramesPerBlock;
- uint16_t CodecDelay;
-} WaveFormatEx;
-
-#define AVI_STREAM_HEADER_SIZE 64
-typedef struct AviStreamHeader
-{
- uint32_t FourCC;
- uint32_t BytesCount;
- uint32_t Type;
- uint32_t Handler;
- uint32_t Flags;
- uint16_t Priority;
- uint16_t Language;
- uint32_t InitialFrames;
- uint32_t Scale;
- uint32_t Rate;
- uint32_t Start;
- uint32_t Length;
- uint32_t SuggestedBufferSize;
- uint32_t Quality;
- uint32_t SampleSize;
- int16_t Left;
- int16_t Top;
- int16_t Right;
- int16_t Bottom;
-} AviStreamHeader;
-
-#define AVI_MAIN_HEADER_SIZE 64
-typedef struct AviMainHeader
-{
- uint32_t FourCC;
- uint32_t BytesCount;
- uint32_t MicroSecPerFrame;
- uint32_t MaxBytesPerSec;
- uint32_t PaddingGranularity;
- uint32_t Flags;
- uint32_t TotalFrames;
- uint32_t InitialFrames;
- uint32_t Streams;
- uint32_t SuggestedBufferSize;
- uint32_t Width;
- uint32_t Height;
- uint32_t Reserved[4];
-} AviMainHeader;
-
-class HBAviIndex : public HBBuffer
-{
- public:
- HBAviIndex( uint32_t size );
- void WriteInt32( uint32_t val );
-};
-
-class HBAviMuxer : public HBThread
-{
- public:
- HBAviMuxer( HBManager * manager,
- HBTitle * title, HBAudio * audio1,
- HBAudio * audio2,
- char * fileName );
-
- private:
- void DoWork();
- bool AddVideoChunk();
- bool AddAudioChunk( int track );
- void UpdateMainHeader();
-
- HBManager * fManager;
- HBTitle * fTitle;
- HBAudio * fAudio1;
- HBAudio * fAudio2;
- char * fFileName;
-
- FILE * fFile;
- HBBuffer * fVideoBuffer;
- HBBuffer * fAudio1Buffer;
- HBBuffer * fAudio2Buffer;
-
- /* The main header */
- AviMainHeader fMainHeader;
-
- /* The video track */
- AviStreamHeader fVideoStreamHeader;
- BitmapInfo fVideoStreamFormat;
-
- /* The audio tracks */
- AviStreamHeader fAudio1StreamHeader;
- WaveFormatEx fAudio1StreamFormat;
- AviStreamHeader fAudio2StreamHeader;
- WaveFormatEx fAudio2StreamFormat;
-
- uint32_t fRiffBytesCount;
- uint32_t fHdrlBytesCount;
- uint32_t fMoviBytesCount;
-
- HBAviIndex * fIndex;
-
-};
-
-#endif
diff --git a/core/Common.cpp b/core/Common.cpp
deleted file mode 100644
index 4087a001d..000000000
--- a/core/Common.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-/* $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/>.
- It may be used under the terms of the GNU General Public License. */
-
-#if defined( SYS_BEOS )
-# include <OS.h>
-#endif
-
-#include "Common.h"
-#include "Fifo.h"
-#include "MpegDemux.h"
-#include "Languages.h"
-
-#include <stdarg.h>
-#include <time.h>
-#include <sys/time.h>
-#include <dvdread/ifo_types.h>
-#include <dvdplay/dvdplay.h>
-#include <dvdplay/info.h>
-#include <dvdplay/state.h>
-#include <dvdplay/nav.h>
-
-extern "C" {
-#include <mpeg2dec/mpeg2.h>
-}
-
-void Snooze( uint64_t time )
-{
-#if defined( SYS_BEOS )
- snooze( time );
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
- usleep( time );
-#endif
-}
-
-void Log( char * log, ... )
-{
- if( !getenv( "HB_DEBUG" ) )
- {
- return;
- }
-
- char string[1024];
-
- /* Show the time */
- time_t _now = time( NULL );
- struct tm * now = localtime( &_now );
- sprintf( string, "[%02d:%02d:%02d] ",
- now->tm_hour, now->tm_min, now->tm_sec );
-
- /* Convert the message to a string */
- va_list args;
- va_start( args, log );
- int ret = vsnprintf( string + 11, 1011, log, args );
- va_end( args );
-
- /* Add the end of line */
- string[ret+11] = '\n';
- string[ret+12] = '\0';
-
- /* Print it */
- fprintf( stderr, "%s", string );
-}
-
-char * LanguageForCode( int code )
-{
- char codeString[2];
- codeString[0] = ( code >> 8 ) & 0xFF;
- codeString[1] = code & 0xFF;
-
- iso639_lang_t * lang;
- for( lang = languages; lang->engName; lang++ )
- {
- if( !strncmp( lang->iso639_1, codeString, 2 ) )
- {
- if( *lang->nativeName )
- return lang->nativeName;
-
- return lang->engName;
- }
- }
-
- return "Unknown";
-}
-
-uint64_t GetDate()
-{
- struct timeval tv;
- gettimeofday( &tv, NULL );
- 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()
-{
- fItems = (void**) malloc( HBLIST_DEFAULT_SIZE * sizeof( void* ) );
- fAllocItems = HBLIST_DEFAULT_SIZE;
- fNbItems = 0;
-}
-
-HBList::~HBList()
-{
- free( fItems );
-}
-
-uint32_t HBList::CountItems()
-{
- return fNbItems;
-}
-
-void HBList::AddItem( void * item )
-{
- if( !item )
- {
- return;
- }
-
- if( fNbItems == fAllocItems )
- {
- fAllocItems += HBLIST_DEFAULT_SIZE;
- fItems = (void**) realloc( fItems, fAllocItems * sizeof( void* ) );
- }
-
- fItems[fNbItems] = item;
-
- fNbItems++;
-}
-
-void HBList::RemoveItem( void * item )
-{
- if( !item || !fNbItems )
- {
- return;
- }
-
- uint32_t i;
- for( i = 0; i < fNbItems; i++ )
- {
- if( fItems[i] == item )
- {
- break;
- }
- }
-
- if( fItems[i] != item )
- {
- Log( "HBList::RemoveItem() : item not in the list" );
- return;
- }
-
- for( ; i < fNbItems - 1; i++ )
- {
- fItems[i] = fItems[i+1];
- }
-
- fNbItems--;
-}
-
-void * HBList::ItemAt( uint32_t index )
-{
- if( index < fNbItems )
- {
- return fItems[index];
- }
-
- return NULL;
-}
-
-HBTitle::HBTitle( char * device, int index )
-{
- fDevice = strdup( device );
- fIndex = index;
-
- fAudioList = new HBList();
- fPSFifo = NULL;
- fMpeg2Fifo = NULL;
- fRawFifo = NULL;
- fMpeg4Fifo = NULL;
-
- fTopCrop = 0;
- fBottomCrop = 0;
- fLeftCrop = 0;
- fRightCrop = 0;
- fBitrate = 1024;
- fDeinterlace = false;
- fTwoPass = false;
-}
-
-HBTitle::~HBTitle()
-{
- HBAudio * audio;
-
- while( ( audio = (HBAudio*) fAudioList->ItemAt( 0 ) ) )
- {
- fAudioList->RemoveItem( audio );
- delete audio;
- }
- delete fAudioList;
-}
-
-/* Audio track */
-HBAudio::HBAudio( int id, char * description )
-{
- fId = id;
- fDescription = strdup( description );
- fOutSampleRate = 44100;
- fOutBitrate = 128;
-
- fAc3Fifo = NULL;
- fRawFifo = NULL;
- fMp3Fifo = NULL;
-}
-
-HBAudio::~HBAudio()
-{
- free( fDescription );
-}
diff --git a/core/Common.h b/core/Common.h
deleted file mode 100644
index 3c138e2a1..000000000
--- a/core/Common.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/* $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/>.
- It may be used under the terms of the GNU General Public License. */
-
-#ifndef HB_COMMON_H
-#define HB_COMMON_H
-
-/* Standard headers */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <inttypes.h>
-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;
-typedef struct AVFrame AVFrame;
-typedef struct AVCodecContext AVCodecContext;
-typedef struct ImgReSampleContext ImgReSampleContext;
-
-/* Classes */
-class HBAc3Decoder;
-class HBAudio;
-class HBAviIndex;
-class HBAviMuxer;
-class HBBuffer;
-class HBDVDReader;
-class HBFifo;
-class HBList;
-class HBLock;
-class HBManager;
-class HBMp3Encoder;
-class HBMpeg2Decoder;
-class HBMpeg4Encoder;
-class HBMpegDemux;
-class HBResizer;
-class HBScanner;
-class HBStatus;
-class HBThread;
-class HBTitle;
-class HBWorker;
-
-/* Handy macros */
-#ifndef MIN
-# define MIN( a, b ) ( ( (a) > (b) ) ? (b) : (a) )
-#endif
-#ifndef MAX
-# define MAX( a, b ) ( ( (a) > (b) ) ? (a) : (b) )
-#endif
-#define EVEN( a ) ( ( (a) & 0x1 ) ? ( (a) + 1 ) : (a) )
-#define MULTIPLE_16( a ) ( 16 * ( ( (a) + 8 ) / 16 ) )
-
-#define VOUT_ASPECT_FACTOR 432000
-
-/* Global prototypes */
-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 = 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:
- HBMode fMode;
-
- /* HB_MODE_SCANNING */
- char * fScannedVolume;
- int fScannedTitle;
-
- /* HB_MODE_SCANDONE */
- HBList * fTitleList;
-
- /* HB_MODE_ENCODING || HB_MODE_SUSPENDED */
- float fPosition;
- float fFrameRate;
- uint32_t fFrames;
- uint64_t fStartDate;
- uint32_t fRemainingTime; /* in seconds */
- uint64_t fSuspendDate;
-
- /* HB_MODE_ERROR */
- HBError fError;
-};
-
-class HBList
-{
- public:
- HBList();
- ~HBList();
- uint32_t CountItems();
- void AddItem( void * item );
- void RemoveItem( void * item );
- void * ItemAt( uint32_t index );
-
- private:
- void ** fItems;
- uint32_t fAllocItems;
- uint32_t fNbItems;
-};
-
-class HBAudio
-{
- public:
- HBAudio( int id, char * description );
- ~HBAudio();
-
- /* Ident */
- uint32_t fId;
- char * fDescription;
-
- /* Settings */
- int fInSampleRate;
- int fOutSampleRate;
- int fInBitrate;
- int fOutBitrate;
-
- int64_t fDelay; /* in ms */
-
- /* Fifos */
- HBFifo * fAc3Fifo;
- HBFifo * fRawFifo;
- HBFifo * fMp3Fifo;
-
- /* Threads */
- HBAc3Decoder * fAc3Decoder;
- HBMp3Encoder * fMp3Encoder;
-};
-
-class HBTitle
-{
- public:
- HBTitle( char * device, int index );
- ~HBTitle();
-
- char * fDevice;
- int fIndex;
- uint64_t fLength;
-
- /* Video input */
- uint32_t fInWidth;
- uint32_t fInHeight;
- uint32_t fAspect;
- uint32_t fRate;
- uint32_t fScale;
-
- /* Video output */
- bool fDeinterlace;
- uint32_t fOutWidth;
- uint32_t fOutHeight;
- uint32_t fOutWidthMax;
- uint32_t fOutHeightMax;
- uint32_t fTopCrop;
- uint32_t fBottomCrop;
- uint32_t fLeftCrop;
- uint32_t fRightCrop;
- uint32_t fBitrate;
- bool fTwoPass;
-
- /* Audio infos */
- HBList * fAudioList;
-
- /* Fifos */
- HBFifo * fPSFifo;
- HBFifo * fMpeg2Fifo;
- HBFifo * fRawFifo;
- HBFifo * fResizedFifo;
- HBFifo * fMpeg4Fifo;
-
- /* Threads */
- HBDVDReader * fDVDReader;
- HBMpegDemux * fMpegDemux;
- HBMpeg2Decoder * fMpeg2Decoder;
- HBResizer * fResizer;
- HBMpeg4Encoder * fMpeg4Encoder;
- HBAviMuxer * fAviMuxer;
- HBWorker * fWorkers[4];
-};
-
-#endif
diff --git a/core/DVDRead.c b/core/DVDRead.c
new file mode 100644
index 000000000..58e8f1031
--- /dev/null
+++ b/core/DVDRead.c
@@ -0,0 +1,328 @@
+/* $Id: DVDRead.c,v 1.4 2003/11/06 13:03:19 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "DVDRead.h"
+#include "Fifo.h"
+#include "Thread.h"
+
+#include <dvdread/ifo_types.h>
+#include <dvdplay/dvdplay.h>
+#include <dvdplay/info.h>
+#include <dvdplay/state.h>
+#include <dvdplay/nav.h>
+
+/* Local prototypes */
+static void DVDReadThread( void * );
+static int DoPass( HBDVDRead * );
+static int Demux( HBDVDRead * );
+static int Push( HBDVDRead *, HBFifo * fifo, HBBuffer ** buffer );
+
+struct HBDVDRead
+{
+ HBHandle * handle;
+
+ dvdplay_ptr vmg;
+ HBTitle * title;
+ HBAudio * audio;
+ HBAudio * optAudio;
+ int beginPosition;
+ int endPosition;
+ int pass;
+ HBBuffer * psBuffer;
+ HBList * esBufferList;
+ HBBuffer * videoBuf;
+ HBBuffer * audioBuf;
+ HBBuffer * optAudioBuf;
+ int videoStart;
+ int audioStart;
+ int optAudioStart;
+
+ int die;
+ HBThread * thread;
+};
+
+HBDVDRead * HBDVDReadInit( HBHandle * handle, HBTitle * t,
+ HBAudio * a1, HBAudio * a2 )
+{
+ HBDVDRead * d;
+ if( !( d = malloc( sizeof( HBDVDRead ) ) ) )
+ {
+ HBLog( "HBDVDReadInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ /* Initializations */
+ d->handle = handle;
+ d->vmg = NULL;
+ d->title = t;
+ d->audio = a1;
+ d->optAudio = a2;
+ d->beginPosition = 0;
+ d->endPosition = 0;
+ d->pass = 0;
+ d->psBuffer = NULL;
+ d->esBufferList = HBListInit();
+ d->videoBuf = NULL;
+ d->audioBuf = NULL;
+ d->optAudioBuf = NULL;
+ d->videoStart = -1;
+ d->audioStart = -1;
+ d->optAudioStart = -1;
+
+ /* Launch the thread */
+ d->die = 0;
+ d->thread = HBThreadInit( "dvd reader", DVDReadThread, d,
+ HB_NORMAL_PRIORITY );
+
+ return d;
+}
+
+void HBDVDReadClose( HBDVDRead ** _d )
+{
+ HBBuffer * buffer;
+
+ HBDVDRead * d = *_d;
+
+ /* Stop the thread */
+ d->die = 1;
+ HBThreadClose( &d->thread );
+
+ /* Clean up */
+ while( ( buffer = (HBBuffer*) HBListItemAt( d->esBufferList, 0 ) ) )
+ {
+ HBListRemove( d->esBufferList, buffer );
+ HBBufferClose( &buffer );
+ }
+ HBListClose( &d->esBufferList ) ;
+ free( d );
+
+ (*_d) = NULL;
+}
+
+static void DVDReadThread( void * _d )
+{
+ HBDVDRead * d = (HBDVDRead*) _d;
+ uint8_t dummy[DVD_VIDEO_LB_LEN];
+ int i;
+
+ /* Open the device */
+ d->vmg = dvdplay_open( d->title->device, NULL, NULL );
+ if( !d->vmg )
+ {
+ HBLog( "HBDVDRead: dvdplay_open() failed" );
+ HBErrorOccured( d->handle, HB_ERROR_DVD_OPEN );
+ return;
+ }
+
+ /* Open the title */
+ dvdplay_start( d->vmg, d->title->index );
+ d->beginPosition = dvdplay_title_first( d->vmg );
+ d->endPosition = dvdplay_title_end( d->vmg );
+
+ HBLog( "HBDVDRead: starting, blocks: %d to %d",
+ d->beginPosition, d->endPosition );
+
+ /* Lalala */
+ dvdplay_read( d->vmg, dummy, 1 );
+
+ /* Do the job */
+ for( i = 0; i < ( d->title->twoPass ? 2 : 1 ); i++ )
+ {
+ dvdplay_seek( d->vmg, 0 );
+
+ HBLog( "HBDVDRead: starting pass %d of %d", i + 1,
+ d->title->twoPass ? 2 : 1 );
+
+ d->pass = d->title->twoPass ? ( i + 1 ) : 0;
+
+ if( !DoPass( d ) )
+ {
+ break;
+ }
+ }
+
+ /* Flag the latest buffers so we know when we're done */
+ if( !d->die )
+ {
+ HBLog( "HBDVDRead: done" );
+
+ if( d->videoBuf )
+ {
+ d->videoBuf->last = 1;
+ Push( d, d->title->mpeg2Fifo, &d->videoBuf );
+ }
+ if( d->audioBuf )
+ {
+ d->audioBuf->last = 1;
+ Push( d, d->audio->ac3Fifo, &d->audioBuf );
+ }
+ if( d->optAudioBuf )
+ {
+ d->optAudioBuf->last = 1;
+ Push( d, d->optAudio->ac3Fifo, &d->optAudioBuf );
+ }
+ }
+
+ /* Clean up */
+ dvdplay_close( d->vmg );
+}
+
+
+static int DoPass( HBDVDRead * d )
+{
+ int i;
+
+ for( i = 0; i < d->endPosition - d->beginPosition; i++ )
+ {
+ d->psBuffer = HBBufferInit( DVD_VIDEO_LB_LEN );
+ d->psBuffer->position =
+ (float) i / ( d->endPosition - d->beginPosition );
+
+ if( d->pass )
+ {
+ d->psBuffer->position /= 2;
+
+ if( d->pass == 2 )
+ {
+ d->psBuffer->position += 0.5;
+ }
+ }
+ d->psBuffer->pass = d->pass;
+
+ if( dvdplay_read( d->vmg, d->psBuffer->data, 1 ) < 0 )
+ {
+ HBLog( "HBDVDRead: dvdplay_read() failed" );
+ HBErrorOccured( d->handle, HB_ERROR_DVD_READ );
+ HBBufferClose( &d->psBuffer );
+ return 0;
+ }
+
+ if( !Demux( d ) )
+ {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static int Demux( HBDVDRead * d )
+{
+ HBBuffer * esBuffer;
+
+ /* Demux */
+ HBPStoES( &d->psBuffer, d->esBufferList );
+
+ /* Push buffers */
+ while( ( esBuffer = (HBBuffer*) HBListItemAt( d->esBufferList, 0 ) ) )
+ {
+ /* First pass: trash audio buffers */
+ if( d->pass == 1 && esBuffer->streamId != 0xE0 )
+ {
+ HBListRemove( d->esBufferList, esBuffer );
+ HBBufferClose( &esBuffer );
+ continue;
+ }
+
+ if( esBuffer->streamId == 0xE0 )
+ {
+ if( d->videoStart < 0 )
+ {
+ d->videoStart = esBuffer->pts / 90;
+ HBLog( "HBDVDRead: got first 0xE0 packet (%d)",
+ d->videoStart );
+ }
+
+ if( d->videoBuf )
+ {
+ d->videoBuf->last = 0;
+ if( !Push( d, d->title->mpeg2Fifo, &d->videoBuf ) )
+ {
+ return 0;
+ }
+ }
+
+ HBListRemove( d->esBufferList, esBuffer );
+ d->videoBuf = esBuffer;
+ }
+ else if( esBuffer->streamId == d->audio->id )
+ {
+ if( d->audioStart < 0 )
+ {
+ d->audioStart = esBuffer->pts / 90;
+ HBLog( "HBDVDRead: got first 0x%x packet (%d)",
+ d->audio->id, d->audioStart );
+
+ d->audio->delay = d->audioStart - d->videoStart;
+ }
+
+ if( d->audioBuf )
+ {
+ d->audioBuf->last = 0;
+ if( !Push( d, d->audio->ac3Fifo, &d->audioBuf ) )
+ {
+ return 0;
+ }
+ }
+
+ HBListRemove( d->esBufferList, esBuffer );
+ d->audioBuf = esBuffer;
+ }
+ else if( d->optAudio && esBuffer->streamId == d->optAudio->id )
+ {
+ if( d->optAudioStart < 0 )
+ {
+ d->optAudioStart = esBuffer->pts / 90;
+ HBLog( "HBDVDRead: got first 0x%x packet (%d)",
+ d->optAudio->id, d->optAudioStart );
+
+ d->optAudio->delay = d->optAudioStart - d->videoStart;
+ }
+
+ if( d->optAudioBuf )
+ {
+ d->optAudioBuf->last = 0;
+ if( !Push( d, d->optAudio->ac3Fifo, &d->optAudioBuf ) )
+ {
+ return 0;
+ }
+ }
+
+ HBListRemove( d->esBufferList, esBuffer );
+ d->optAudioBuf = esBuffer;
+ }
+ else
+ {
+ HBListRemove( d->esBufferList, esBuffer );
+ HBBufferClose( &esBuffer );
+ }
+ }
+
+ return 1;
+}
+
+static int Push( HBDVDRead * d, HBFifo * fifo, HBBuffer ** buffer )
+{
+ for( ;; )
+ {
+ HBCheckPaused( d->handle );
+
+ if( HBFifoPush( fifo, buffer ) )
+ {
+ return 1;
+ }
+
+ if( d->die )
+ {
+ break;
+ }
+
+ HBSnooze( 10000 );
+ }
+
+ return 0;
+}
+
diff --git a/core/DVDRead.h b/core/DVDRead.h
new file mode 100644
index 000000000..7a9aa7e21
--- /dev/null
+++ b/core/DVDRead.h
@@ -0,0 +1,16 @@
+/* $Id: DVDRead.h,v 1.1 2003/11/03 12:08:00 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_DVD_READ_H
+#define HB_DVD_READ_H
+
+#include "HandBrakeInternal.h"
+
+HBDVDRead * HBDVDReadInit( HBHandle *, HBTitle *,
+ HBAudio *, HBAudio * );
+void HBDVDReadClose( HBDVDRead ** );
+
+#endif
diff --git a/core/DVDReader.cpp b/core/DVDReader.cpp
deleted file mode 100644
index c3c0e6f3e..000000000
--- a/core/DVDReader.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/* $Id: DVDReader.cpp,v 1.18 2003/10/16 13:39:13 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 "DVDReader.h"
-#include "Manager.h"
-#include "Fifo.h"
-
-#include <dvdread/ifo_types.h>
-#include <dvdplay/dvdplay.h>
-#include <dvdplay/info.h>
-#include <dvdplay/state.h>
-#include <dvdplay/nav.h>
-
-HBDVDReader::HBDVDReader( HBManager * manager, HBTitle * title )
- : HBThread( "dvdreader", HB_NORMAL_PRIORITY )
-{
- fManager = manager;
- fTitle = title;
-
- Run();
-}
-
-void HBDVDReader::DoWork()
-{
- /* Open the device */
- dvdplay_ptr vmg;
- vmg = dvdplay_open( fTitle->fDevice, NULL, NULL );
- if( !vmg )
- {
- Log( "HBDVDReader: dvdplay_open() failed" );
- fManager->Error( HB_ERROR_DVD_OPEN );
- return;
- }
-
- bool die = false;
- for( int i = 0; i < ( fTitle->fTwoPass ? 2 : 1 ); i++ )
- {
- /* Open the title */
- dvdplay_start( vmg, fTitle->fIndex );
-
- /* Read */
- HBBuffer * dvdBuffer;
- int beginPosition = dvdplay_position( vmg );
- int endPosition = dvdplay_title_end( vmg );
-
- while( dvdplay_position( vmg ) < endPosition )
- {
- while( fSuspend )
- {
- Snooze( 10000 );
- }
-
- dvdBuffer = new HBBuffer( DVD_VIDEO_LB_LEN );
- dvdBuffer->fPosition = (float) ( dvdplay_position( vmg )
- - beginPosition ) /
- (float) ( endPosition - beginPosition ) ;
- if( fTitle->fTwoPass )
- {
- dvdBuffer->fPosition /= 2;
- if( i == 1 )
- {
- dvdBuffer->fPosition += 0.5;
- }
- }
- dvdBuffer->fPass = fTitle->fTwoPass ? ( i + 1 ) : 0;
-
- if( dvdplay_read( vmg, dvdBuffer->fData, 1 ) < 0 )
- {
- Log( "HBDVDReader: dvdplay_read() failed" );
- delete dvdBuffer;
- fManager->Error( HB_ERROR_DVD_READ );
- die = true;
- break;
- }
-
- if( !Push( fTitle->fPSFifo, dvdBuffer ) )
- {
- die = true;
- break;
- }
- }
-
- if( die )
- {
- break;
- }
- }
-
- if( !die )
- {
- fManager->Done();
- }
-
- /* Clean up */
- dvdplay_close( vmg );
-}
diff --git a/core/DVDReader.h b/core/DVDReader.h
deleted file mode 100644
index b76f57566..000000000
--- a/core/DVDReader.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Id: DVDReader.h,v 1.5 2003/09/30 14:38:15 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_DVD_READER_H
-#define HB_DVD_READER_H
-
-#include "Common.h"
-#include "Thread.h"
-
-class HBDVDReader : public HBThread
-{
- public:
- HBDVDReader( HBManager * manager, HBTitle * title );
-
- private:
- void DoWork();
-
- HBManager * fManager;
- HBTitle * fTitle;
-};
-
-#endif
diff --git a/core/FfmpegEnc.c b/core/FfmpegEnc.c
new file mode 100644
index 000000000..2118c29d6
--- /dev/null
+++ b/core/FfmpegEnc.c
@@ -0,0 +1,230 @@
+/* $Id: FfmpegEnc.c,v 1.5 2003/11/06 13:03:19 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "FfmpegEnc.h"
+#include "Fifo.h"
+#include "Work.h"
+
+#include <ffmpeg/avcodec.h>
+
+/* Extern functions */
+void HBSetPosition( HBHandle *, float );
+
+/* Local prototypes */
+static int FfmpegEncWork( HBWork * );
+
+struct HBFfmpegEnc
+{
+ HB_WORK_COMMON_MEMBERS
+
+ HBHandle * handle;
+ HBTitle * title;
+
+ HBBuffer * mpeg4Buffer;
+ int pass;
+ AVCodecContext * context;
+ FILE * file;
+};
+
+HBFfmpegEnc * HBFfmpegEncInit( HBHandle * handle, HBTitle * title )
+{
+ HBFfmpegEnc * f;
+ if( !( f = malloc( sizeof( HBFfmpegEnc ) ) ) )
+ {
+ HBLog( "HBFfmpegEncInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ f->name = strdup( "FfmpegEnc" );
+ f->work = FfmpegEncWork;
+
+ f->handle = handle;
+ f->title = title;
+
+ f->mpeg4Buffer = NULL;
+ f->pass = 42;
+ f->context = NULL;
+ f->file = NULL;
+
+ return f;
+}
+
+void HBFfmpegEncClose( HBFfmpegEnc ** _f )
+{
+ HBFfmpegEnc * f = *_f;
+
+ if( f->context )
+ {
+ HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)",
+ f->pass );
+
+ avcodec_close( f->context );
+ if( f->file )
+ {
+ fclose( f->file );
+ f->file = NULL;
+ }
+ }
+ free( f->name );
+ free( f );
+
+ *_f = NULL;
+}
+
+static int FfmpegEncWork( HBWork * w )
+{
+ HBFfmpegEnc * f = (HBFfmpegEnc*) w;
+ HBTitle * title = f->title;
+
+ HBBuffer * scaledBuffer;
+ HBBuffer * mpeg4Buffer;
+ AVFrame * frame;
+
+ int didSomething = 0;
+
+ if( f->mpeg4Buffer )
+ {
+ if( HBFifoPush( title->mpeg4Fifo, &f->mpeg4Buffer ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+ }
+
+ if( ( scaledBuffer = HBFifoPop( title->scaledFifo ) ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+
+ /* Init or re-init if needed */
+ if( scaledBuffer->pass != f->pass )
+ {
+ AVCodec * codec;
+ AVCodecContext * context;
+
+ if( f->context )
+ {
+ HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)",
+ f->pass );
+
+ avcodec_close( f->context );
+ if( f->file )
+ {
+ fclose( f->file );
+ f->file = NULL;
+ }
+ }
+
+ f->pass = scaledBuffer->pass;
+
+ HBLog( "HBFfmpegEnc: opening libavcodec (pass %d)", f->pass );
+ codec = avcodec_find_encoder( CODEC_ID_MPEG4 );
+ if( !codec )
+ {
+ HBLog( "HBFfmpegEnc: avcodec_find_encoder() failed" );
+ HBErrorOccured( f->handle, HB_ERROR_MPEG4_INIT );
+ return didSomething;
+ }
+
+ context = avcodec_alloc_context();
+ context->bit_rate = 1024 * title->bitrate;
+ context->bit_rate_tolerance = 10240 * title->bitrate;
+ context->width = title->outWidth;
+ context->height = title->outHeight;
+ context->frame_rate = title->rate;
+ context->frame_rate_base = title->rateBase;
+ context->gop_size = 10 * title->rate /
+ title->rateBase;
+
+ if( f->pass )
+ {
+ char fileName[1024]; memset( fileName, 0, 1024 );
+ sprintf( fileName, "/tmp/HB.%d.ffmpeg.log",
+ HBGetPid( f->handle ) );
+
+ if( f->pass == 1 )
+ {
+ f->file = fopen( fileName, "w" );
+
+ context->flags |= CODEC_FLAG_PASS1;
+ }
+ else
+ {
+ FILE * file;
+ int size;
+ char * log;
+
+ file = fopen( fileName, "r" );
+ fseek( file, 0, SEEK_END );
+ size = ftell( file );
+ fseek( file, 0, SEEK_SET );
+ if( !( log = malloc( size + 1 ) ) )
+ {
+ HBLog( "HBFfmpegEnc: malloc() failed, gonna crash" );
+ }
+ log[size] = '\0';
+ fread( log, size, 1, file );
+ fclose( file );
+
+ context->flags |= CODEC_FLAG_PASS2;
+ context->stats_in = log;
+ }
+ }
+
+ if( avcodec_open( context, codec ) < 0 )
+ {
+ HBLog( "HBFfmpegEnc: avcodec_open() failed" );
+ HBErrorOccured( f->handle, HB_ERROR_MPEG4_INIT );
+ return didSomething;
+ }
+
+ f->context = context;
+ }
+
+ frame = avcodec_alloc_frame();
+ frame->data[0] = scaledBuffer->data;
+ frame->data[1] = frame->data[0] + title->outWidth *
+ title->outHeight;
+ frame->data[2] = frame->data[1] + title->outWidth *
+ title->outHeight / 4;
+ frame->linesize[0] = title->outWidth;
+ frame->linesize[1] = title->outWidth / 2;
+ frame->linesize[2] = title->outWidth / 2;
+
+ mpeg4Buffer = HBBufferInit( 3 * title->outWidth *
+ title->outHeight / 2 );
+ mpeg4Buffer->position = scaledBuffer->position;
+ mpeg4Buffer->size =
+ avcodec_encode_video( f->context, mpeg4Buffer->data,
+ mpeg4Buffer->alloc, frame );
+ mpeg4Buffer->keyFrame = f->context->coded_frame->key_frame;
+
+ /* Inform the GUI about the current position */
+ HBPosition( f->handle, scaledBuffer->position );
+
+ if( f->pass == 1 )
+ {
+ if( f->context->stats_out )
+ {
+ fprintf( f->file, "%s", f->context->stats_out );
+ }
+ HBBufferClose( &mpeg4Buffer );
+ }
+
+ HBBufferClose( &scaledBuffer );
+ free( frame );
+
+ f->mpeg4Buffer = mpeg4Buffer;
+
+ return didSomething;
+}
diff --git a/core/FfmpegEnc.h b/core/FfmpegEnc.h
new file mode 100644
index 000000000..8ab622011
--- /dev/null
+++ b/core/FfmpegEnc.h
@@ -0,0 +1,15 @@
+/* $Id: FfmpegEnc.h,v 1.1 2003/11/03 12:08:01 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_FFMPEG_ENC_H
+#define HB_FFMPEG_ENC_H
+
+#include "HandBrakeInternal.h"
+
+HBFfmpegEnc * HBFfmpegEncInit( HBHandle *, HBTitle * );
+void HBFfmpegEncClose( HBFfmpegEnc ** );
+
+#endif
diff --git a/core/Fifo.c b/core/Fifo.c
new file mode 100644
index 000000000..a8f6034c0
--- /dev/null
+++ b/core/Fifo.c
@@ -0,0 +1,105 @@
+/* $Id: Fifo.c,v 1.2 2003/11/05 19:14:37 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "Fifo.h"
+
+HBBuffer * HBBufferInit( int size )
+{
+ HBBuffer * b;
+ if( !( b = malloc( sizeof( HBBuffer ) ) ) )
+ {
+ HBLog( "HBBufferInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ b->alloc = size;
+ b->size = size;
+
+ if( !( b->data = malloc( size ) ) )
+ {
+ HBLog( "HBBufferInit: malloc() failed, gonna crash" );
+ free( b );
+ return NULL;
+ }
+
+ b->position = 0.0;
+ b->streamId = 0;
+ b->keyFrame = 0;
+ b->pts = 0;
+ b->pass = 0;
+ b->last = 0;
+
+ return b;
+}
+
+void HBBufferReAlloc( HBBuffer * b, int size )
+{
+ b->alloc = size;
+ b->data = realloc( b->data, size );
+
+ if( !b->data )
+ {
+ HBLog( "HBBufferReAlloc: realloc() failed, gonna crash soon" );
+ }
+}
+
+void HBBufferClose( HBBuffer ** b )
+{
+ free( (*b)->data );
+ (*b) = NULL;
+}
+
+HBFifo * HBFifoInit( int capacity )
+{
+ HBFifo * f;
+ if( !( f = malloc( sizeof( HBFifo ) ) ) )
+ {
+ HBLog( "HBFifoInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ f->capacity = capacity;
+ f->whereToPush = 0;
+ f->whereToPop = 0;
+
+ if( !( f->buffers = malloc( ( capacity + 1 ) * sizeof( void* ) ) ) )
+ {
+ HBLog( "HBFifoInit: malloc() failed, gonna crash" );
+ free( f );
+ return NULL;
+ }
+
+ f->lock = HBLockInit();
+
+ return f;
+}
+
+int HBFifoSize( HBFifo * f )
+{
+ return ( f->capacity + 1 + f->whereToPush - f->whereToPop ) %
+ ( f->capacity + 1 );
+}
+
+void HBFifoClose( HBFifo ** _f )
+{
+ HBFifo * f = (*_f);
+
+ HBLog( "HBFifoClose: trashing %d buffer%s",
+ HBFifoSize( f ), ( HBFifoSize( f ) > 1 ) ? "s" : "" );
+
+ while( f->whereToPush != f->whereToPop )
+ {
+ HBBufferClose( &(f->buffers[f->whereToPop]) );
+ f->whereToPop++;
+ f->whereToPop %= ( f->capacity + 1 );
+ }
+
+ HBLockClose( &f->lock );
+ free( f->buffers );
+ free( f );
+ (*_f) = NULL;
+}
+
diff --git a/core/Fifo.cpp b/core/Fifo.cpp
deleted file mode 100644
index d1d051c33..000000000
--- a/core/Fifo.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/* $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/>.
- It may be used under the terms of the GNU General Public License. */
-
-#include "Fifo.h"
-#include "Thread.h"
-
-HBBuffer::HBBuffer( uint32_t size )
-{
- fAllocSize = size;
- fSize = size;
- fKeyFrame = false;
- fData = (uint8_t*) malloc( size );
- fPosition = 0;
-
- if( !fData )
- {
- Log( "HBBuffer::HBBuffer() : malloc() failed, gonna crash soon" );
- }
-}
-
-HBBuffer::~HBBuffer()
-{
- free( fData );
-}
-
-void HBBuffer::ReAlloc( uint32_t size )
-{
- fData = (uint8_t*) realloc( fData, size );
-
- if( !fData )
- {
- Log( "HBBuffer::ReAlloc() : realloc() failed, gonna crash soon" );
- }
-
- fAllocSize = size;
-}
-
-/* Constructor */
-HBFifo::HBFifo( int capacity )
-{
- fCapacity = capacity;
-
- fWhereToPush = 0;
- fWhereToPop = 0;
- fBuffers = (HBBuffer**) malloc( ( fCapacity + 1 ) * sizeof( void* ) );
- fLock = new HBLock();
-}
-
-HBFifo::~HBFifo()
-{
- Log( "HBFifo::~HBFifo: trashing %d buffer%s",
- Size(), Size() ? "s" : "" );
-
- /* Empty the fifo */
- while( fWhereToPush != fWhereToPop )
- {
- HBBuffer * buffer = fBuffers[fWhereToPop];
- fWhereToPop++;
- fWhereToPop %= ( fCapacity + 1 );
- delete buffer;
- }
-
- /* Cleaning */
- free( fBuffers );
-
- delete fLock;
-}
-
-/* Size() : returns how much the fifo is currently filled */
-int HBFifo::Size()
-{
- return ( fCapacity + 1 + fWhereToPush - fWhereToPop ) %
- ( fCapacity + 1 );
-}
-
-/* Capacity() : simply returns the fifo capacity... */
-int HBFifo::Capacity()
-{
- return fCapacity;
-}
-
-/* Push() - returns immediatly (true if successful, false otherwise ) */
-bool HBFifo::Push( HBBuffer * buffer )
-{
- fLock->Lock();
-
- if( Size() < fCapacity )
- {
- fBuffers[fWhereToPush] = buffer;
- fWhereToPush++;
- fWhereToPush %= ( fCapacity + 1 );
- fLock->Unlock();
- return true;
- }
-
- fLock->Unlock();
- return false;
-}
-
-/* Pop() - returns immediatly (a pointer to a buffer if successful,
- NULL otherwise ) */
-HBBuffer * HBFifo::Pop()
-{
- fLock->Lock();
-
- if( fWhereToPush != fWhereToPop )
- {
- HBBuffer * buffer = fBuffers[fWhereToPop];
- fWhereToPop++;
- fWhereToPop %= ( fCapacity + 1 );
- fLock->Unlock();
- return buffer;
- }
-
- fLock->Unlock();
- return NULL;
-}
diff --git a/core/Fifo.h b/core/Fifo.h
index 69200d30c..758125ebd 100644
--- a/core/Fifo.h
+++ b/core/Fifo.h
@@ -1,49 +1,81 @@
-/* $Id: Fifo.h,v 1.11 2003/09/30 14:38:15 titer Exp $
+/* $Id: Fifo.h,v 1.3 2003/11/06 13:07:52 titer Exp $
This file is part of the HandBrake source code.
- Homepage: <http://beos.titer.org/handbrake/>.
+ Homepage: <http://handbrake.m0k.org/>.
It may be used under the terms of the GNU General Public License. */
#ifndef HB_FIFO_H
#define HB_FIFO_H
-#include "Common.h"
+#include "Utils.h"
+#include "Thread.h"
-class HBBuffer
+struct HBBuffer
{
- public:
- HBBuffer( uint32_t size );
- ~HBBuffer();
- void ReAlloc( uint32_t size );
-
- uint32_t fAllocSize;
- uint32_t fSize;
- uint8_t * fData;
-
- float fPosition;
- uint32_t fStreamId;
- bool fKeyFrame;
- uint64_t fPTS;
- uint32_t fPass;
+ int alloc;
+ int size;
+ uint8_t * data;
+
+ float position;
+ int streamId;
+ int keyFrame;
+ uint64_t pts;
+ int pass;
+ int last;
};
-class HBFifo
+HBBuffer * HBBufferInit( int size );
+void HBBufferReAlloc( HBBuffer *, int size );
+void HBBufferClose( HBBuffer ** );
+
+struct HBFifo
{
- public:
- HBFifo( int capacity = 32 );
- ~HBFifo();
-
- int Size();
- int Capacity();
- bool Push( HBBuffer * buffer );
- HBBuffer * Pop();
-
- private:
- int fCapacity;
- int fWhereToPush;
- int fWhereToPop;
- HBBuffer ** fBuffers;
- HBLock * fLock;
+ int capacity;
+ int whereToPush;
+ int whereToPop;
+ HBBuffer ** buffers;
+ HBLock * lock;
};
+HBFifo * HBFifoInit( int capacity );
+int HBFifoSize( HBFifo * );
+static inline int HBFifoPush( HBFifo *, HBBuffer ** );
+static inline HBBuffer * HBFifoPop( HBFifo * );
+void HBFifoClose( HBFifo ** );
+
+static inline int HBFifoPush( HBFifo * f, HBBuffer ** b )
+{
+ HBLockLock( f->lock );
+
+ if( HBFifoSize( f ) < f->capacity )
+ {
+ f->buffers[f->whereToPush] = *b;
+ f->whereToPush++;
+ f->whereToPush %= ( f->capacity + 1 );
+ HBLockUnlock( f->lock );
+ *b = NULL;
+ return 1;
+ }
+
+ HBLockUnlock( f->lock );
+ return 0;
+}
+
+static inline HBBuffer * HBFifoPop( HBFifo * f )
+{
+ HBLockLock( f->lock );
+
+ if( f->whereToPush != f->whereToPop )
+ {
+ HBBuffer * b = f->buffers[f->whereToPop];
+ f->whereToPop++;
+ f->whereToPop %= ( f->capacity + 1 );
+ HBLockUnlock( f->lock );
+ return b;
+ }
+
+ HBLockUnlock( f->lock );
+ return NULL;
+}
+
#endif
diff --git a/core/HandBrake.c b/core/HandBrake.c
new file mode 100644
index 000000000..3f84a5757
--- /dev/null
+++ b/core/HandBrake.c
@@ -0,0 +1,767 @@
+/* $Id: HandBrake.c,v 1.15 2003/11/07 21:52:57 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "HandBrakeInternal.h"
+
+#include <ffmpeg/avcodec.h>
+
+#include "Ac3Dec.h"
+#include "AviMux.h"
+#include "DVDRead.h"
+#include "FfmpegEnc.h"
+#include "Fifo.h"
+#include "Mp3Enc.h"
+#include "Mpeg2Dec.h"
+#include "Scale.h"
+#include "Scan.h"
+#include "Thread.h"
+#include "Work.h"
+#include "XvidEnc.h"
+
+/* Local prototypes */
+static void HandBrakeThread( void * );
+static void _StopRip( HBHandle * );
+static void FixPictureSettings( HBTitle * );
+static int GetCPUCount();
+
+struct HBHandle
+{
+ HBThread * thread;
+ int die;
+ int pid;
+
+ int cpuCount;
+
+ int stopScan;
+ int stopRip;
+ int ripDone;
+ int error;
+
+ HBScan * scan;
+
+ HBLock * lock;
+ HBStatus status;
+ int modeChanged;
+ HBTitle * curTitle;
+ HBAudio * curAudio;
+ HBAudio * curOptAudio;
+
+ int frames;
+ uint64_t beginDate;
+ int framesSinceFpsUpdate;
+ uint64_t lastFpsUpdate;
+ uint64_t pauseDate;
+
+ HBLock * pauseLock;
+};
+
+HBHandle * HBInit( int debug, int cpuCount )
+{
+ HBHandle * h;
+ if( !( h = malloc( sizeof( HBHandle ) ) ) )
+ {
+ HBLog( "HBInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ /* See HBLog() in Utils.cpp */
+ if( debug )
+ {
+ putenv( "HB_DEBUG=1" );
+ }
+
+ /* Init libavcodec */
+ avcodec_init();
+ register_avcodec( &mpeg4_encoder );
+
+ /* Check CPU count */
+ if( !cpuCount )
+ {
+ h->cpuCount = GetCPUCount();
+ HBLog( "HBInit: %d CPU%s detected", h->cpuCount,
+ ( h->cpuCount > 1 ) ? "s" : "" );
+ }
+ else
+ {
+ if( cpuCount < 1 )
+ {
+ HBLog( "HBInit: invalid CPU count (%d), using 1",
+ cpuCount );
+ h->cpuCount = 1;
+ }
+ else if( cpuCount > 8 )
+ {
+ HBLog( "HBInit: invalid CPU count (%d), using 8",
+ cpuCount );
+ h->cpuCount = 8;
+ }
+ else
+ {
+ HBLog( "HBInit: user specified %d CPU%s",
+ cpuCount, ( cpuCount > 1 ) ? "s" : "" );
+ h->cpuCount = cpuCount;
+ }
+ }
+
+ /* Initializations */
+ h->stopScan = 0;
+ h->stopRip = 0;
+ h->ripDone = 0;
+ h->error = 0;
+
+ h->scan = NULL;
+
+ h->lock = HBLockInit();
+ h->modeChanged = 1;
+ h->status.mode = HB_MODE_NEED_DEVICE;
+ h->curTitle = NULL;
+ h->curAudio = NULL;
+ h->curOptAudio = NULL;
+
+ h->pauseLock = HBLockInit();
+
+ h->die = 0;
+ h->thread = HBThreadInit( "libhb", HandBrakeThread, h,
+ HB_NORMAL_PRIORITY );
+
+ return h;
+}
+
+int HBGetStatus( HBHandle * h, HBStatus * status )
+{
+ HBLockLock( h->lock );
+ memcpy( status, &h->status, sizeof( HBStatus ) );
+
+ if( !h->modeChanged )
+ {
+ HBLockUnlock( h->lock );
+ return 0;
+ }
+
+ h->modeChanged = 0;
+ HBLockUnlock( h->lock );
+ return 1;
+}
+
+void HBScanDevice( HBHandle * h, char * device, int title )
+{
+ if( !( h->status.mode & ( HB_MODE_NEED_DEVICE |
+ HB_MODE_INVALID_DEVICE ) ) )
+ {
+ HBLog( "HBScanDevice: current mode is %d, aborting",
+ h->status.mode );
+ return;
+ }
+
+ HBLockLock( h->lock );
+ h->modeChanged = 1;
+ h->status.mode = HB_MODE_SCANNING;
+ h->status.scannedTitle = 0;
+ HBLockUnlock( h->lock );
+
+ h->scan = HBScanInit( h, device, title );
+}
+
+void HBStartRip( HBHandle * h, HBTitle * t,
+ HBAudio * a1, HBAudio * a2 )
+{
+ int i;
+
+ if( !( h->status.mode & ( HB_MODE_READY_TO_RIP | HB_MODE_DONE |
+ HB_MODE_CANCELED | HB_MODE_ERROR ) ) )
+ {
+ HBLog( "HBStartRip: current mode is %d, aborting",
+ h->status.mode );
+ return;
+ }
+
+ HBLockLock( h->lock );
+ h->modeChanged = 1;
+ h->status.mode = HB_MODE_ENCODING;
+ h->status.position = 0.0;
+ h->status.pass = 1;
+ h->status.passCount = t->twoPass ? 2 : 1;
+ h->frames = 0;
+ h->framesSinceFpsUpdate = 0;
+ HBLockUnlock( h->lock );
+
+ FixPictureSettings( t );
+
+ /* Create fifos */
+ t->mpeg2Fifo = HBFifoInit( 512 );
+ t->rawFifo = HBFifoInit( 1 );
+ t->scaledFifo = HBFifoInit( 1 );
+ t->mpeg4Fifo = HBFifoInit( 1 );
+ a1->ac3Fifo = HBFifoInit( 512 );
+ a1->rawFifo = HBFifoInit( 1 );
+ a1->mp3Fifo = HBFifoInit( 1 );
+ if( a2 )
+ {
+ a2->ac3Fifo = HBFifoInit( 512 );
+ a2->rawFifo = HBFifoInit( 1 );
+ a2->mp3Fifo = HBFifoInit( 1 );
+ }
+
+ /* Create work objects */
+ t->mpeg2Dec = HBMpeg2DecInit( h, t );
+ t->scale = HBScaleInit( h, t );
+
+ if( t->codec == HB_CODEC_FFMPEG )
+ t->ffmpegEnc = HBFfmpegEncInit( h, t );
+ else if( t->codec == HB_CODEC_XVID )
+ t->xvidEnc = HBXvidEncInit( h, t );
+
+ a1->ac3Dec = HBAc3DecInit( h, a1 );
+ a1->mp3Enc = HBMp3EncInit( h, a1 );
+ if( a2 )
+ {
+ a2->ac3Dec = HBAc3DecInit( h, a2 );
+ a2->mp3Enc = HBMp3EncInit( h, a2 );
+ }
+
+ /* Create threads */
+ t->dvdRead = HBDVDReadInit( h, t, a1, a2 );
+ t->aviMux = HBAviMuxInit( h, t, a1, a2 );
+ for( i = 0; i < h->cpuCount; i++ )
+ {
+ t->workThreads[i] = HBWorkThreadInit( h, t, a1, a2, i ? 0 : 1 );
+ }
+
+ h->curTitle = t;
+ h->curAudio = a1;
+ h->curOptAudio = a2;
+}
+
+void HBPauseRip( HBHandle * h )
+{
+ if( h->status.mode != HB_MODE_ENCODING )
+ {
+ HBLog( "HBPauseRip: current mode is %d, aborting",
+ h->status.mode );
+ return;
+ }
+
+ h->pauseDate = HBGetDate();
+ HBLockLock( h->pauseLock );
+ HBLockLock( h->lock );
+ h->status.mode = HB_MODE_PAUSED;
+ h->modeChanged = 1;
+ HBLockUnlock( h->lock );
+}
+
+void HBResumeRip( HBHandle * h )
+{
+ if( h->status.mode != HB_MODE_PAUSED )
+ {
+ HBLog( "HBResumeRip: current mode is %d, aborting",
+ h->status.mode );
+ return;
+ }
+
+ h->beginDate += HBGetDate() - h->pauseDate;
+ h->lastFpsUpdate += HBGetDate() - h->pauseDate;
+ HBLockUnlock( h->pauseLock );
+ HBLockLock( h->lock );
+ h->modeChanged = 1;
+ h->status.mode = HB_MODE_ENCODING;
+ HBLockUnlock( h->lock );
+}
+
+void HBStopRip( HBHandle * h )
+{
+ if( !( h->status.mode & ( HB_MODE_ENCODING | HB_MODE_PAUSED ) ) )
+ {
+ HBLog( "HBStopRip: current mode is %d, aborting",
+ h->status.mode );
+ return;
+ }
+
+ if( h->status.mode & HB_MODE_PAUSED )
+ {
+ HBLockUnlock( h->pauseLock );
+ }
+
+ HBLockLock( h->lock );
+ h->modeChanged = 1;
+ h->status.mode = HB_MODE_STOPPING;
+ HBLockUnlock( h->lock );
+ h->stopRip = 1;
+}
+
+uint8_t * HBGetPreview( HBHandle * h, HBTitle * t, int picture )
+{
+ AVPicture pic1, pic2, pic3, pic4;
+ uint8_t * buf1, * buf2, * buf3, * buf4;
+ char fileName[1024];
+ FILE * file;
+ ImgReSampleContext * resampleContext;
+ int8_t * preview, * pen;
+ int i;
+
+ FixPictureSettings( t );
+
+ buf1 = malloc( 3 * t->inWidth * t->inHeight / 2 );
+ buf2 = malloc( 3 * t->inWidth * t->inHeight / 2 );
+ buf3 = malloc( 3 * t->outWidth * t->outHeight / 2 );
+ buf4 = malloc( 4 * t->outWidth * t->outHeight );
+
+ if( !buf1 || !buf2 || !buf3 || !buf4 )
+ {
+ HBLog( "HBGetPreview: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ /* Original YUV picture */
+ avpicture_fill( &pic1, buf1, PIX_FMT_YUV420P, t->inWidth,
+ t->inHeight );
+
+ /* Deinterlaced YUV picture */
+ avpicture_fill( &pic2, buf2, PIX_FMT_YUV420P,
+ t->inWidth, t->inHeight );
+
+ /* Scaled YUV picture */
+ avpicture_fill( &pic3, buf3, PIX_FMT_YUV420P, t->outWidth,
+ t->outHeight );
+
+ /* Scaled RGB picture ) */
+ avpicture_fill( &pic4, buf4, PIX_FMT_RGBA32, t->outWidth,
+ t->outHeight );
+
+ /* Get the original image from the temp file */
+ memset( fileName, 0, 1024 );
+ sprintf( fileName, "/tmp/HB.%d.%d.%d", h->pid, t->index,
+ picture );
+ file = fopen( fileName, "r" );
+ if( file )
+ {
+ fread( buf1, 3 * t->inWidth * t->inHeight / 2, 1, file );
+ fclose( file );
+ }
+ else
+ {
+ HBLog( "HBGetPreview: could not open %s", fileName );
+ memset( buf1, 0, 3 * t->inWidth * t->inHeight / 2 );
+ }
+
+ /* Deinterlace if needed, and scale */
+ resampleContext =
+ img_resample_full_init( t->outWidth, t->outHeight,
+ t->inWidth, t->inHeight,
+ t->topCrop, t->bottomCrop,
+ t->leftCrop, t->rightCrop );
+ if( t->deinterlace )
+ {
+ avpicture_deinterlace( &pic2, &pic1, PIX_FMT_YUV420P,
+ t->inWidth, t->inHeight );
+ img_resample( resampleContext, &pic3, &pic2 );
+ }
+ else
+ {
+ img_resample( resampleContext, &pic3, &pic1 );
+ }
+
+ /* Convert to RGB */
+ img_convert( &pic4, PIX_FMT_RGBA32, &pic3, PIX_FMT_YUV420P,
+ t->outWidth, t->outHeight );
+
+ /* Create the final preview */
+ preview = malloc( 4 * ( t->outWidthMax + 2 ) *
+ ( t->outHeightMax + 2 ) );
+
+ if( !preview )
+ {
+ HBLog( "HBGetPreview: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ /* Blank it */
+ memset( preview, 0x80,
+ 4 * ( t->outWidthMax + 2 ) * ( t->outHeightMax + 2 ) );
+
+ /* Draw the picture (centered) and draw the cropping zone */
+ pen = preview + ( t->outHeightMax - t->outHeight ) *
+ ( t->outWidthMax + 2 ) * 2 +
+ ( t->outWidthMax - t->outWidth ) * 2;
+
+ memset( pen, 0xFF, 4 * ( t->outWidth + 2 ) );
+ pen += 4 * ( t->outWidthMax + 2 );
+
+ for( i = 0; i < t->outHeight; i++ )
+ {
+ uint8_t * nextLine = pen + 4 * ( t->outWidthMax + 2 );
+
+ memset( pen, 0xFF, 4 );
+ pen += 4;
+ memcpy( pen, buf4 + 4 * t->outWidth * i, 4 * t->outWidth );
+ pen += 4 * t->outWidth;
+ memset( pen, 0xFF, 4 );
+
+ pen = nextLine;
+ }
+
+ memset( pen, 0xFF, 4 * ( t->outWidth + 2 ) );
+
+ /* Free memory */
+ free( buf1 );
+ free( buf2 );
+ free( buf3 );
+ free( buf4 );
+
+ return preview;
+ return NULL;
+}
+
+void HBClose( HBHandle ** _h )
+{
+ char command[1024];
+
+ HBHandle * h = *_h;
+
+ h->die = 1;
+ HBThreadClose( &h->thread );
+
+ if( h->status.mode == HB_MODE_SCANNING )
+ {
+ HBScanClose( &h->scan );
+ }
+ else if( h->status.mode == HB_MODE_PAUSED )
+ {
+ HBLockUnlock( h->pauseLock );
+ _StopRip( h );
+ }
+ else if( h->status.mode == HB_MODE_ENCODING )
+ {
+ _StopRip( h );
+ }
+
+ memset( command, 0, 1024 );
+ sprintf( command, "rm -f /tmp/HB.%d.*", h->pid );
+ system( command );
+
+ if( h->status.titleList )
+ {
+ HBTitle * title;
+ while( ( title = HBListItemAt( h->status.titleList, 0 ) ) )
+ {
+ HBListRemove( h->status.titleList, title );
+ HBTitleClose( &title );
+ }
+ HBListClose( &h->status.titleList );
+ }
+
+ HBLockClose( &h->lock );
+ HBLockClose( &h->pauseLock );
+ free( h );
+
+ *_h = NULL;
+}
+
+/* Following functions are called by libhb's internal threads */
+void HBCheckPaused( HBHandle * h )
+{
+ HBLockLock( h->pauseLock );
+ HBLockUnlock( h->pauseLock );
+}
+
+void HBScanning( HBHandle * h, int title )
+{
+ HBLockLock( h->lock );
+ h->status.scannedTitle = title;
+ HBLockUnlock( h->lock );
+}
+
+void HBScanDone( HBHandle * h, HBList * titleList )
+{
+ h->status.titleList = titleList;
+ h->stopScan = 1;
+}
+
+int HBGetPid( HBHandle * h )
+{
+ return h->pid;
+}
+
+void HBDone( HBHandle * h )
+{
+ h->ripDone = 1;
+}
+
+void HBPosition( HBHandle * h, float position )
+{
+ if( !h->frames )
+ {
+ h->beginDate = HBGetDate();
+ h->lastFpsUpdate = h->beginDate;
+ }
+
+ h->frames++;
+ h->framesSinceFpsUpdate++;
+
+ HBLockLock( h->lock );
+ if( position - h->status.position > 0.0001 || h->frames == 2 )
+ {
+ HBLog( "Progress: %.2f %%", 100.0 * position );
+ h->status.position = position;
+
+ if( h->curTitle->twoPass )
+ h->status.pass = ( position < 0.5 ) ? 1 : 2;
+ else
+ h->status.pass = 1;
+ }
+ if( HBGetDate() - h->lastFpsUpdate > 1000000 )
+ {
+ h->status.frameRate = 1000000.0 * h->framesSinceFpsUpdate /
+ ( HBGetDate() - h->lastFpsUpdate );
+ h->status.avFrameRate = 1000000.0 * h->frames /
+ ( HBGetDate() - h->beginDate );
+ h->status.remainingTime = ( 1.0 - h->status.position ) *
+ ( HBGetDate() - h->beginDate ) /
+ h->status.position / 1000000;
+
+ HBLog( "Speed: %.2f fps (average: %.2f fps, "
+ "remaining: %02d:%02d:%02d)",
+ h->status.frameRate, h->status.avFrameRate,
+ h->status.remainingTime / 3600,
+ ( h->status.remainingTime / 60 ) % 60,
+ h->status.remainingTime % 60 );
+
+ h->lastFpsUpdate = HBGetDate();
+ h->framesSinceFpsUpdate = 0;
+ }
+ HBLockUnlock( h->lock );
+}
+
+void HBErrorOccured( HBHandle * h, HBError error )
+{
+ if( !( h->status.mode & ( HB_MODE_ENCODING | HB_MODE_PAUSED ) ) )
+ {
+ return;
+ }
+
+ h->status.error = error;
+ h->error = 1;
+}
+
+/* Local functions */
+static void HandBrakeThread( void * _h )
+{
+ HBHandle * h = (HBHandle*) _h;
+
+ h->pid = getpid();
+
+ while( !h->die )
+ {
+ if( h->stopScan )
+ {
+ HBScanClose( &h->scan );
+ HBLockLock( h->lock );
+ h->modeChanged = 1;
+ h->status.mode = HBListCountItems( h->status.titleList ) ?
+ HB_MODE_READY_TO_RIP : HB_MODE_INVALID_DEVICE;
+ HBLockUnlock( h->lock );
+ h->stopScan = 0;
+ }
+
+ if( h->stopRip )
+ {
+ _StopRip( h );
+
+ HBLockLock( h->lock );
+ h->modeChanged = 1;
+ h->status.mode = HB_MODE_CANCELED;
+ HBLockUnlock( h->lock );
+
+ h->stopRip = 0;
+ }
+
+ if( h->ripDone )
+ {
+ /* Wait a bit */
+ HBSnooze( 500000 );
+
+ _StopRip( h );
+ HBLockLock( h->lock );
+ h->modeChanged = 1;
+ h->status.mode = HB_MODE_DONE;
+ HBLockUnlock( h->lock );
+
+ h->ripDone = 0;
+ }
+
+ if( h->error )
+ {
+ _StopRip( h );
+
+ HBLockLock( h->lock );
+ h->modeChanged = 1;
+ h->status.mode = HB_MODE_ERROR;
+ HBLockUnlock( h->lock );
+
+ h->error = 0;
+ }
+
+ HBSnooze( 10000 );
+ }
+}
+
+static void _StopRip( HBHandle * h )
+{
+ int i;
+
+ /* Stop threads */
+ HBDVDReadClose( &h->curTitle->dvdRead );
+ HBAviMuxClose( &h->curTitle->aviMux );
+ for( i = 0; i < h->cpuCount; i++ )
+ {
+ HBWorkThreadClose( &h->curTitle->workThreads[h->cpuCount-i-1] );
+ }
+
+ /* Clean up */
+ HBMpeg2DecClose( &h->curTitle->mpeg2Dec );
+ HBScaleClose( &h->curTitle->scale );
+
+ if( h->curTitle->codec == HB_CODEC_FFMPEG )
+ HBFfmpegEncClose( &h->curTitle->ffmpegEnc );
+ else if( h->curTitle->codec == HB_CODEC_XVID )
+ HBXvidEncClose( &h->curTitle->xvidEnc );
+
+ HBAc3DecClose( &h->curAudio->ac3Dec );
+ HBMp3EncClose( &h->curAudio->mp3Enc );
+ if( h->curOptAudio )
+ {
+ HBAc3DecClose( &h->curOptAudio->ac3Dec );
+ HBMp3EncClose( &h->curOptAudio->mp3Enc );
+ }
+
+ /* Destroy fifos */
+ HBFifoClose( &h->curTitle->mpeg2Fifo );
+ HBFifoClose( &h->curTitle->rawFifo );
+ HBFifoClose( &h->curTitle->scaledFifo );
+ HBFifoClose( &h->curTitle->mpeg4Fifo );
+ HBFifoClose( &h->curAudio->ac3Fifo );
+ HBFifoClose( &h->curAudio->rawFifo );
+ HBFifoClose( &h->curAudio->mp3Fifo );
+ if( h->curOptAudio )
+ {
+ HBFifoClose( &h->curOptAudio->ac3Fifo );
+ HBFifoClose( &h->curOptAudio->rawFifo );
+ HBFifoClose( &h->curOptAudio->mp3Fifo );
+ }
+}
+
+static void FixPictureSettings( HBTitle * t )
+{
+ /* Sanity checks */
+ t->topCrop = EVEN( t->topCrop );
+ t->bottomCrop = EVEN( t->bottomCrop );
+ t->leftCrop = EVEN( t->leftCrop );
+ t->rightCrop = EVEN( t->rightCrop );
+
+ t->outWidth = MIN( t->outWidth, t->outWidthMax );
+ t->outWidth = MAX( 16, t->outWidth );
+
+ t->outHeight =
+ MULTIPLE_16( (uint64_t) t->outWidth * t->inWidth *
+ ( t->inHeight - t->topCrop - t->bottomCrop ) *
+ VOUT_ASPECT_FACTOR /
+ ( (uint64_t) t->inHeight *
+ ( t->inWidth - t->leftCrop - t->rightCrop ) *
+ t->aspect ) );
+ t->outHeight = MAX( 16, t->outHeight );
+
+ if( t->outHeight > t->outHeightMax )
+ {
+ t->outHeight = t->outHeightMax;
+ t->outWidth =
+ MULTIPLE_16( (uint64_t) t->outHeight * t->inHeight *
+ ( t->inWidth - t->leftCrop - t->rightCrop ) *
+ t->aspect /
+ ( (uint64_t) t->inWidth *
+ ( t->inHeight - t->topCrop - t->bottomCrop ) *
+ VOUT_ASPECT_FACTOR ) );
+ t->outWidth = MIN( t->outWidth, t->outWidthMax );
+ t->outWidth = MAX( 16, t->outWidth );
+ }
+}
+
+static 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
+ {
+ HBLog( "GetCPUCount: sscanf() failed" );
+ }
+ }
+ else
+ {
+ HBLog( "GetCPUCount: fgets() failed" );
+ }
+ fclose( info );
+ }
+ else
+ {
+ HBLog( "GetCPUCount: popen() failed" );
+ }
+
+#elif defined( SYS_LINUX )
+ FILE * info;
+ char buffer[256];
+
+ if( ( info = popen( "grep -c '^processor' /proc/cpuinfo", "r" ) ) )
+ {
+ if( fgets( buffer, 256, info ) )
+ {
+ int count;
+ if( sscanf( buffer, "%d", &count ) == 1 )
+ {
+ CPUCount = count;
+ }
+ else
+ {
+ HBLog( "GetCPUCount: sscanf() failed" );
+ }
+ }
+ else
+ {
+ HBLog( "GetCPUCount: fgets() failed" );
+ }
+ fclose( info );
+ }
+ else
+ {
+ HBLog( "GetCPUCount: fopen() failed" );
+ }
+
+#elif defined( SYS_CYGWIN )
+ /* TODO */
+ CPUCount = 1;
+
+#endif
+ CPUCount = MAX( 1, CPUCount );
+ CPUCount = MIN( CPUCount, 8 );
+
+ return CPUCount;
+}
+
diff --git a/core/HandBrake.h b/core/HandBrake.h
new file mode 100644
index 000000000..35ec0fc0a
--- /dev/null
+++ b/core/HandBrake.h
@@ -0,0 +1,55 @@
+/* $Id: HandBrake.h,v 1.3 2003/11/06 13:03:19 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_HANDBRAKE_H
+#define HB_HANDBRAKE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "Utils.h"
+
+/* Init libhb. Set debug to 0 to see no output, 1 to see all libhb logs.
+ Set cpuCount to 0 if you want libhb to autodetect */
+HBHandle * HBInit( int debug, int cpuCount );
+
+/* Fills the HBStatus * argument with infos about the current status.
+ Returns 1 if mode has changed, 0 otherwise */
+int HBGetStatus( HBHandle *, HBStatus * );
+
+/* Launch a thread which scans the specified device and title. Use
+ title = 0 to scan all titles. Returns immediately */
+void HBScanDevice( HBHandle *, char * device, int title );
+
+/* Start ripping the specified title with specified audio tracks.
+ Returns immediatly */
+void HBStartRip( HBHandle *, HBTitle *, HBAudio *, HBAudio * );
+
+/* Suspend rip. Returns immediatly */
+void HBPauseRip( HBHandle * );
+
+/* Resume rip. Returns immediatly */
+void HBResumeRip( HBHandle * );
+
+/* Cancel rip. Returns immediatly */
+void HBStopRip( HBHandle * );
+
+/* Calculate preview for the specified picture of the specified title,
+ taking care of the current cropping & scaling settings. Returns a
+ pointer to raw RGBA data. It includes the white border around the
+ picture, so the size of the picture is ( maxWidth + 2 ) x
+ ( maxHeight + 2 ) */
+uint8_t * HBGetPreview( HBHandle *, HBTitle *, int picture );
+
+/* Clean up things */
+void HBClose( HBHandle ** );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/core/HandBrakeInternal.h b/core/HandBrakeInternal.h
new file mode 100644
index 000000000..7c10512c9
--- /dev/null
+++ b/core/HandBrakeInternal.h
@@ -0,0 +1,35 @@
+/* $Id: HandBrakeInternal.h,v 1.2 2003/11/04 15:44:24 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_HANDBRAKE_INTERNAL_H
+#define HB_HANDBRAKE_INTERNAL_H
+
+#include "HandBrake.h"
+
+/* Called by HBScan to tell the GUI how far we are */
+void HBScanning( HBHandle *, int title );
+
+/* Called by HBScan. titleList is a list of all valid titles which
+ should be shown on the interface */
+void HBScanDone( HBHandle *, HBList * titleList );
+
+/* Used to create temporary files (/tmp/HB.pid.whatever) */
+int HBGetPid( HBHandle * );
+
+/* Called by every thread involved in the rip process. Returns
+ immediately is rip isn't paused, blocks if it is */
+void HBCheckPaused( HBHandle * );
+
+/* Called by the decoders when the last packet is being proceeded */
+void HBDone( HBHandle * );
+
+/* Called by the video encoder to update the GUI progress */
+void HBPosition( HBHandle *, float );
+
+/* Called by any thread which couldn't continue and ask to stop */
+void HBErrorOccured( HBHandle *, HBError );
+
+#endif
diff --git a/core/Languages.h b/core/Languages.h
index 21a5e1487..7949688c9 100644
--- a/core/Languages.h
+++ b/core/Languages.h
@@ -1,7 +1,7 @@
-/* $Id: Languages.h,v 1.2 2003/09/30 14:38:15 titer Exp $
+/* $Id: Languages.h,v 1.1 2003/11/03 12:08:01 titer Exp $
This file is part of the HandBrake source code.
- Homepage: <http://beos.titer.org/handbrake/>.
+ Homepage: <http://handbrake.m0k.org/>.
It may be used under the terms of the GNU General Public License. */
#ifndef HB_LANGUAGES_H
@@ -14,7 +14,7 @@ typedef struct iso639_lang_t
char * iso639_1; /* ISO-639-1 (2 characters) code */
} iso639_lang_t;
-iso639_lang_t languages[] =
+static iso639_lang_t languages[] =
{ { "Afar", "", "aa" },
{ "Abkhazian", "", "ab" },
{ "Afrikaans", "", "af" },
diff --git a/core/MadDec.c b/core/MadDec.c
new file mode 100644
index 000000000..deecfeebd
--- /dev/null
+++ b/core/MadDec.c
@@ -0,0 +1,9 @@
+/* $Id: MadDec.c,v 1.1 2003/11/03 12:08:01 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "MadDec.h"
+#include "Fifo.h"
+
diff --git a/core/MadDec.h b/core/MadDec.h
new file mode 100644
index 000000000..b1624338f
--- /dev/null
+++ b/core/MadDec.h
@@ -0,0 +1,15 @@
+/* $Id: MadDec.h,v 1.1 2003/11/03 12:08:01 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_MAD_DEC_H
+#define HB_MAD_DEC_H
+
+#include "HandBrakeInternal.h"
+
+HBMadDec * HBMadDecInit( HBHandle *, HBAudio * );
+void HBMadDecClose( HBMadDec * );
+
+#endif
diff --git a/core/Manager.cpp b/core/Manager.cpp
deleted file mode 100644
index 908aa08fd..000000000
--- a/core/Manager.cpp
+++ /dev/null
@@ -1,652 +0,0 @@
-/* $Id: Manager.cpp,v 1.70 2003/10/16 13:36:17 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 "AviMuxer.h"
-#include "DVDReader.h"
-#include "Fifo.h"
-#include "Manager.h"
-#include "Mp3Encoder.h"
-#include "Mpeg2Decoder.h"
-#include "Mpeg4Encoder.h"
-#include "MpegDemux.h"
-#include "Resizer.h"
-#include "Scanner.h"
-#include "Worker.h"
-
-#include <ffmpeg/avcodec.h>
-
-/* Public methods */
-
-HBManager::HBManager( bool debug, int cpuCount )
- : HBThread( "manager", HB_NORMAL_PRIORITY )
-{
- /* See Log() in Common.cpp */
- if( debug )
- {
- putenv( "HB_DEBUG=1" );
- }
-
- /* Check CPU count */
- if( !cpuCount )
- {
- fCPUCount = GetCPUCount();
- Log( "HBManager::HBManager: %d CPU%s detected", fCPUCount,
- ( fCPUCount > 1 ) ? "s" : "" );
- }
- else
- {
- 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" : "" );
- }
-
- /* 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 */
- fStatusLock->Lock();
- if( fStatus.fMode == HB_MODE_ENCODING )
- {
- fStatusLock->Unlock();
-
- StopRip();
- while( fStopRip )
- {
- Snooze( 10000 );
- }
- }
- else
- {
- fStatusLock->Unlock();
- }
-
- /* Stop scanning if needed */
- if( fScanner )
- {
- delete fScanner;
- }
-
- /* Remove temp files */
- char command[1024]; memset( command, 0, 1024 );
- sprintf( command, "rm -f /tmp/HB.%d.*", GetPid() );
- system( command );
-
- delete fStatusLock;
-}
-
-void HBManager::DoWork()
-{
- while( !fDie )
- {
- if( fStopScan )
- {
- /* Destroy the thread */
- delete fScanner;
- fScanner = NULL;
-
- /* Update interface */
- fStatusLock->Lock();
- if( fStatus.fTitleList && fStatus.fTitleList->CountItems() )
- {
- fStatus.fMode = HB_MODE_READY_TO_RIP;
- }
- else
- {
- fStatus.fMode = HB_MODE_INVALID_VOLUME;
- }
- fNeedUpdate = true;
- fStatusLock->Unlock();
-
- fStopScan = false;
- }
-
- if( fStopRip || fError || fRipDone )
- {
- if( fRipDone )
- {
- /* Wait a bit */
- while( fCurTitle->fPSFifo->Size() )
- {
- Snooze( 10000 );
- }
- while( fCurTitle->fMpeg2Fifo->Size() &&
- ( !fCurAudio1 || fCurAudio1->fAc3Fifo->Size() ) &&
- ( !fCurAudio2 || fCurAudio2->fAc3Fifo->Size() ) )
- {
- Snooze( 10000 );
- }
- Snooze( 500000 );
- }
- else
- {
- fStatusLock->Lock();
- fStatus.fMode = HB_MODE_STOPPING;
- fNeedUpdate = true;
- fStatusLock->Unlock();
- }
-
- /* Stop threads */
- delete fCurTitle->fDVDReader;
- delete fCurTitle->fAviMuxer;
- for( int i = 0; i < fCPUCount; i++ )
- {
- delete fCurTitle->fWorkers[i];
- }
-
- /* Clean up */
- delete fCurTitle->fMpegDemux;
- delete fCurTitle->fMpeg2Decoder;
- delete fCurTitle->fResizer;
- delete fCurTitle->fMpeg4Encoder;
-
- if( fCurAudio1 )
- {
- delete fCurAudio1->fAc3Decoder;
- delete fCurAudio1->fMp3Encoder;
- }
-
- if( fCurAudio2 )
- {
- delete fCurAudio2->fAc3Decoder;
- delete fCurAudio2->fMp3Encoder;
- }
-
- /* Destroy fifos */
- 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;
- }
-
- /* 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 );
- }
-}
-
-bool HBManager::NeedUpdate()
-{
- fStatusLock->Lock();
- if( fNeedUpdate )
- {
- fNeedUpdate = false;
- fStatusLock->Unlock();
- return true;
- }
- fStatusLock->Unlock();
-
- return false;
-}
-
-HBStatus HBManager::GetStatus()
-{
- fStatusLock->Lock();
- HBStatus status = fStatus;
- fStatusLock->Unlock();
-
- return status;
-}
-
-void HBManager::ScanVolumes( char * device )
-{
- if( !( fStatus.fMode &
- ( HB_MODE_NEED_VOLUME | HB_MODE_INVALID_VOLUME ) ) )
- {
- Log( "HBManager::ScanVolumes : current mode is %d, aborting",
- fStatus.fMode );
- return;
- }
-
- fScanner = new HBScanner( this, device );
-
- 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,
- HBAudio * audio2, char * file )
-{
- if( !title || !file )
- {
- Log( "HBManager::StartRip : error (title = %p, file = %s)",
- title, file );
- return;
- }
-
- if( !( fStatus.fMode & ( HB_MODE_READY_TO_RIP | HB_MODE_DONE |
- HB_MODE_CANCELED | HB_MODE_ERROR ) ) )
- {
- Log( "HBManager::StartRip : current mode is %d, aborting",
- fStatus.fMode );
- return;
- }
-
- FixPictureSettings( title );
-
- 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",
- 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 );
- }
- if( audio2 )
- {
- Log( "- audio 2: lang = %s (%x), bitrate = %d",
- audio2->fDescription, audio2->fId, audio2->fOutBitrate );
- }
-
- /* 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 );
- }
-
- /* 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 );
- if( audio1 )
- {
- audio1->fAc3Decoder = new HBAc3Decoder( this, audio1 );
- audio1->fMp3Encoder = new HBMp3Encoder( this, audio1 );
- }
- if( audio2 )
- {
- audio2->fAc3Decoder = new HBAc3Decoder( this, audio2 );
- audio2->fMp3Encoder = new HBMp3Encoder( this, 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++ )
- {
- 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;
- fStatus.fFrames = 0;
- fStatus.fStartDate = 0;
- fStatus.fRemainingTime = 0;
- fStatus.fSuspendDate = 0;
- fNeedUpdate = true;
- fStatusLock->Unlock();
-}
-
-void HBManager::SuspendRip()
-{
- if( fStatus.fMode != HB_MODE_ENCODING )
- {
- Log( "HBManager::SuspendRip : current mode is %d, aborting",
- fStatus.fMode );
- return;
- }
-
- fCurTitle->fDVDReader->Suspend();
- fCurTitle->fAviMuxer->Suspend();
- for( int i = 0; i < fCPUCount; i++ )
- {
- fCurTitle->fWorkers[i]->Suspend();
- }
-
- fStatusLock->Lock();
- fStatus.fMode = HB_MODE_SUSPENDED;
- fStatus.fSuspendDate = GetDate();
- fNeedUpdate = true;
- fStatusLock->Unlock();
-}
-
-void HBManager::ResumeRip()
-{
- if( fStatus.fMode != HB_MODE_SUSPENDED )
- {
- Log( "HBManager::ResumeRip : current mode is %d, aborting",
- fStatus.fMode );
- return;
- }
-
- fCurTitle->fDVDReader->Resume();
- fCurTitle->fAviMuxer->Resume();
- for( int i = 0; i < fCPUCount; i++ )
- {
- fCurTitle->fWorkers[i]->Resume();
- }
-
- fStatusLock->Lock();
- fStatus.fMode = HB_MODE_ENCODING;
- fStatus.fStartDate += GetDate() - fStatus.fSuspendDate;
- fNeedUpdate = true;
- fStatusLock->Unlock();
-}
-
-void HBManager::StopRip()
-{
- if( !( fStatus.fMode & ( HB_MODE_ENCODING | HB_MODE_SUSPENDED ) ) )
- {
- Log( "HBManager::StopRip : current mode is %d, aborting",
- fStatus.fMode );
- return;
- }
-
- /* Stop the threads */
- fStopRip = true;
-}
-
-#define fInWidth title->fInWidth
-#define fInHeight title->fInHeight
-#define fAspect title->fAspect
-#define fDeinterlace title->fDeinterlace
-#define fOutWidth title->fOutWidth
-#define fOutHeight title->fOutHeight
-#define fOutWidthMax title->fOutWidthMax
-#define fOutHeightMax title->fOutHeightMax
-#define fTopCrop title->fTopCrop
-#define fBottomCrop title->fBottomCrop
-#define fLeftCrop title->fLeftCrop
-#define fRightCrop title->fRightCrop
-
-void HBManager::FixPictureSettings( HBTitle * title )
-{
- /* Sanity checks */
- fTopCrop = EVEN( fTopCrop );
- fBottomCrop = EVEN( fBottomCrop );
- fLeftCrop = EVEN( fLeftCrop );
- fRightCrop = EVEN( fRightCrop );
-
- fOutWidth = MIN( fOutWidth, fOutWidthMax );
- fOutWidth = MAX( 16, fOutWidth );
-
- fOutHeight = MULTIPLE_16( (uint64_t) fOutWidth * fInWidth *
- ( fInHeight - fTopCrop - fBottomCrop ) *
- VOUT_ASPECT_FACTOR /
- ( (uint64_t) fInHeight *
- ( fInWidth - fLeftCrop - fRightCrop ) *
- fAspect ) );
- fOutHeight = MAX( 16, fOutHeight );
-
- if( fOutHeight > fOutHeightMax )
- {
- fOutHeight = fOutHeightMax;
- fOutWidth = MULTIPLE_16( (uint64_t) fOutHeight * fInHeight *
- ( fInWidth - fLeftCrop - fRightCrop ) *
- fAspect /
- ( (uint64_t) fInWidth *
- ( fInHeight - fTopCrop - fBottomCrop ) *
- VOUT_ASPECT_FACTOR ) );
- fOutWidth = MIN( fOutWidth, fOutWidthMax );
- fOutWidth = MAX( 16, fOutWidth );
- }
-}
-
-uint8_t * HBManager::GetPreview( HBTitle * title, uint32_t image )
-{
- FixPictureSettings( title );
-
- AVPicture pic1, pic2, pic3, pic4;
- uint8_t * buf1, * buf2, * buf3, * buf4;
-
- /* Original YUV picture */
- buf1 = (uint8_t*) malloc( 3 * fInWidth * fInHeight / 2 );
- avpicture_fill( &pic1, buf1, PIX_FMT_YUV420P, fInWidth,
- fInHeight );
-
- /* Deinterlaced YUV picture */
- buf2 = (uint8_t*) malloc( 3 * fInWidth * fInHeight / 2 );
- avpicture_fill( &pic2, buf2, PIX_FMT_YUV420P,
- fInWidth, fInHeight );
-
- /* Resized YUV picture */
- buf3 = (uint8_t*) malloc( 3 * fOutWidth * fOutHeight / 2 );
- avpicture_fill( &pic3, buf3, PIX_FMT_YUV420P, fOutWidth,
- fOutHeight );
-
- /* Resized RGB picture ) */
- buf4 = (uint8_t*) malloc( 4 * fOutWidth * fOutHeight );
- avpicture_fill( &pic4, buf4, PIX_FMT_RGBA32, fOutWidth,
- fOutHeight );
-
- /* Get the original image from the temp file */
- char fileName[1024]; memset( fileName, 0, 1024 );
- 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 );
- fclose( file );
-
- /* Deinterlace if needed, and resize */
- ImgReSampleContext * resampleContext =
- img_resample_full_init( fOutWidth, fOutHeight,
- fInWidth, fInHeight,
- fTopCrop, fBottomCrop,
- fLeftCrop, fRightCrop );
- if( fDeinterlace )
- {
- avpicture_deinterlace( &pic2, &pic1, PIX_FMT_YUV420P,
- fInWidth, fInHeight );
- img_resample( resampleContext, &pic3, &pic2 );
- }
- else
- {
- img_resample( resampleContext, &pic3, &pic1 );
- }
-
- /* Convert to RGB */
- img_convert( &pic4, PIX_FMT_RGBA32, &pic3, PIX_FMT_YUV420P,
- fOutWidth, fOutHeight );
-
- /* Create the final preview */
- uint8_t * preview = (uint8_t*) malloc( 4 * ( fOutWidthMax + 2 ) *
- ( fOutHeightMax + 2 ) );
-
- /* Blank it */
- memset( preview, 0,
- 4 * ( fOutWidthMax + 2 ) * ( fOutHeightMax + 2 ) );
-
- /* Draw the picture (centered) and draw the cropping zone */
- uint32_t leftOffset = 1 + ( fOutWidthMax - fOutWidth ) / 2;
- uint32_t topOffset = 1 + ( fOutHeightMax - fOutHeight ) / 2;
-
- memset( preview + 4 * ( ( fOutWidthMax + 2 ) * ( topOffset - 1 ) +
- leftOffset - 1 ),
- 0xFF, 4 * ( fOutWidth + 2 ) );
-
- for( uint32_t i = 0; i < fOutHeight; i++ )
- {
- memset( preview + 4 * ( ( fOutWidthMax + 2 ) *
- ( i + topOffset ) + leftOffset - 1 ),
- 0xFF, 4 );
- memcpy( preview + 4 * ( ( fOutWidthMax + 2 ) *
- ( i + topOffset ) + leftOffset ),
- buf4 + 4 * fOutWidth * i,
- 4 * fOutWidth );
- memset( preview + 4 * ( ( fOutWidthMax + 2 ) *
- ( i + topOffset ) + leftOffset +
- fOutWidth ),
- 0xFF, 4 );
- }
-
- memset( preview + 4 * ( ( fOutWidthMax + 2 ) *
- ( topOffset + fOutHeight ) +
- leftOffset - 1 ),
- 0xFF, 4 * ( fOutWidth + 2 ) );
-
- /* Free memory */
- free( buf1 );
- free( buf2 );
- free( buf3 );
- free( buf4 );
-
- return preview;
-}
-
-#undef fInWidth
-#undef fInHeight
-#undef fAspect
-#undef fDeinterlace
-#undef fOutWidth
-#undef fOutHeight
-#undef fOutWidthMax
-#undef fOutHeightMax
-#undef fTopCrop
-#undef fBottomCrop
-#undef fLeftCrop
-#undef fRightCrop
-
-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 )
-{
- fStatus.fTitleList = titleList;;
- fStopScan = true;
-}
-
-/* Called by the DVD reader */
-void HBManager::Done()
-{
- fRipDone = true;
-}
-
-void HBManager::Error( HBError error )
-{
- if( fStatus.fMode != HB_MODE_ENCODING )
- {
- return;
- }
-
- fStatus.fError = error;
- fError = true;
-}
-
-void HBManager::SetPosition( float pos )
-{
- if( !fStatus.fStartDate )
- {
- fStatus.fStartDate = GetDate();
- }
-
- fStatus.fFrames++;
-
- if( ( pos - fStatus.fPosition ) * 10000 < 1 )
- {
- return;
- }
-
- fStatusLock->Lock();
- fStatus.fPosition = pos;
- fStatus.fFrameRate = (float) fStatus.fFrames /
- ( ( (float) ( GetDate() - fStatus.fStartDate ) ) / 1000000 ) ;
- fStatus.fRemainingTime =
- (uint32_t) ( (float) ( GetDate() - fStatus.fStartDate ) *
- ( 1 - fStatus.fPosition ) /
- ( 1000000 * fStatus.fPosition ) );
- fNeedUpdate = true;
- fStatusLock->Unlock();
-}
-
diff --git a/core/Manager.h b/core/Manager.h
deleted file mode 100644
index dc885e5f5..000000000
--- a/core/Manager.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* $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/>.
- It may be used under the terms of the GNU General Public License. */
-
-#ifndef HB_MANAGER_H
-#define HB_MANAGER_H
-
-#include "Common.h"
-#include "Thread.h"
-
-class HBManager : public HBThread
-{
- public:
- HBManager( bool debug = false,
- int cpuCount = 0 );
- ~HBManager();
- void DoWork();
-
- /* Methods called by the interface */
- bool NeedUpdate();
- HBStatus GetStatus();
- void ScanVolumes( char * device );
- void StartRip( HBTitle * title, HBAudio * audio1,
- HBAudio * audio2, char * file );
- void SuspendRip();
- void ResumeRip();
- void StopRip();
- uint8_t * GetPreview( HBTitle * title, uint32_t image );
-
- /* Methods called by the working threads */
- void Scanning( char * volume, int title );
- void ScanDone( HBList * titleList );
- void Done();
- void Error( HBError error );
- void SetPosition( float pos );
-
- private:
- void FixPictureSettings( HBTitle * title );
-
- int fPid;
- int fCPUCount;
-
- /* Booleans used in DoWork() */
- bool fStopScan;
- volatile bool fStopRip;
- bool fRipDone;
- bool fError;
-
- /* Scanner thread */
- HBScanner * fScanner;
-
- /* Status infos */
- HBLock * fStatusLock;
- bool fNeedUpdate;
- HBStatus fStatus;
-
- HBTitle * fCurTitle;
- HBAudio * fCurAudio1;
- HBAudio * fCurAudio2;
-};
-
-#endif
diff --git a/core/Mp3Enc.c b/core/Mp3Enc.c
new file mode 100644
index 000000000..70693467f
--- /dev/null
+++ b/core/Mp3Enc.c
@@ -0,0 +1,281 @@
+/* $Id: Mp3Enc.c,v 1.5 2003/11/07 21:52:57 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "Fifo.h"
+#include "Mp3Enc.h"
+#include "Work.h"
+
+#include <lame/lame.h>
+
+/* Local prototypes */
+static int Mp3EncWork( HBWork * );
+static int GetBytes( HBMp3Enc * );
+
+struct HBMp3Enc
+{
+ HB_WORK_COMMON_MEMBERS
+
+ HBHandle * handle;
+ HBAudio * audio;
+ lame_global_flags * globalFlags;
+ HBBuffer * rawBuffer;
+ int rawBufferPos;
+ float position;
+ int samplesNeeded;
+ int samplesGot;
+ float * left;
+ float * right;
+ HBBuffer * mp3Buffer;
+};
+
+HBMp3Enc * HBMp3EncInit( HBHandle * handle, HBAudio * audio )
+{
+ HBMp3Enc * m;
+ if( !( m = malloc( sizeof( HBMp3Enc ) ) ) )
+ {
+ HBLog( "HBMp3EncInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ m->name = strdup( "Mp3Enc" );
+ m->work = Mp3EncWork;
+
+ m->handle = handle;
+ m->audio = audio;
+ m->globalFlags = NULL;
+ m->rawBuffer = NULL;
+ m->rawBufferPos = 0;
+ m->position = 0.0;
+ m->samplesNeeded = 0;
+ m->samplesGot = 0;
+ m->left = NULL;
+ m->right = NULL;
+ m->mp3Buffer = NULL;
+
+ return m;
+}
+
+void HBMp3EncClose( HBMp3Enc ** _m )
+{
+ HBMp3Enc * m = *_m;
+
+ if( m->globalFlags ) lame_close( m->globalFlags );
+ if( m->rawBuffer ) HBBufferClose( &m->rawBuffer );
+ if( m->left ) free( m->left );
+ if( m->right ) free( m->right );
+ if( m->mp3Buffer ) HBBufferClose( &m->mp3Buffer );
+ free( m->name );
+ free( m );
+
+ *_m = NULL;
+}
+
+static int Mp3EncWork( HBWork * w )
+{
+ HBMp3Enc * m = (HBMp3Enc*) w;
+ HBAudio * audio = m->audio;
+
+ HBBuffer * mp3Buffer;
+ int ret;
+
+ int didSomething = 0;
+
+ if( !m->globalFlags )
+ {
+ int i;
+
+ /* Get a first buffer so we know that audio->inSampleRate is
+ correct */
+ if( ( m->rawBuffer = HBFifoPop( audio->rawFifo ) ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+ m->rawBufferPos = 0;
+ m->position = m->rawBuffer->position;
+
+ /* The idea is to have exactly one mp3 frame (i.e. 1152 samples) by
+ output buffer. As we are resampling from inSampleRate to
+ outSampleRate, we will give ( 1152 * inSampleRate ) /
+ ( 2 * outSampleRate ) samples to libmp3lame so we are sure we
+ will never get more than 1 frame at a time */
+ m->samplesNeeded = 1152 * audio->inSampleRate /
+ audio->outSampleRate / 2;
+
+ HBLog( "HBMp3Enc: opening lame (%d->%d Hz, %d kbps)",
+ audio->inSampleRate, audio->outSampleRate,
+ audio->outBitrate );
+ m->globalFlags = lame_init();
+ lame_set_in_samplerate( m->globalFlags, audio->inSampleRate );
+ lame_set_out_samplerate( m->globalFlags, audio->outSampleRate );
+ lame_set_brate( m->globalFlags, audio->outBitrate );
+
+ if( lame_init_params( m->globalFlags ) == -1 )
+ {
+ HBLog( "HBMp3Enc: lame_init_params() failed" );
+ HBErrorOccured( m->handle, HB_ERROR_MP3_INIT );
+ return didSomething;
+ }
+
+ m->left = malloc( m->samplesNeeded * sizeof( float ) );
+ m->right = malloc( m->samplesNeeded * sizeof( float ) );
+
+ if( !m->left || !m->right )
+ {
+ HBLog( "HBMp3Enc: malloc() failed, gonna crash" );
+ }
+
+ for( i = 0; i < m->samplesNeeded; i++ )
+ {
+ m->left[i] = 0.0;
+ m->right[i] = 0.0;
+ }
+ }
+
+ /* Push encoded buffer */
+ if( m->mp3Buffer )
+ {
+ if( HBFifoPush( audio->mp3Fifo, &m->mp3Buffer ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+ }
+
+ /* A/V synchro fix in case audio doesn't start at the same time
+ than video */
+ if( audio->delay > 0 )
+ {
+ /* Audio starts later - insert some silence */
+ int length = m->samplesNeeded * 1000 / audio->inSampleRate;
+
+ if( audio->delay > length )
+ {
+ HBLog( "HBMp3Enc: adding %d ms of silence", length );
+ m->samplesGot = m->samplesNeeded;
+ audio->delay -= length;
+ }
+ else
+ {
+ audio->delay = 0;
+ }
+ }
+ else if( audio->delay < 0 )
+ {
+ /* Audio starts sooner - trash some */
+ int length = m->samplesNeeded * 1000 / audio->inSampleRate;
+
+ if( - audio->delay > length )
+ {
+ if( GetBytes( m ) )
+ {
+ didSomething = 1;
+ HBLog( "HBMp3Enc: trashing %d ms", length );
+ m->samplesGot = 0;
+ audio->delay += length;
+ return didSomething;
+ }
+ else
+ {
+ return didSomething;
+ }
+ }
+ else
+ {
+ audio->delay = 0;
+ }
+ }
+
+ /* Get new samples */
+ if( GetBytes( m ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+
+ m->samplesGot = 0;
+
+ mp3Buffer = HBBufferInit( LAME_MAXMP3BUFFER );
+ ret = lame_encode_buffer_float( m->globalFlags, m->left,
+ m->right, m->samplesNeeded,
+ mp3Buffer->data,
+ mp3Buffer->size );
+
+ if( ret < 0 )
+ {
+ /* Error */
+ HBLog( "HBMp3Enc: lame_encode_buffer_float() failed (%d)",
+ ret );
+ HBErrorOccured( m->handle, HB_ERROR_MP3_ENCODE );
+ HBBufferClose( &mp3Buffer );
+ }
+ else if( ret == 0 )
+ {
+ /* No error, but nothing encoded */
+ HBBufferClose( &mp3Buffer );
+ }
+ else
+ {
+ /* Encoding was successful */
+ mp3Buffer->size = ret;
+ mp3Buffer->keyFrame = 1;
+ mp3Buffer->position = m->position;
+
+ m->mp3Buffer = mp3Buffer;
+ }
+
+ return didSomething;
+}
+
+static int GetBytes( HBMp3Enc * m )
+{
+ while( m->samplesGot < m->samplesNeeded )
+ {
+ int i;
+
+ if( !m->rawBuffer )
+ {
+ if( !( m->rawBuffer = HBFifoPop( m->audio->rawFifo ) ) )
+ {
+ return 0;
+ }
+
+ m->rawBufferPos = 0;
+ m->position = m->rawBuffer->position;
+ }
+
+ i = MIN( m->samplesNeeded - m->samplesGot,
+ ( m->rawBuffer->size / 2 -
+ m->rawBufferPos ) / sizeof( float ) );
+
+ memcpy( m->left + m->samplesGot,
+ m->rawBuffer->data + m->rawBufferPos,
+ i * sizeof( float ) );
+ memcpy( m->right + m->samplesGot,
+ m->rawBuffer->data + m->rawBuffer->size / 2 +
+ m->rawBufferPos,
+ i * sizeof( float ) );
+
+ m->samplesGot += i;
+ m->rawBufferPos += i * sizeof( float );
+
+ if( m->rawBufferPos == m->rawBuffer->size / 2 )
+ {
+ HBBufferClose( &m->rawBuffer );
+ }
+ }
+
+ return 1;
+}
diff --git a/core/Mp3Enc.h b/core/Mp3Enc.h
new file mode 100644
index 000000000..db02f4f44
--- /dev/null
+++ b/core/Mp3Enc.h
@@ -0,0 +1,15 @@
+/* $Id: Mp3Enc.h,v 1.1 2003/11/03 12:08:01 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_MP3_ENCODER_H
+#define HB_MP3_ENCODER_H
+
+#include "HandBrakeInternal.h"
+
+HBMp3Enc * HBMp3EncInit( HBHandle *, HBAudio * );
+void HBMp3EncClose( HBMp3Enc ** );
+
+#endif
diff --git a/core/Mp3Encoder.cpp b/core/Mp3Encoder.cpp
deleted file mode 100644
index 96ae8c568..000000000
--- a/core/Mp3Encoder.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/* $Id: Mp3Encoder.cpp,v 1.14 2003/10/14 14:35:20 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 "Mp3Encoder.h"
-#include "Manager.h"
-#include "Fifo.h"
-
-#include <lame/lame.h>
-
-HBMp3Encoder::HBMp3Encoder( HBManager * manager, HBAudio * 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;
-}
-
-bool HBMp3Encoder::Work()
-{
- if( !Lock() )
- {
- return false;
- }
-
- if( !fInitDone )
- {
- /* 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;
- }
-
- fLeftSamples = (float*) malloc( fCount * sizeof( float ) );
- fRightSamples = (float*) malloc( fCount * sizeof( float ) );
-
- fInitDone = true;
- }
-
- if( fMp3Buffer )
- {
- if( fAudio->fMp3Fifo->Push( fMp3Buffer ) )
- {
- fMp3Buffer = NULL;
- }
- else
- {
- Unlock();
- return false;
- }
- }
-
- /* Get new samples */
- if( GetSamples() )
- {
- fSamplesNb = 0;
-
- fMp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER );
- int ret = lame_encode_buffer_float( fGlobalFlags, fLeftSamples,
- fRightSamples, fCount,
- fMp3Buffer->fData,
- fMp3Buffer->fSize );
-
- if( ret < 0 )
- {
- 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 */
- fMp3Buffer->fSize = ret;
- fMp3Buffer->fKeyFrame = true;
- fMp3Buffer->fPosition = fPosition;
- }
- else
- {
- delete fMp3Buffer;
- fMp3Buffer = NULL;
- }
- }
- else
- {
- Unlock();
- return false;
- }
-
- Unlock();
- return true;
-}
-
-bool HBMp3Encoder::Lock()
-{
- fLock->Lock();
- if( fUsed )
- {
- fLock->Unlock();
- return false;
- }
- fUsed = true;
- fLock->Unlock();
- return true;
-}
-
-void HBMp3Encoder::Unlock()
-{
- fLock->Lock();
- fUsed = false;
- fLock->Unlock();
-}
-
-bool HBMp3Encoder::GetSamples()
-{
- while( fSamplesNb < fCount )
- {
- if( !fRawBuffer )
- {
- if( !( fRawBuffer = fAudio->fRawFifo->Pop() ) )
- {
- return false;
- }
-
- fPosInBuffer = 0;
- fPosition = fRawBuffer->fPosition;
- }
-
- int willCopy = MIN( fCount - fSamplesNb, 6 * 256 - fPosInBuffer );
-
- memcpy( fLeftSamples + fSamplesNb,
- (float*) fRawBuffer->fData + fPosInBuffer,
- willCopy * sizeof( float ) );
- memcpy( fRightSamples + fSamplesNb,
- (float*) fRawBuffer->fData + 6 * 256 + fPosInBuffer,
- willCopy * sizeof( float ) );
-
- fSamplesNb += willCopy;
- fPosInBuffer += willCopy;
-
- if( fPosInBuffer == 6 * 256 )
- {
- delete fRawBuffer;
- fRawBuffer = NULL;
- }
- }
-
- return true;
-}
diff --git a/core/Mp3Encoder.h b/core/Mp3Encoder.h
deleted file mode 100644
index fb8348961..000000000
--- a/core/Mp3Encoder.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* $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/>.
- It may be used under the terms of the GNU General Public License. */
-
-#ifndef HB_MP3_ENCODER_H
-#define HB_MP3_ENCODER_H
-
-#include "Common.h"
-
-class HBMp3Encoder
-{
- public:
- HBMp3Encoder( HBManager * manager,
- HBAudio * audio );
- bool Work();
-
- private:
- 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/Mpeg2Dec.c b/core/Mpeg2Dec.c
new file mode 100644
index 000000000..d6ce22b3f
--- /dev/null
+++ b/core/Mpeg2Dec.c
@@ -0,0 +1,195 @@
+/* $Id: Mpeg2Dec.c,v 1.3 2003/11/06 12:33:11 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "Fifo.h"
+#include "Mpeg2Dec.h"
+#include "Work.h"
+
+#include <mpeg2dec/mpeg2.h>
+
+/* Local prototypes */
+static int Mpeg2DecWork( HBWork * );
+
+struct HBMpeg2Dec
+{
+ HB_WORK_COMMON_MEMBERS
+
+ HBHandle * handle;
+ HBTitle * title;
+ HBList * rawBufferList;
+ int pass;
+ mpeg2dec_t * libmpeg2;
+ const mpeg2_info_t * info;
+ int lateField;
+};
+
+HBMpeg2Dec * HBMpeg2DecInit( HBHandle * handle, HBTitle * title )
+{
+ HBMpeg2Dec * m ;
+ if( !( m = malloc( sizeof( HBMpeg2Dec ) ) ) )
+ {
+ HBLog( "HBMpeg2Dec: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ m->name = strdup( "Mpeg2Dec" );
+ m->work = Mpeg2DecWork;
+
+ m->handle = handle;
+ m->title = title;
+
+ m->rawBufferList = HBListInit();
+ m->pass = 42;
+ m->libmpeg2 = NULL;
+ m->info = NULL;
+ m->lateField = 0;
+
+ return m;
+}
+
+void HBMpeg2DecClose( HBMpeg2Dec ** _m )
+{
+ HBBuffer * buffer;
+
+ HBMpeg2Dec * m = *_m;
+
+ if( m->libmpeg2 )
+ {
+ HBLog( "HBMpeg2Dec: closing libmpeg2 (pass %d)", m->pass );
+ mpeg2_close( m->libmpeg2 );
+ }
+ while( ( buffer = HBListItemAt( m->rawBufferList, 0 ) ) )
+ {
+ HBListRemove( m->rawBufferList, buffer );
+ HBBufferClose( &buffer );
+ }
+ HBListClose( &m->rawBufferList );
+ free( m->name );
+ free( m );
+
+ *_m = NULL;
+}
+
+static int Mpeg2DecWork( HBWork * w )
+{
+ HBMpeg2Dec * m = (HBMpeg2Dec*) w;
+ HBTitle * title = m->title;
+ HBBuffer * mpeg2Buffer;
+ HBBuffer * rawBuffer;
+ HBBuffer * tmpBuffer;
+ mpeg2_state_t state;
+
+ int didSomething = 0;
+
+ /* Push decoded buffers */
+ while( ( rawBuffer = (HBBuffer*)
+ HBListItemAt( m->rawBufferList, 0 ) ) )
+ {
+ tmpBuffer = rawBuffer;
+ if( HBFifoPush( title->rawFifo, &rawBuffer ) )
+ {
+ didSomething = 1;
+ HBListRemove( m->rawBufferList, tmpBuffer );
+ }
+ else
+ {
+ return didSomething;
+ }
+ }
+
+ /* Get a new buffer to decode */
+ if( ( mpeg2Buffer = HBFifoPop( title->mpeg2Fifo ) ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+
+ /* Init or re-init if needed */
+ if( mpeg2Buffer->pass != m->pass )
+ {
+ if( m->libmpeg2 )
+ {
+ HBLog( "HBMpeg2Dec: closing libmpeg2 (pass %d)", m->pass );
+ mpeg2_close( m->libmpeg2 );
+ }
+
+ m->pass = mpeg2Buffer->pass;
+
+ HBLog( "HBMpeg2Dec: opening libmpeg2 (pass %d)", m->pass );
+ m->libmpeg2 = mpeg2_init();
+ m->info = mpeg2_info( m->libmpeg2 );
+ m->lateField = 0;
+ }
+
+ /* Decode */
+ mpeg2_buffer( m->libmpeg2, mpeg2Buffer->data,
+ mpeg2Buffer->data + mpeg2Buffer->size );
+
+ for( ;; )
+ {
+ state = mpeg2_parse( m->libmpeg2 );
+
+ if( state == STATE_BUFFER )
+ {
+ break;
+ }
+ else if( ( state == STATE_SLICE || state == STATE_END ) &&
+ m->info->display_fbuf )
+ {
+ rawBuffer = HBBufferInit( 3 * title->inWidth *
+ title->outWidth );
+
+ /* TODO: make libmpeg2 write directly in our buffer */
+ memcpy( rawBuffer->data, m->info->display_fbuf->buf[0],
+ title->inWidth * title->inHeight );
+ memcpy( rawBuffer->data + title->inWidth * title->inHeight,
+ m->info->display_fbuf->buf[1],
+ title->inWidth * title->inHeight / 4 );
+ memcpy( rawBuffer->data + title->inWidth * title->inHeight +
+ title->inWidth * title->inHeight / 4,
+ m->info->display_fbuf->buf[2],
+ title->inWidth * title->inHeight / 4 );
+
+ rawBuffer->position = mpeg2Buffer->position;
+ rawBuffer->pass = mpeg2Buffer->pass;
+
+ HBListAdd( m->rawBufferList, rawBuffer );
+
+ /* NTSC pulldown kludge */
+ if( m->info->display_picture->nb_fields == 3 )
+ {
+ if( m->lateField )
+ {
+ tmpBuffer = HBBufferInit( rawBuffer->size );
+ tmpBuffer->position = rawBuffer->position;
+ tmpBuffer->pass = rawBuffer->pass;
+ tmpBuffer->last = rawBuffer->last;
+ memcpy( tmpBuffer->data, rawBuffer->data,
+ tmpBuffer->size );
+ HBListAdd( m->rawBufferList, tmpBuffer );
+ }
+ m->lateField = !m->lateField;
+ }
+ }
+ else if( state == STATE_INVALID )
+ {
+ /* Shouldn't happen on a DVD */
+ HBLog( "HBMpeg2Dec: STATE_INVALID" );
+ }
+ }
+
+ if( mpeg2Buffer->last )
+ {
+ HBDone( m->handle );
+ }
+
+ HBBufferClose( &mpeg2Buffer );
+
+ return didSomething;
+}
diff --git a/core/Mpeg2Dec.h b/core/Mpeg2Dec.h
new file mode 100644
index 000000000..af7f18c44
--- /dev/null
+++ b/core/Mpeg2Dec.h
@@ -0,0 +1,15 @@
+/* $Id: Mpeg2Dec.h,v 1.1 2003/11/03 12:08:01 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_MPEG2_DEC_H
+#define HB_MPEG2_DEC_H
+
+#include "HandBrakeInternal.h"
+
+HBMpeg2Dec * HBMpeg2DecInit( HBHandle *, HBTitle * );
+void HBMpeg2DecClose( HBMpeg2Dec ** );
+
+#endif
diff --git a/core/Mpeg2Decoder.cpp b/core/Mpeg2Decoder.cpp
deleted file mode 100644
index a9b6a5373..000000000
--- a/core/Mpeg2Decoder.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/* $Id: Mpeg2Decoder.cpp,v 1.22 2003/10/14 14:35:20 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 "Mpeg2Decoder.h"
-#include "Manager.h"
-#include "Fifo.h"
-
-extern "C" {
-#include <mpeg2dec/mpeg2.h>
-}
-#include <ffmpeg/avcodec.h>
-
-HBMpeg2Decoder::HBMpeg2Decoder( HBManager * manager, HBTitle * title )
-{
- fManager = manager;
- fTitle = title;
-
- fLock = new HBLock();
- fUsed = false;
-
- fPass = 42;
- fRawBuffer = NULL;
- fRawBufferList = new HBList();
- fHandle = NULL;
-}
-
-bool HBMpeg2Decoder::Work()
-{
- if( !Lock() )
- {
- return false;
- }
-
- /* Push decoded buffers */
- while( ( fRawBuffer =
- (HBBuffer*) fRawBufferList->ItemAt( 0 ) ) )
- {
- if( fTitle->fRawFifo->Push( fRawBuffer ) )
- {
- fRawBufferList->RemoveItem( fRawBuffer );
- }
- else
- {
- Unlock();
- return false;
- }
- }
-
- /* Get a new buffer to decode */
- if( ( fMpeg2Buffer = fTitle->fMpeg2Fifo->Pop() ) )
- {
- /* (Re)init if needed */
- if( fMpeg2Buffer->fPass != fPass )
- {
- fPass = fMpeg2Buffer->fPass;
- Init();
- }
-
- /* Do the job */
- DecodeBuffer();
- }
- else
- {
- Unlock();
- return false;
- }
-
- Unlock();
- return true;
-}
-
-bool HBMpeg2Decoder::Lock()
-{
- fLock->Lock();
- if( fUsed )
- {
- fLock->Unlock();
- return false;
- }
- fUsed = true;
- fLock->Unlock();
- return true;
-}
-
-void HBMpeg2Decoder::Unlock()
-{
- fLock->Lock();
- fUsed = false;
- fLock->Unlock();
-}
-
-void HBMpeg2Decoder::Init()
-{
- if( fHandle )
- {
- mpeg2_close( fHandle );
- }
-
- fLateField = false;
-
- fHandle = mpeg2_init();
-}
-
-void HBMpeg2Decoder::DecodeBuffer()
-{
- const mpeg2_info_t * info = mpeg2_info( fHandle );
-
- /* Feed libmpeg2 */
- mpeg2_buffer( fHandle, fMpeg2Buffer->fData,
- fMpeg2Buffer->fData + fMpeg2Buffer->fSize );
-
- mpeg2_state_t state;
- for( ;; )
- {
- state = mpeg2_parse( fHandle );
-
- if( state == STATE_BUFFER )
- {
- break;
- }
- else if( ( state == STATE_SLICE || state == STATE_END ) &&
- info->display_fbuf )
- {
- fRawBuffer = new HBBuffer( 3 * fTitle->fInWidth *
- fTitle->fInHeight / 2 );
-
- /* TODO : make libmpeg2 write directly in our buffer */
- memcpy( fRawBuffer->fData,
- info->display_fbuf->buf[0],
- fTitle->fInWidth * fTitle->fInHeight );
- memcpy( fRawBuffer->fData + fTitle->fInWidth *
- fTitle->fInHeight,
- info->display_fbuf->buf[1],
- fTitle->fInWidth * fTitle->fInHeight / 4 );
- memcpy( fRawBuffer->fData + fTitle->fInWidth *
- fTitle->fInHeight + fTitle->fInWidth *
- fTitle->fInHeight / 4,
- info->display_fbuf->buf[2],
- fTitle->fInWidth * fTitle->fInHeight / 4 );
-
- fRawBuffer->fPosition = fMpeg2Buffer->fPosition;
- fRawBuffer->fPass = fMpeg2Buffer->fPass;
-
- fRawBufferList->AddItem( fRawBuffer );
-
- /* NTSC pulldown kludge */
- if( info->display_picture->nb_fields == 3 )
- {
- if( fLateField )
- {
- 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;
- }
- }
- else if( state == STATE_INVALID )
- {
- /* Shouldn't happen on a DVD */
- Log( "HBMpeg2Decoder: STATE_INVALID" );
- }
- }
-
- delete fMpeg2Buffer;
- fMpeg2Buffer = NULL;
-}
-
diff --git a/core/Mpeg2Decoder.h b/core/Mpeg2Decoder.h
deleted file mode 100644
index 6e20509a2..000000000
--- a/core/Mpeg2Decoder.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* $Id: Mpeg2Decoder.h,v 1.16 2003/10/14 14:35:20 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_MPEG2_DECODER_H
-#define HB_MPEG2_DECODER_H
-
-#include "Common.h"
-
-class HBMpeg2Decoder
-{
- public:
- HBMpeg2Decoder( HBManager * manager,
- HBTitle * title );
- bool Work();
-
- private:
- bool Lock();
- void Unlock();
-
- void Init();
- void DecodeBuffer();
-
- HBManager * fManager;
- HBTitle * fTitle;
-
- HBLock * fLock;
- bool fUsed;
-
- uint32_t fPass;
- HBBuffer * fMpeg2Buffer;
- HBBuffer * fRawBuffer;
- HBList * fRawBufferList;
- mpeg2dec_t * fHandle;
- bool fLateField;
-};
-
-#endif
diff --git a/core/Mpeg4Encoder.cpp b/core/Mpeg4Encoder.cpp
deleted file mode 100644
index bf5821a4c..000000000
--- a/core/Mpeg4Encoder.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/* $Id: Mpeg4Encoder.cpp,v 1.25 2003/10/14 15:23:56 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 "Mpeg4Encoder.h"
-#include "Manager.h"
-#include "Fifo.h"
-
-#include <ffmpeg/avcodec.h>
-
-HBMpeg4Encoder::HBMpeg4Encoder( HBManager * manager, HBTitle * title )
-{
- fManager = manager;
- fTitle = title;
-
- fLock = new HBLock();
- fUsed = false;
-
- fPass = 42;
- fMpeg4Buffer = NULL;
- fFile = NULL;
- fFrame = avcodec_alloc_frame();
- fLog = NULL;
-}
-
-bool HBMpeg4Encoder::Work()
-{
- if( !Lock() )
- {
- return false;
- }
-
- if( fMpeg4Buffer )
- {
- if( fTitle->fMpeg4Fifo->Push( fMpeg4Buffer ) )
- {
- fMpeg4Buffer = NULL;
- }
- else
- {
- Unlock();
- return false;
- }
- }
-
- if( ( fResizedBuffer = fTitle->fResizedFifo->Pop() ) )
- {
- if( fResizedBuffer->fPass != fPass )
- {
- fPass = fResizedBuffer->fPass;
- Init();
- }
-
- fManager->SetPosition( fResizedBuffer->fPosition );
- EncodeBuffer();
- }
- else
- {
- Unlock();
- return false;
- }
-
- Unlock();
- return true;
-}
-
-bool HBMpeg4Encoder::Lock()
-{
- fLock->Lock();
- if( fUsed )
- {
- fLock->Unlock();
- return false;
- }
- 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( HB_ERROR_MPEG4_INIT );
- return;
- }
-
- fContext = avcodec_alloc_context();
- fContext->bit_rate = 1024 * fTitle->fBitrate;
- fContext->bit_rate_tolerance = 10240 * fTitle->fBitrate;
- fContext->width = fTitle->fOutWidth;
- fContext->height = fTitle->fOutHeight;
- fContext->frame_rate = fTitle->fRate;
- fContext->frame_rate_base = fTitle->fScale;
- fContext->gop_size = 10 * fTitle->fRate / fTitle->fScale;
-
- if( fPass == 1 )
- {
- fContext->flags |= CODEC_FLAG_PASS1;
-
- char fileName[1024]; memset( fileName, 0, 1024 );
- sprintf( fileName, "/tmp/HB.%d.ffmpeg.log", fManager->GetPid() );
- fFile = fopen( fileName, "w" );
- }
- else if( fPass == 2 )
- {
- fContext->flags |= CODEC_FLAG_PASS2;
-
- char fileName[1024]; memset( fileName, 0, 1024 );
- sprintf( fileName, "/tmp/HB.%d.ffmpeg.log", fManager->GetPid() );
- fFile = fopen( fileName, "r" );
- fseek( fFile, 0, SEEK_END );
- uint32_t size = ftell( fFile );
- fLog = (char*) malloc( size + 1 );
- fseek( fFile, 0, SEEK_SET );
- fread( fLog, size, 1, fFile );
- fclose( fFile );
- fLog[size] = '\0';
- fContext->stats_in = fLog;
- }
-
- if( avcodec_open( fContext, codec ) < 0 )
- {
- Log( "HBMpeg4Encoder: avcodec_open() failed" );
- fManager->Error( HB_ERROR_MPEG4_INIT );
- return;
- }
-}
-
-void HBMpeg4Encoder::EncodeBuffer()
-{
- fFrame->data[0] = fResizedBuffer->fData;
- fFrame->data[1] = fFrame->data[0] + fTitle->fOutWidth *
- fTitle->fOutHeight;
- fFrame->data[2] = fFrame->data[1] + fTitle->fOutWidth *
- fTitle->fOutHeight / 4;
- fFrame->linesize[0] = fTitle->fOutWidth;
- fFrame->linesize[1] = fTitle->fOutWidth / 2;
- fFrame->linesize[2] = fTitle->fOutWidth / 2;
-
- fMpeg4Buffer = new HBBuffer( 3 * fTitle->fOutWidth *
- fTitle->fOutHeight / 2 );
- /* Should be really too much... */
-
- fMpeg4Buffer->fPosition = fResizedBuffer->fPosition;
- fMpeg4Buffer->fSize =
- avcodec_encode_video( fContext, fMpeg4Buffer->fData,
- fMpeg4Buffer->fAllocSize, fFrame );
- fMpeg4Buffer->fKeyFrame = ( fContext->coded_frame->key_frame != 0 );
-
- if( fResizedBuffer->fPass == 1 )
- {
- if( fContext->stats_out )
- {
- fprintf( fFile, "%s", fContext->stats_out );
- }
- delete fMpeg4Buffer;
- fMpeg4Buffer = NULL;
- }
-
- delete fResizedBuffer;
- fResizedBuffer = NULL;
-}
-
diff --git a/core/Mpeg4Encoder.h b/core/Mpeg4Encoder.h
deleted file mode 100644
index 3d20f315a..000000000
--- a/core/Mpeg4Encoder.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* $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/>.
- It may be used under the terms of the GNU General Public License. */
-
-#ifndef HB_MPEG4_ENCODER_H
-#define HB_MPEG4_ENCODER_H
-
-#include "Common.h"
-
-class HBMpeg4Encoder
-{
- public:
- HBMpeg4Encoder( HBManager * manager,
- HBTitle * title );
- bool Work();
-
- private:
- bool Lock();
- void Unlock();
-
- void Init();
- 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
deleted file mode 100644
index 249ee2738..000000000
--- a/core/MpegDemux.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-/* $Id: MpegDemux.cpp,v 1.20 2003/10/16 13:36:17 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 "MpegDemux.h"
-#include "Manager.h"
-#include "Fifo.h"
-
-extern "C" {
-#include <a52dec/a52.h>
-}
-
-HBMpegDemux::HBMpegDemux( HBManager * manager, HBTitle * title,
- HBAudio * audio1, HBAudio * audio2 )
-{
- fManager = manager;
- fTitle = title;
- fAudio1 = audio1;
- fAudio2 = audio2;
-
- fLock = new HBLock();
- fUsed = false;
-
- fPSBuffer = NULL;
- fESBuffer = NULL;
- fESBufferList = NULL;
-
- fFirstVideoPTS = -1;
- fFirstAudio1PTS = -1;
- fFirstAudio2PTS = -1;
-}
-
-HBMpegDemux::~HBMpegDemux()
-{
- /* Free memory */
- if( fESBufferList )
- {
- while( ( fESBuffer = (HBBuffer*) fESBufferList->ItemAt( 0 ) ) )
- {
- fESBufferList->RemoveItem( fESBuffer );
- delete fESBuffer;
- }
- }
- delete fLock;
-}
-
-bool HBMpegDemux::Work()
-{
- if( !Lock() )
- {
- return false;
- }
-
- /* Push waiting buffers */
- if( fESBufferList )
- {
- for( uint32_t i = 0; i < fESBufferList->CountItems(); )
- {
- 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 )
- {
- fFirstVideoPTS = fESBuffer->fPTS;
- Log( "HBMpegDemux: got first 0xE0 packet (%lld)",
- fFirstVideoPTS );
- }
- if( fTitle->fMpeg2Fifo->Push( fESBuffer ) )
- {
- fESBufferList->RemoveItem( fESBuffer );
- }
- else
- {
- i++;
- }
- }
- else if( fAudio1 &&
- fESBuffer->fStreamId == fAudio1->fId )
- {
- if( fFirstAudio1PTS < 0 )
- {
- fFirstAudio1PTS = fESBuffer->fPTS;
- Log( "HBMpegDemux: got first 0x%x packet (%lld)",
- fAudio1->fId, fFirstAudio1PTS );
-
- fAudio1->fDelay =
- ( fFirstAudio1PTS - fFirstVideoPTS ) / 90;
- }
- if( fAudio1->fAc3Fifo->Push( fESBuffer ) )
- {
- fESBufferList->RemoveItem( fESBuffer );
- }
- else
- {
- i++;
- }
- }
- else if( fAudio2 &&
- fESBuffer->fStreamId == fAudio2->fId )
- {
- if( fFirstAudio2PTS < 0 )
- {
- fFirstAudio2PTS = fESBuffer->fPTS;
- Log( "HBMpegDemux: got first 0x%x packet (%lld)",
- fAudio2->fId, fFirstAudio2PTS );
-
- fAudio2->fDelay =
- ( fFirstAudio2PTS - fFirstVideoPTS ) / 90;
- }
- if( fAudio2->fAc3Fifo->Push( fESBuffer ) )
- {
- fESBufferList->RemoveItem( fESBuffer );
- }
- else
- {
- i++;
- }
- }
- else
- {
- fESBufferList->RemoveItem( fESBuffer );
- delete fESBuffer;
- }
- }
-
- if( !fESBufferList->CountItems() )
- {
- delete fESBufferList;
- fESBufferList = NULL;
- }
- else
- {
- Unlock();
- return false;
- }
- }
-
- /* Get a PS packet */
- if( ( fPSBuffer = fTitle->fPSFifo->Pop() ) )
- {
- /* Get the ES data in it */
- PStoES( fPSBuffer, &fESBufferList );
- }
- else
- {
- Unlock();
- return false;
- }
-
- Unlock();
- return true;
-}
-
-bool HBMpegDemux::Lock()
-{
- fLock->Lock();
- if( fUsed )
- {
- 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 )
-{
-#define psData (psBuffer->fData)
-
- uint32_t pos = 0;
-
- /* pack_header */
- if( psData[pos] != 0 || psData[pos+1] != 0 ||
- psData[pos+2] != 0x1 || psData[pos+3] != 0xBA )
- {
- Log( "PStoES: not a PS packet (%02x%02x%02x%02x)",
- psData[pos] << 24, psData[pos+1] << 16,
- psData[pos+2] << 8, psData[pos+3] );
- delete psBuffer;
- (*_esBufferList) = NULL;
- return false;
- }
- pos += 4; /* pack_start_code */
- pos += 9; /* pack_header */
- pos += 1 + ( psData[pos] & 0x7 ); /* stuffing bytes */
-
- /* system_header */
- if( psData[pos] == 0 && psData[pos+1] == 0 &&
- psData[pos+2] == 0x1 && psData[pos+3] == 0xBB )
- {
- uint32_t header_length;
-
- pos += 4; /* system_header_start_code */
- header_length = ( psData[pos] << 8 ) + psData[pos+1];
- pos += 2 + header_length;
- }
-
- HBList * esBufferList = new HBList();
- HBBuffer * esBuffer;
-
- /* PES */
- while( pos + 6 < psBuffer->fSize &&
- psData[pos] == 0 && psData[pos+1] == 0 && psData[pos+2] == 0x1 )
- {
- uint32_t streamId;
- uint32_t PES_packet_length;
- uint32_t PES_packet_end;
- uint32_t PES_header_data_length;
- uint32_t PES_header_end;
- bool hasPTS;
- uint64_t PTS = 0;
-
- pos += 3; /* packet_start_code_prefix */
- streamId = psData[pos];
- pos += 1;
-
- PES_packet_length = ( psData[pos] << 8 ) + psData[pos+1];
- pos += 2; /* PES_packet_length */
- PES_packet_end = pos + PES_packet_length;
-
- if( streamId != 0xE0 && streamId != 0xBD )
- {
- /* Not interesting */
- pos = PES_packet_end;
- continue;
- }
-
- hasPTS = ( ( psData[pos+1] >> 6 ) & 0x2 );
- pos += 2; /* Required headers */
-
- PES_header_data_length = psData[pos];
- pos += 1;
- PES_header_end = pos + PES_header_data_length;
-
- if( hasPTS )
- {
- PTS = ( ( ( (uint64_t) psData[pos] >> 1 ) & 0x7 ) << 30 ) +
- ( psData[pos+1] << 22 ) +
- ( ( psData[pos+2] >> 1 ) << 15 ) +
- ( psData[pos+3] << 7 ) +
- ( psData[pos+4] >> 1 );
- }
-
- pos = PES_header_end;
-
- if( streamId == 0xBD )
- {
- /* A52: don't ask */
- streamId |= ( psData[pos] << 8 );
- pos += 4;
- }
-
- /* Sanity check */
- if( pos >= PES_packet_end )
- {
- Log( "PStoES: pos >= PES_packet_end" );
- pos = PES_packet_end;
- continue;
- }
-
- /* Here we hit we ES payload */
- esBuffer = new HBBuffer( PES_packet_end - pos );
-
- esBuffer->fPosition = psBuffer->fPosition;
- esBuffer->fPass = psBuffer->fPass;
- esBuffer->fStreamId = streamId;
- esBuffer->fPTS = PTS;
- memcpy( esBuffer->fData, psBuffer->fData + pos,
- PES_packet_end - pos );
-
- esBufferList->AddItem( esBuffer );
-
- pos = PES_packet_end;
- }
-
- delete psBuffer;
-
- if( !esBufferList->CountItems() )
- {
- delete esBufferList;
- esBufferList = NULL;
- }
-
- (*_esBufferList) = esBufferList;
- return true;
-
-#undef psData
-}
diff --git a/core/MpegDemux.h b/core/MpegDemux.h
deleted file mode 100644
index 187a08de9..000000000
--- a/core/MpegDemux.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* $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/>.
- It may be used under the terms of the GNU General Public License. */
-
-#ifndef HB_MPEG_DEMUX_H
-#define HB_MPEG_DEMUX_H
-
-#include "Common.h"
-
-bool PStoES( HBBuffer * psBuffer, HBList ** _esBufferList );
-
-class HBMpegDemux
-{
- public:
- HBMpegDemux( HBManager * manager, HBTitle * title,
- HBAudio * audio1, HBAudio * audio2 );
- ~HBMpegDemux();
- bool Work();
-
- private:
- bool Lock();
- void Unlock();
-
- HBManager * fManager;
- HBTitle * fTitle;
- HBAudio * fAudio1;
- HBAudio * fAudio2;
-
- HBLock * fLock;
- bool fUsed;
-
- HBBuffer * fPSBuffer;
- HBBuffer * fESBuffer;
- HBList * fESBufferList;
-
- int64_t fFirstVideoPTS;
- int64_t fFirstAudio1PTS;
- int64_t fFirstAudio2PTS;
-};
-
-#endif
diff --git a/core/Resizer.cpp b/core/Resizer.cpp
deleted file mode 100644
index c49a39bf3..000000000
--- a/core/Resizer.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/* $Id: Resizer.cpp,v 1.9 2003/10/14 14:35:20 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 "Resizer.h"
-#include "Manager.h"
-#include "Fifo.h"
-
-#include <ffmpeg/avcodec.h>
-
-HBResizer::HBResizer( HBManager * manager, HBTitle * title )
-{
- fManager = manager;
- fTitle = title;
-
- /* Lock */
- fLock = new HBLock();
- fUsed = false;
-
- /* Init libavcodec */
- fResampleContext =
- img_resample_full_init( fTitle->fOutWidth, fTitle->fOutHeight,
- fTitle->fInWidth, fTitle->fInHeight,
- fTitle->fTopCrop, fTitle->fBottomCrop,
- fTitle->fLeftCrop, fTitle->fRightCrop );
-
- /* Buffers & pictures */
- 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;
- }
-
- /* Push the latest resized buffer */
- if( fResizedBuffer )
- {
- if( fTitle->fResizedFifo->Push( fResizedBuffer ) )
- {
- fResizedBuffer = NULL;
- }
- else
- {
- Unlock();
- return false;
- }
- }
-
- /* Get a new raw picture */
- if( ( fRawBuffer = fTitle->fRawFifo->Pop() ) )
- {
- /* Do the job */
- avpicture_fill( fRawPicture, fRawBuffer->fData,
- PIX_FMT_YUV420P, fTitle->fInWidth,
- fTitle->fInHeight );
-
- fResizedBuffer = new HBBuffer( 3 * fTitle->fOutWidth *
- fTitle->fOutHeight / 2 );
- 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( fDeinterlacedPicture, fRawPicture,
- PIX_FMT_YUV420P,
- fTitle->fInWidth,
- fTitle->fInHeight );
- img_resample( fResampleContext, fResizedPicture,
- fDeinterlacedPicture );
- }
- else
- {
- img_resample( fResampleContext, fResizedPicture,
- fRawPicture );
- }
- delete fRawBuffer;
- fRawBuffer = NULL;
- }
- else
- {
- Unlock();
- return false;
- }
-
- Unlock();
- return true;
-}
-
-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
deleted file mode 100644
index f6d4a4568..000000000
--- a/core/Resizer.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* $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/>.
- It may be used under the terms of the GNU General Public License. */
-
-#ifndef HB_RESIZER_H
-#define HB_RESIZER_H
-
-#include "Common.h"
-
-class HBResizer
-{
- public:
- HBResizer( HBManager * manager, HBTitle * title );
- ~HBResizer();
- bool Work();
-
- private:
- 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/Scale.c b/core/Scale.c
new file mode 100644
index 000000000..7e9295962
--- /dev/null
+++ b/core/Scale.c
@@ -0,0 +1,139 @@
+/* $Id: Scale.c,v 1.4 2003/11/06 13:03:19 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "Fifo.h"
+#include "Scale.h"
+#include "Work.h"
+
+#include <ffmpeg/avcodec.h>
+
+/* Local prototypes */
+static int ScaleWork( HBWork * );
+
+struct HBScale
+{
+ HB_WORK_COMMON_MEMBERS
+
+ HBHandle * handle;
+ HBTitle * title;
+
+ ImgReSampleContext * context;
+ AVPicture rawPicture;
+ HBBuffer * deintBuffer;
+ AVPicture deintPicture;
+ HBBuffer * scaledBuffer;
+ AVPicture scaledPicture;
+};
+
+HBScale * HBScaleInit( HBHandle * handle, HBTitle * title )
+{
+ HBScale * s;
+ if( !( s = malloc( sizeof( HBScale ) ) ) )
+ {
+ HBLog( "HBScaleInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ s->name = strdup( "Scale" );
+ s->work = ScaleWork;
+
+ s->handle = handle;
+ s->title = title;
+
+ /* Init libavcodec */
+ s->context =
+ img_resample_full_init( title->outWidth, title->outHeight,
+ title->inWidth, title->inHeight,
+ title->topCrop, title->bottomCrop,
+ title->leftCrop, title->rightCrop );
+
+ /* Allocate a constant buffer used for deinterlacing */
+ s->deintBuffer = HBBufferInit( 3 * title->inWidth *
+ title->inHeight / 2 );
+ avpicture_fill( &s->deintPicture, s->deintBuffer->data,
+ PIX_FMT_YUV420P, title->inWidth, title->inHeight );
+
+ s->scaledBuffer = NULL;
+
+ return s;
+}
+
+void HBScaleClose( HBScale ** _s )
+{
+ HBScale * s = *_s;
+
+ img_resample_close( s->context );
+ HBBufferClose( &s->deintBuffer );
+ free( s->name );
+ free( s );
+
+ *_s = NULL;
+}
+
+static int ScaleWork( HBWork * w )
+{
+ HBScale * s = (HBScale*) w;
+ HBTitle * title = s->title;
+ HBBuffer * rawBuffer;
+
+ int didSomething = 0;
+
+ /* Push scaled buffer */
+ if( s->scaledBuffer )
+ {
+ if( HBFifoPush( title->scaledFifo, &s->scaledBuffer ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+ }
+
+ /* Get a new raw picture */
+ if( ( rawBuffer = HBFifoPop( title->rawFifo ) ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+
+ /* Allocate new buffer for the scaled picture */
+ s->scaledBuffer = HBBufferInit( 3 * title->outWidth *
+ title->outHeight / 2 );
+ s->scaledBuffer->position = rawBuffer->position;
+ s->scaledBuffer->pass = rawBuffer->pass;
+
+ /* libavcodec stuff */
+ avpicture_fill( &s->rawPicture, rawBuffer->data, PIX_FMT_YUV420P,
+ title->inWidth, title->inHeight );
+ avpicture_fill( &s->scaledPicture, s->scaledBuffer->data,
+ PIX_FMT_YUV420P, title->outWidth,
+ title->outHeight );
+
+ /* Do the job */
+ if( title->deinterlace )
+ {
+ avpicture_deinterlace( &s->deintPicture, &s->rawPicture,
+ PIX_FMT_YUV420P, title->inWidth,
+ title->inHeight );
+ img_resample( s->context, &s->scaledPicture,
+ &s->deintPicture );
+ }
+ else
+ {
+ img_resample( s->context, &s->scaledPicture, &s->rawPicture );
+ }
+
+ /* Free memory */
+ HBBufferClose( &rawBuffer );
+
+ return didSomething;
+}
+
diff --git a/core/Scale.h b/core/Scale.h
new file mode 100644
index 000000000..cf06ad661
--- /dev/null
+++ b/core/Scale.h
@@ -0,0 +1,15 @@
+/* $Id: Scale.h,v 1.1 2003/11/03 12:08:01 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_SCALE_H
+#define HB_SCALE_H
+
+#include "HandBrakeInternal.h"
+
+HBScale * HBScaleInit( HBHandle *, HBTitle * );
+void HBScaleClose( HBScale ** );
+
+#endif
diff --git a/core/Scan.c b/core/Scan.c
new file mode 100644
index 000000000..83f2fc098
--- /dev/null
+++ b/core/Scan.c
@@ -0,0 +1,395 @@
+/* $Id: Scan.c,v 1.4 2003/11/06 13:03:19 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "Fifo.h"
+#include "Languages.h"
+#include "Scan.h"
+#include "Thread.h"
+
+#include <dvdread/ifo_types.h>
+#include <dvdplay/dvdplay.h>
+#include <dvdplay/info.h>
+#include <dvdplay/state.h>
+#include <dvdplay/nav.h>
+
+#include <mpeg2dec/mpeg2.h>
+
+/* Local prototypes */
+static void ScanThread( void * );
+static HBTitle * ScanTitle( HBScan *, dvdplay_ptr vmg, int index );
+static int DecodeFrame( HBScan * s, dvdplay_ptr vmg,
+ HBTitle * title, int which );
+static char * LanguageForCode( int code );
+
+struct HBScan
+{
+ HBHandle * handle;
+ char * device;
+ int title;
+ int die;
+ HBThread * thread;
+};
+
+HBScan * HBScanInit( HBHandle * handle, char * device, int title )
+{
+ HBScan * s;
+ if( !( s = malloc( sizeof( HBScan ) ) ) )
+ {
+ HBLog( "HBScanInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ s->handle = handle;
+ s->device = strdup( device );
+ s->title = title;
+ s->die = 0;
+ s->thread = HBThreadInit( "scan", ScanThread, s,
+ HB_NORMAL_PRIORITY );
+
+ return s;
+}
+
+void HBScanClose( HBScan ** _s )
+{
+ HBScan * s = *_s;
+
+ s->die = 1;
+ HBThreadClose( &s->thread );
+
+ free( s->device );
+ free( s );
+ *_s = NULL;
+}
+
+static void ScanThread( void * _s )
+{
+ HBScan * s = (HBScan*) _s;
+ dvdplay_ptr vmg;
+ HBList * titleList = HBListInit();
+ HBTitle * title;
+ int i;
+
+ HBLog( "HBScan: opening device %s", s->device );
+ HBScanning( s->handle, 0 );
+
+ vmg = dvdplay_open( s->device, NULL, NULL );
+ if( !vmg )
+ {
+ HBLog( "HBScan: dvdplay_open() failed (%s)", s->device );
+ HBScanDone( s->handle, titleList );
+ return;
+ }
+
+ /* Detect titles */
+ for( i = ( s->title ? s->title - 1 : 0 );
+ i < ( s->title ? s->title : dvdplay_title_nr( vmg ) );
+ i++ )
+ {
+ if( s->die )
+ {
+ break;
+ }
+
+ if( !( title = ScanTitle( s, vmg, i + 1 ) ) )
+ {
+ continue;
+ }
+
+ HBListAdd( titleList, title );
+ }
+
+ HBLog( "HBScan: closing device %s", s->device );
+ dvdplay_close( vmg );
+
+ HBScanDone( s->handle, titleList );
+}
+
+static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index )
+{
+ HBTitle * title;
+ int audio_nr, foo;
+ audio_attr_t * attr;
+ HBAudio * audio;
+ int i;
+ uint8_t dummy[DVD_VIDEO_LB_LEN];
+
+ HBLog( "HBScan: scanning title %d", index );
+ HBScanning( s->handle, index );
+
+ title = HBTitleInit( s->device, index );
+ dvdplay_start( vmg, index );
+
+ /* Length */
+ title->length = dvdplay_title_time( vmg );
+ HBLog( "HBScan: title length is %d seconds", title->length );
+
+ /* Discard titles under 10 seconds */
+ if( title->length < 10 )
+ {
+ HBLog( "HBScan: ignoring title %d (too short)", index );
+ HBTitleClose( &title );
+ return NULL;
+ }
+
+ /* Detect languages */
+ dvdplay_audio_info( vmg, &audio_nr, &foo );
+
+ for( i = 0; i < audio_nr; i++ )
+ {
+ int id;
+ int j;
+
+ if( s->die )
+ {
+ break;
+ }
+
+ id = dvdplay_audio_id( vmg, i );
+
+ if( id < 1 )
+ {
+ continue;
+ }
+
+ if( ( id & 0xFF ) != 0xBD )
+ {
+ HBLog( "HBScan: non-AC3 audio track detected, ignoring" );
+ continue;
+ }
+
+ /* Check if we don't already found an track with the same id */
+ audio = NULL;
+ for( j = 0; j < HBListCountItems( title->audioList ); j++ )
+ {
+ audio = (HBAudio*) HBListItemAt( title->audioList, j );
+ if( id == audio->id )
+ {
+ break;
+ }
+ else
+ {
+ audio = NULL;
+ }
+ }
+
+ if( audio )
+ {
+ HBLog( "HBScan: discarding duplicate track %x", id );
+ continue;
+ }
+
+ attr = dvdplay_audio_attr( vmg, j );
+ audio = HBAudioInit( id, LanguageForCode( attr->lang_code ) );
+ HBLog( "HBScan: new language (%x, %s)", id, audio->language );
+ HBListAdd( title->audioList, audio );
+ }
+
+ /* Discard titles with no audio tracks */
+ if( !HBListCountItems( title->audioList ) )
+ {
+ HBLog( "HBScan: ignoring title %d (no audio track)", index );
+ HBTitleClose( &title );
+ return NULL;
+ }
+
+ /* Kludge : libdvdplay wants we to read a first block before seeking */
+ dvdplay_read( vmg, dummy, 1 );
+
+
+ for( i = 0; i < 10; i++ )
+ {
+ if( s->die )
+ {
+ break;
+ }
+
+ if( !DecodeFrame( s, vmg, title, i ) )
+ {
+ HBLog( "HBScan: ignoring title %d (could not decode)",
+ index );
+ HBTitleClose( &title );
+ return NULL;
+ }
+ }
+
+ if( title->inHeight * title->aspect >
+ title->inWidth * VOUT_ASPECT_FACTOR )
+ {
+ title->outWidthMax = title->inWidth;
+ title->outHeightMax = MULTIPLE_16( (uint64_t)title->inWidth *
+ VOUT_ASPECT_FACTOR / title->aspect );
+ }
+ else
+ {
+ title->outWidthMax = MULTIPLE_16( (uint64_t)title->inHeight *
+ title->aspect / VOUT_ASPECT_FACTOR );
+ title->outHeightMax = title->inHeight;
+ }
+
+ /* Default picture size */
+ title->outWidth = title->outWidthMax;
+ title->outHeight = title->outHeightMax;
+
+ return title;
+}
+
+static int DecodeFrame( HBScan * s, dvdplay_ptr vmg,
+ HBTitle * title, int which )
+{
+ int titleFirst = dvdplay_title_first( vmg );
+ int titleEnd = dvdplay_title_end( vmg );
+ int pictureStart = ( which + 1 ) * ( titleEnd - titleFirst ) / 11;
+ int pictureEnd = titleFirst + ( which + 2 ) *
+ ( titleEnd - titleFirst ) / 11;
+
+ mpeg2dec_t * handle;
+ const mpeg2_info_t * info;
+ mpeg2_state_t state;
+ char fileName[1024];
+ FILE * file;
+
+ HBList * esBufferList = HBListInit();
+ HBBuffer * psBuffer = NULL;
+ HBBuffer * esBuffer = NULL;
+
+ /* Seek to the right place */
+ dvdplay_seek( vmg, pictureStart );
+
+ /* Init libmpeg2 */
+ handle = mpeg2_init();
+ info = mpeg2_info( handle );
+
+ /* Init the destination file */
+ memset( fileName, 0, 1024 );
+ sprintf( fileName, "/tmp/HB.%d.%d.%d", HBGetPid( s->handle ),
+ title->index, which );
+ file = fopen( fileName, "w" );
+
+#define CLEANUP \
+ while( ( esBuffer = (HBBuffer*) HBListItemAt( esBufferList, 0 ) ) ) \
+ { \
+ HBListRemove( esBufferList, esBuffer ); \
+ HBBufferClose( &esBuffer ); \
+ } \
+ HBListClose( &esBufferList ); \
+ if( psBuffer ) HBBufferClose( &psBuffer ); \
+ if( esBuffer ) HBBufferClose( &esBuffer ); \
+ mpeg2_close( handle ); \
+ fclose( file )
+
+ for( ;; )
+ {
+ state = mpeg2_parse( handle );
+
+ if( state == STATE_BUFFER )
+ {
+ /* Free the previous buffer */
+ if( esBuffer )
+ {
+ HBBufferClose( &esBuffer );
+ }
+
+ /* Get a new one */
+ while( !esBuffer )
+ {
+ while( !HBListCountItems( esBufferList ) )
+ {
+ psBuffer = HBBufferInit( DVD_VIDEO_LB_LEN );
+ if( dvdplay_read( vmg, psBuffer->data, 1 ) != 1 ||
+ !HBPStoES( &psBuffer, esBufferList ) )
+ {
+ HBLog( "HBScan: failed to get a valid PS "
+ "packet" );
+ CLEANUP;
+ return 0;
+ }
+
+ if( dvdplay_position( vmg ) >= pictureEnd )
+ {
+ HBLog( "HBScan: gone too far, aborting" );
+ CLEANUP;
+ return 0;
+ }
+ }
+
+ esBuffer = (HBBuffer*) HBListItemAt( esBufferList, 0 );
+ HBListRemove( esBufferList, esBuffer );
+
+ if( esBuffer->streamId != 0xE0 )
+ {
+ HBBufferClose( &esBuffer );
+ }
+ }
+
+ /* Feed libmpeg2 */
+ mpeg2_buffer( handle, esBuffer->data,
+ esBuffer->data + esBuffer->size );
+ }
+ else if( state == STATE_SEQUENCE )
+ {
+ /* Get size & framerate info */
+ title->inWidth = info->sequence->width;
+ title->inHeight = info->sequence->height;
+ title->aspect = (uint64_t)info->sequence->display_width *
+ info->sequence->pixel_width * VOUT_ASPECT_FACTOR /
+ ( info->sequence->display_height *
+ info->sequence->pixel_height );
+ title->rate = 27000000;
+ title->rateBase = info->sequence->frame_period;
+ }
+ else if( ( state == STATE_SLICE || state == STATE_END ) &&
+ ( info->display_fbuf ) &&
+ ( info->display_picture->flags & PIC_MASK_CODING_TYPE )
+ == PIC_FLAG_CODING_TYPE_I )
+ {
+ /* Write the raw picture to a file */
+ fwrite( info->display_fbuf->buf[0],
+ title->inWidth * title->inHeight, 1, file );
+ fwrite( info->display_fbuf->buf[1],
+ title->inWidth * title->inHeight / 4, 1, file );
+ fwrite( info->display_fbuf->buf[2],
+ title->inWidth * title->inHeight / 4, 1, file );
+ break;
+ }
+ else if( state == STATE_INVALID )
+ {
+ /* Reset libmpeg2 */
+ mpeg2_close( handle );
+ handle = mpeg2_init();
+ }
+ }
+
+ CLEANUP;
+
+ return 1;
+
+#undef CLEANUP
+}
+
+static char * LanguageForCode( int code )
+{
+ char codeString[2];
+ iso639_lang_t * lang;
+
+ codeString[0] = ( code >> 8 ) & 0xFF;
+ codeString[1] = code & 0xFF;
+
+ for( lang = languages; lang->engName; lang++ )
+ {
+ if( !strncmp( lang->iso639_1, codeString, 2 ) )
+ {
+ if( *lang->nativeName )
+ {
+ return lang->nativeName;
+ }
+
+ return lang->engName;
+ }
+ }
+
+ return "Unknown";
+}
+
diff --git a/core/Scan.h b/core/Scan.h
new file mode 100644
index 000000000..5cc8542e7
--- /dev/null
+++ b/core/Scan.h
@@ -0,0 +1,15 @@
+/* $Id: Scan.h,v 1.2 2003/11/06 13:03:19 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_SCAN_H
+#define HB_SCAN_H
+
+#include "HandBrakeInternal.h"
+
+HBScan * HBScanInit( HBHandle *, char * device, int title );
+void HBScanClose( HBScan ** );
+
+#endif
diff --git a/core/Scanner.cpp b/core/Scanner.cpp
deleted file mode 100644
index 44ff6be3a..000000000
--- a/core/Scanner.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-/* $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/>.
- It may be used under the terms of the GNU General Public License. */
-
-#include "Scanner.h"
-#include "Manager.h"
-#include "Fifo.h"
-#include "MpegDemux.h"
-
-#include <dvdread/ifo_types.h>
-#include <dvdplay/dvdplay.h>
-#include <dvdplay/info.h>
-#include <dvdplay/state.h>
-#include <dvdplay/nav.h>
-
-extern "C" {
-#include <mpeg2dec/mpeg2.h>
-}
-
-HBScanner::HBScanner( HBManager * manager, char * device )
- : HBThread( "scanner", HB_NORMAL_PRIORITY )
-{
- fManager = manager;
- fDevice = strdup( device );
-
- Run();
-}
-
-void HBScanner::DoWork()
-{
- Log( "HBScanner: opening device %s", fDevice );
-
- dvdplay_ptr vmg;
- vmg = dvdplay_open( fDevice, NULL, NULL );
- if( !vmg )
- {
- Log( "HBScanner: dvdplay_open() failed (%s)",
- fDevice );
- fManager->ScanDone( NULL );
- return;
- }
-
- /* Detect titles */
- HBList * titleList = new HBList();
- HBTitle * title;
- for( int i = 0; i < dvdplay_title_nr( vmg ); i++ )
- {
- if( fDie )
- {
- break;
- }
-
- Log( "HBScanner: scanning title %d", i + 1 );
- fManager->Scanning( fDevice, i + 1 );
-
- title = new HBTitle( fDevice, i + 1 );
-
- if( ScanTitle( title, vmg ) )
- {
- titleList->AddItem( title );
- }
- else
- {
- Log( "HBScanner: ignoring title %d", i + 1 );
- delete title;
- }
- }
-
- Log( "HBScanner: closing device %s", fDevice );
- dvdplay_close( vmg );
-
- fManager->ScanDone( titleList );
-}
-
-bool HBScanner::ScanTitle( HBTitle * title, dvdplay_ptr vmg )
-{
- dvdplay_start( vmg, title->fIndex );
-
- /* Length */
- title->fLength = dvdplay_title_time( vmg );
- Log( "HBScanner::ScanTitle: title length is %lld seconds",
- title->fLength );
-
- /* Discard titles under 10 seconds */
- if( title->fLength < 10 )
- {
- return false;
- }
-
- /* Detect languages */
- int audio_nr, foo;
- dvdplay_audio_info( vmg, &audio_nr, &foo );
-
- audio_attr_t * attr;
- HBAudio * audio;
- for( int i = 0; i < audio_nr; i++ )
- {
- if( fDie )
- {
- break;
- }
-
- int id = dvdplay_audio_id( vmg, i );
-
- if( id < 1 )
- {
- 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
- {
- audio = NULL;
- }
- }
-
- 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 */
- if( !title->fAudioList->CountItems() )
- {
- return false;
- }
-
- /* Kludge : libdvdplay wants we to read a first block before seeking */
- uint8_t dummyBuf[DVD_VIDEO_LB_LEN];
- dvdplay_read( vmg, dummyBuf, 1 );
-
- for( int i = 0; i < 10; i++ )
- {
- if( fDie )
- {
- break;
- }
-
- if( !DecodeFrame( title, vmg, i ) )
- {
- return false;
- }
- }
-
- if( title->fInHeight * title->fAspect >
- title->fInWidth * VOUT_ASPECT_FACTOR )
- {
- title->fOutWidthMax = title->fInWidth;
- title->fOutHeightMax = MULTIPLE_16( (uint64_t)title->fInWidth *
- VOUT_ASPECT_FACTOR / title->fAspect );
- }
- else
- {
- title->fOutWidthMax = MULTIPLE_16( (uint64_t)title->fInHeight *
- title->fAspect / VOUT_ASPECT_FACTOR );
- title->fOutHeightMax = title->fInHeight;
- }
-
- /* Default picture size */
- title->fOutWidth = title->fOutWidthMax;
- title->fOutHeight = title->fOutHeightMax;
-
- return true;
-}
-bool HBScanner::DecodeFrame( HBTitle * title, dvdplay_ptr vmg, int i )
-{
- /* Seek to the right place */
- int titleFirst = dvdplay_title_first ( vmg );
- int titleEnd = dvdplay_title_end( vmg );
-
- dvdplay_seek( vmg, ( i + 1 ) * ( titleEnd - titleFirst ) / 11 ) ;
-
- /* Init libmpeg2 */
- mpeg2dec_t * handle = mpeg2_init();
- const mpeg2_info_t * info = mpeg2_info( handle );
- mpeg2_state_t state;
-
- /* Init the destination file */
- char fileName[1024];
- memset( fileName, 0, 1024 );
- sprintf( fileName, "/tmp/HB.%d.%x.%d", fManager->GetPid(),
- (uint32_t) title, i );
- FILE * file = fopen( fileName, "w" );
-
- HBList * esBufferList = NULL;
- HBBuffer * psBuffer = NULL;
- HBBuffer * esBuffer = NULL;
-
- for( ;; )
- {
- state = mpeg2_parse( handle );
-
- if( state == STATE_BUFFER )
- {
- /* Free the previous buffer */
- if( esBuffer )
- {
- delete esBuffer;
- esBuffer = NULL;
- }
-
- /* Get a new one */
- while( !esBuffer )
- {
- while( !esBufferList )
- {
- psBuffer = new HBBuffer( DVD_VIDEO_LB_LEN );
- if( dvdplay_read( vmg, psBuffer->fData, 1 ) != 1 ||
- !PStoES( psBuffer, &esBufferList ) )
- {
- Log( "HBScanner::DecodeFrame: failed to get "
- "a valid PS packet" );
- mpeg2_close( handle );
- fclose( file );
- return false;
- }
- }
-
- esBuffer = (HBBuffer*) esBufferList->ItemAt( 0 );
- esBufferList->RemoveItem( esBuffer );
- if( !esBufferList->CountItems() )
- {
- delete esBufferList;
- esBufferList = NULL;
- }
-
- if( esBuffer->fStreamId != 0xE0 )
- {
- delete esBuffer;
- esBuffer = NULL;
- }
- }
-
- /* Feed libmpeg2 */
- mpeg2_buffer( handle, esBuffer->fData,
- esBuffer->fData + esBuffer->fSize );
- }
- else if( state == STATE_SEQUENCE )
- {
- /* Get size & framerate info */
- title->fInWidth = info->sequence->width;
- title->fInHeight = info->sequence->height;
- title->fAspect = (uint64_t)info->sequence->display_width *
- info->sequence->pixel_width * VOUT_ASPECT_FACTOR /
- ( info->sequence->display_height *
- info->sequence->pixel_height );
- title->fRate = 27000000;
- title->fScale = info->sequence->frame_period;
- }
- else if( ( state == STATE_SLICE || state == STATE_END ) &&
- ( info->display_fbuf ) &&
- ( info->display_picture->flags & PIC_MASK_CODING_TYPE )
- == PIC_FLAG_CODING_TYPE_I )
- {
- /* Write the raw picture to a file */
- fwrite( info->display_fbuf->buf[0],
- title->fInWidth * title->fInHeight, 1, file );
- fwrite( info->display_fbuf->buf[1],
- title->fInWidth * title->fInHeight / 4, 1, file );
- fwrite( info->display_fbuf->buf[2],
- title->fInWidth * title->fInHeight / 4, 1, file );
- break;
- }
- else if( state == STATE_INVALID )
- {
- /* Reset libmpeg2 */
- mpeg2_close( handle );
- handle = mpeg2_init();
- }
- }
-
- mpeg2_close( handle );
-
- fclose( file );
-
- return true;
-}
diff --git a/core/Scanner.h b/core/Scanner.h
deleted file mode 100644
index dbdb587c4..000000000
--- a/core/Scanner.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* $Id: Scanner.h,v 1.5 2003/09/30 21:21:32 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_SCANNER_H
-#define HB_SCANNER_H
-
-#include "Common.h"
-#include "Thread.h"
-
-class HBScanner : public HBThread
-{
- public:
- HBScanner( HBManager * manager, char * device );
-
- private:
- void DoWork();
- bool ScanTitle( HBTitle * title, dvdplay_ptr vmg );
- bool DecodeFrame( HBTitle * title, dvdplay_ptr vmg, int i );
-
- HBManager * fManager;
- char * fDevice;
-};
-
-#endif
diff --git a/core/Thread.c b/core/Thread.c
new file mode 100644
index 000000000..77caa0ee5
--- /dev/null
+++ b/core/Thread.c
@@ -0,0 +1,138 @@
+/* $Id: Thread.c,v 1.4 2003/11/06 15:51:36 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "Thread.h"
+
+struct HBThread
+{
+ char * name;
+ int priority;
+ void (*function) ( void * );
+ void * arg;
+
+#if defined( SYS_BEOS )
+ int thread;
+#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+ pthread_t thread;
+#elif defined( SYS_CYGWIN )
+ /* TODO */
+ int thread;
+#endif
+};
+
+#ifndef SYS_CYGWIN
+static void ThreadFunc( void * t );
+#endif
+
+HBThread * HBThreadInit( char * name, void (* function)(void *),
+ void * arg, int priority )
+{
+ HBThread * t;
+ if( !( t = malloc( sizeof( HBThread ) ) ) )
+ {
+ HBLog( "HBThreadInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ t->name = strdup( name );
+ t->priority = priority;
+ t->function = function;
+ t->arg = arg;
+
+#if defined( SYS_BEOS )
+ t->thread = spawn_thread( (int32 (*)( void * )) ThreadFunc,
+ name, priority, t );
+ resume_thread( t->thread );
+#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+ pthread_create( &t->thread, NULL,
+ (void * (*)( void * )) ThreadFunc, t );
+#elif defined( SYS_CYGWIN )
+ /* TODO */
+ t->thread = 0;
+#endif
+
+ HBLog( "HBThreadInit: thread %d started (\"%s\")",
+ t->thread, t->name );
+
+ return t;
+}
+
+#ifndef SYS_CYGWIN
+static void ThreadFunc( void * _t )
+{
+ HBThread * t = (HBThread*) _t;
+
+#if defined( SYS_MACOSX )
+ struct sched_param param;
+ memset( &param, 0, sizeof( struct sched_param ) );
+ param.sched_priority = t->priority;
+ if( pthread_setschedparam( pthread_self(), SCHED_OTHER, &param ) )
+ {
+ HBLog( "HBThreadInit: couldn't set thread priority" );
+ }
+#endif
+
+ t->function( t->arg );
+}
+#endif
+
+void HBThreadClose( HBThread ** _t )
+{
+ HBThread * t = *_t;
+
+#if defined( SYS_BEOS )
+ long exitValue;
+ wait_for_thread( t->thread, &exitValue );
+#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+ pthread_join( t->thread, NULL );
+#elif defined( SYS_CYGWIN )
+ /* TODO */
+#endif
+
+ HBLog( "HBThreadClose: thread %d stopped (\"%s\")",
+ t->thread, t->name );
+
+ free( t->name );
+ free( t );
+ *_t = NULL;
+}
+
+HBLock * HBLockInit()
+{
+ HBLock * l;
+ if( !( l = malloc( sizeof( HBLock ) ) ) )
+ {
+ HBLog( "HBLockInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+#if defined( SYS_BEOS )
+ l->sem = create_sem( 1, "sem" );
+#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+ pthread_mutex_init( &l->mutex, NULL );
+#elif defined( SYS_CYGWIN )
+ /* TODO */
+#endif
+
+ return l;
+}
+
+void HBLockClose( HBLock ** _l )
+{
+ HBLock * l = *_l;
+
+#if defined( SYS_BEOS )
+ delete_sem( l->sem );
+#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+ pthread_mutex_destroy( &l->mutex );
+#elif defined( SYS_CYGWIN )
+ /* TODO */
+#endif
+ free( l );
+
+ *_l = NULL;
+}
+
diff --git a/core/Thread.cpp b/core/Thread.cpp
deleted file mode 100644
index c52f7506a..000000000
--- a/core/Thread.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/* $Id: Thread.cpp,v 1.24 2003/10/14 14:35:20 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. */
-
-#if defined( SYS_BEOS )
-# include <OS.h>
-# include <Locker.h>
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
-# include <pthread.h>
-#endif
-
-#include "Thread.h"
-#include "Fifo.h"
-
-HBThread::HBThread( char * name, int priority )
-{
- fName = strdup( name );
- fPriority = priority;
- fDie = false;
- fSuspend = false;
-}
-
-HBThread::~HBThread()
-{
- fDie = true;
- fSuspend = false;
-
-#if defined( SYS_BEOS )
- long exit_value;
- wait_for_thread( fThread, &exit_value );
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
- pthread_join( fThread, NULL );
-#endif
-
- Log( "HBThread: thread %d stopped (\"%s\")", fThread, fName );
- free( fName );
-}
-
-void HBThread::Suspend()
-{
- fSuspend = true;
-}
-
-void HBThread::Resume()
-{
- fSuspend = false;
-}
-
-int HBThread::GetPid()
-{
- return fPid;
-}
-
-void HBThread::Run()
-{
-#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
-
- Log( "HBThread: thread %d started (\"%s\")",
- fThread, fName );
-}
-
-bool HBThread::Push( HBFifo * fifo, HBBuffer * buffer )
-{
- while( !fDie )
- {
- if( fifo->Push( buffer ) )
- {
- return true;
- }
-
- Snooze( 10000 );
- }
-
- delete buffer;
- return false;
-}
-
-HBBuffer * HBThread::Pop( HBFifo * fifo )
-{
- HBBuffer * buffer;
-
- while( !fDie )
- {
- if( ( buffer = fifo->Pop() ) )
- {
- return buffer;
- }
-
- Snooze( 10000 );
- }
-
- return NULL;
-}
-
-void HBThread::ThreadFunc( HBThread * _this )
-{
-#if defined( SYS_MACOSX )
- struct sched_param param;
- memset( &param, 0, sizeof( struct sched_param ) );
- param.sched_priority = _this->fPriority;
- if ( pthread_setschedparam( pthread_self(), SCHED_OTHER, &param ) )
- {
- Log( "HBThread: couldn't set thread priority" );
- }
-#endif
-
- _this->fPid = (int) getpid();
-
- _this->DoWork();
-}
-
-void HBThread::DoWork()
-{
-}
-
-
-HBLock::HBLock()
-{
-#if defined( SYS_BEOS )
- fLocker = new BLocker();
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
- pthread_mutex_init( &fMutex, NULL );
-#endif
-}
-
-HBLock::~HBLock()
-{
-#if defined( SYS_BEOS )
- delete fLocker;
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
- pthread_mutex_destroy( &fMutex );
-#endif
-}
-
-void HBLock::Lock()
-{
-#if defined( SYS_BEOS )
- fLocker->Lock();
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
- pthread_mutex_lock( &fMutex );
-#endif
-}
-
-void HBLock::Unlock()
-{
-#if defined( SYS_BEOS )
- fLocker->Unlock();
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
- pthread_mutex_unlock( &fMutex );
-#endif
-}
diff --git a/core/Thread.h b/core/Thread.h
index 0a09fabc9..58700aae1 100644
--- a/core/Thread.h
+++ b/core/Thread.h
@@ -1,13 +1,19 @@
-/* $Id: Thread.h,v 1.19 2003/10/09 16:03:51 titer Exp $
+/* $Id: Thread.h,v 1.3 2003/11/06 15:51:36 titer Exp $
This file is part of the HandBrake source code.
- Homepage: <http://beos.titer.org/handbrake/>.
+ Homepage: <http://handbrake.m0k.org/>.
It may be used under the terms of the GNU General Public License. */
#ifndef HB_THREAD_H
#define HB_THREAD_H
-#include "Common.h"
+#if defined( SYS_BEOS )
+# include <OS.h>
+#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+# include <pthread.h>
+#endif
+
+#include "Utils.h"
#if defined( SYS_BEOS )
# define HB_LOW_PRIORITY 5
@@ -15,63 +21,52 @@
#elif defined( SYS_MACOSX )
# define HB_LOW_PRIORITY 0
# define HB_NORMAL_PRIORITY 31
-#elif defined( SYS_LINUX )
+#elif defined( SYS_LINUX ) || defined( SYS_CYGWIN )
/* Actually unused */
# define HB_LOW_PRIORITY 0
# define HB_NORMAL_PRIORITY 0
#endif
-class HBThread
-{
- public:
- HBThread( char * name,
- int priority = HB_LOW_PRIORITY );
- virtual ~HBThread();
- void Suspend();
- void Resume();
- int GetPid();
-
- protected:
- void Run();
- bool Push( HBFifo * fifo, HBBuffer * buffer );
- HBBuffer * Pop( HBFifo * fifo );
-
- volatile bool fDie;
- volatile bool fSuspend;
-
- private:
- static void ThreadFunc( HBThread * _this );
- virtual void DoWork();
-
- char * fName;
- int fPriority;
+HBThread * HBThreadInit( char * name, void (* function)(void *),
+ void * arg, int priority );
+void HBThreadClose( HBThread ** );
+struct HBLock
+{
#if defined( SYS_BEOS )
- int fThread;
+ sem_id sem;
#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
- pthread_t fThread;
+ pthread_mutex_t mutex;
+#elif defined( SYS_CYGWIN )
+ /* TODO */
#endif
- int fPid;
};
+HBLock * HBLockInit();
+static inline void HBLockLock( HBLock * );
+static inline void HBLockUnlock( HBLock * );
+void HBLockClose( HBLock ** );
+
+static inline void HBLockLock( HBLock * l )
+{
#if defined( SYS_BEOS )
-class BLocker;
+ acquire_sem( l->sem );
+#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+ pthread_mutex_lock( &l->mutex );
+#elif defined( SYS_CYGWIN )
+ /* TODO */
#endif
+}
-class HBLock
+static inline void HBLockUnlock( HBLock * l )
{
- public:
- HBLock();
- ~HBLock();
- void Lock();
- void Unlock();
-
- private:
#if defined( SYS_BEOS )
- BLocker * fLocker;
+ release_sem( l->sem );
#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
- pthread_mutex_t fMutex;
+ pthread_mutex_unlock( &l->mutex );
+#elif defined( SYS_CYGWIN )
+ /* TODO */
#endif
-};
+}
#endif
diff --git a/core/Utils.c b/core/Utils.c
new file mode 100644
index 000000000..5f35ec3ae
--- /dev/null
+++ b/core/Utils.c
@@ -0,0 +1,352 @@
+/* $Id: Utils.c,v 1.6 2003/11/06 15:51:36 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include <stdarg.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "Utils.h"
+#include "Fifo.h"
+
+struct HBList
+{
+ void ** items;
+ int allocItems;
+ int nbItems;
+};
+
+void HBSnooze( int time )
+{
+#if defined( SYS_BEOS )
+ snooze( time );
+#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+ usleep( time );
+#elif defined( SYS_CYGWIN )
+ /* TODO */
+#endif
+}
+
+void HBLog( char * log, ... )
+{
+ char string[81];
+ time_t _now;
+ struct tm * now;
+ va_list args;
+ int ret;
+
+ if( !getenv( "HB_DEBUG" ) )
+ {
+ return;
+ }
+
+ /* Show the time */
+ _now = time( NULL );
+ now = localtime( &_now );
+ sprintf( string, "[%02d:%02d:%02d] ",
+ now->tm_hour, now->tm_min, now->tm_sec );
+
+ /* Convert the message to a string */
+ va_start( args, log );
+ ret = vsnprintf( string + 11, 68, log, args );
+ va_end( args );
+
+ /* Add the end of line */
+ string[ret+11] = '\n';
+ string[ret+12] = '\0';
+
+ /* Print it */
+ fprintf( stderr, "%s", string );
+}
+
+uint64_t HBGetDate()
+{
+#ifndef SYS_CYGWIN
+ struct timeval tv;
+ gettimeofday( &tv, NULL );
+ return( (uint64_t) tv.tv_sec * 1000000 + (uint64_t) tv.tv_usec );
+#else
+ return 0;
+#endif
+}
+
+/* Basic MPEG demuxer - only works with DVDs ! (2048 bytes packets) */
+int HBPStoES( HBBuffer ** _psBuffer, HBList * esBufferList )
+{
+ HBBuffer * psBuffer = *_psBuffer;
+ HBBuffer * esBuffer;
+ int pos = 0;
+
+#define d (psBuffer->data)
+
+ /* pack_header */
+ if( d[pos] != 0 || d[pos+1] != 0 ||
+ d[pos+2] != 0x1 || d[pos+3] != 0xBA )
+ {
+ HBLog( "HBPStoES: not a PS packet (%02x%02x%02x%02x)",
+ d[pos] << 24, d[pos+1] << 16,
+ d[pos+2] << 8, d[pos+3] );
+ HBBufferClose( _psBuffer );
+ return 0;
+ }
+ pos += 4; /* pack_start_code */
+ pos += 9; /* pack_header */
+ pos += 1 + ( d[pos] & 0x7 ); /* stuffing bytes */
+
+ /* system_header */
+ if( d[pos] == 0 && d[pos+1] == 0 &&
+ d[pos+2] == 0x1 && d[pos+3] == 0xBB )
+ {
+ int header_length;
+
+ pos += 4; /* system_header_start_code */
+ header_length = ( d[pos] << 8 ) + d[pos+1];
+ pos += 2 + header_length;
+ }
+
+ /* PES */
+ while( pos + 6 < psBuffer->size &&
+ d[pos] == 0 && d[pos+1] == 0 && d[pos+2] == 0x1 )
+ {
+ uint32_t streamId;
+ uint32_t PES_packet_length;
+ uint32_t PES_packet_end;
+ uint32_t PES_header_d_length;
+ uint32_t PES_header_end;
+ int hasPTS;
+ uint64_t PTS = 0;
+
+ pos += 3; /* packet_start_code_prefix */
+ streamId = d[pos];
+ pos += 1;
+
+ PES_packet_length = ( d[pos] << 8 ) + d[pos+1];
+ pos += 2; /* PES_packet_length */
+ PES_packet_end = pos + PES_packet_length;
+
+ if( streamId != 0xE0 && streamId != 0xBD )
+ {
+ /* Not interesting */
+ pos = PES_packet_end;
+ continue;
+ }
+
+ hasPTS = ( ( d[pos+1] >> 6 ) & 0x2 ) ? 1 : 0;
+ pos += 2; /* Required headers */
+
+ PES_header_d_length = d[pos];
+ pos += 1;
+ PES_header_end = pos + PES_header_d_length;
+
+ if( hasPTS )
+ {
+ PTS = ( ( ( (uint64_t) d[pos] >> 1 ) & 0x7 ) << 30 ) +
+ ( d[pos+1] << 22 ) +
+ ( ( d[pos+2] >> 1 ) << 15 ) +
+ ( d[pos+3] << 7 ) +
+ ( d[pos+4] >> 1 );
+ }
+
+ pos = PES_header_end;
+
+ if( streamId == 0xBD )
+ {
+ /* A52: don't ask */
+ streamId |= ( d[pos] << 8 );
+ pos += 4;
+ }
+
+ /* Sanity check */
+ if( pos >= PES_packet_end )
+ {
+ HBLog( "HBPStoES: pos >= PES_packet_end" );
+ pos = PES_packet_end;
+ continue;
+ }
+
+ /* Here we hit we ES payload */
+ esBuffer = HBBufferInit( PES_packet_end - pos );
+
+ esBuffer->position = psBuffer->position;
+ esBuffer->pass = psBuffer->pass;
+ esBuffer->streamId = streamId;
+ esBuffer->pts = PTS;
+ memcpy( esBuffer->data, d + pos,
+ PES_packet_end - pos );
+
+ HBListAdd( esBufferList, esBuffer );
+
+ pos = PES_packet_end;
+ }
+
+ HBBufferClose( _psBuffer );
+
+ return 1;
+}
+
+#define HBLIST_DEFAULT_SIZE 20
+HBList * HBListInit()
+{
+ HBList * l;
+ if( !( l = malloc( sizeof( HBList ) ) ) )
+ {
+ HBLog( "HBListInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ if( !( l->items = malloc( HBLIST_DEFAULT_SIZE * sizeof( void* ) ) ) )
+ {
+ HBLog( "HBListInit: malloc() failed, gonna crash" );
+ free( l );
+ return NULL;
+ }
+
+ l->allocItems = HBLIST_DEFAULT_SIZE;
+ l->nbItems = 0;
+
+ return l;
+}
+
+int HBListCountItems( HBList * l )
+{
+ return l->nbItems;
+}
+
+void HBListAdd( HBList * l, void * item )
+{
+ if( !item )
+ {
+ return;
+ }
+
+ if( l->nbItems == l->allocItems )
+ {
+ l->allocItems += HBLIST_DEFAULT_SIZE;
+ l->items = realloc( l->items,
+ l->allocItems * sizeof( void* ) );
+ }
+
+ l->items[l->nbItems] = item;
+ (l->nbItems)++;
+}
+
+void HBListRemove( HBList * l, void * item )
+{
+ int i;
+
+ if( !item || !l->nbItems )
+ {
+ return;
+ }
+
+ for( i = 0; i < l->nbItems; i++ )
+ {
+ if( l->items[i] == item )
+ {
+ break;
+ }
+ }
+
+ if( l->items[i] != item )
+ {
+ HBLog( "HBListRemove: specified item is not in the list" );
+ return;
+ }
+
+ for( ; i < l->nbItems - 1; i++ )
+ {
+ l->items[i] = l->items[i+1];
+ }
+
+ (l->nbItems)--;
+}
+
+void * HBListItemAt( HBList * l, int index )
+{
+ if( index < 0 || index >= l->nbItems )
+ {
+ return NULL;
+ }
+
+ return l->items[index];
+}
+
+void HBListClose( HBList ** _l )
+{
+ HBList * l = *_l;
+
+ free( l->items );
+ free( l );
+
+ *_l = NULL;
+}
+
+HBTitle * HBTitleInit( char * device, int index )
+{
+ HBTitle * t = calloc( sizeof( HBTitle ), 1 );
+
+ t->device = strdup( device );
+ t->index = index;
+
+ t->codec = HB_CODEC_FFMPEG;
+ t->bitrate = 1024;
+
+ t->audioList = HBListInit();
+
+ return t;
+}
+
+void HBTitleClose( HBTitle ** _t )
+{
+ HBTitle * t = *_t;
+
+ HBAudio * audio;
+ while( ( audio = HBListItemAt( t->audioList, 0 ) ) )
+ {
+ HBListRemove( t->audioList, audio );
+ HBAudioClose( &audio );
+ }
+ HBListClose( &t->audioList );
+
+ if( t->file ) free( t->file );
+ free( t->device );
+ free( t );
+
+ *_t = NULL;
+}
+
+HBAudio * HBAudioInit( int id, char * language )
+{
+ HBAudio * a;
+ if( !( a = malloc( sizeof( HBAudio ) ) ) )
+ {
+ HBLog( "HBAudioInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ a->id = id;
+ a->language = strdup( language );
+ a->inSampleRate = 0;
+ a->outSampleRate = 44100;
+ a->delay = 0;
+ a->ac3Fifo = NULL;
+ a->rawFifo = NULL;
+ a->mp3Fifo = NULL;
+ a->ac3Dec = NULL;
+ a->mp3Enc = NULL;
+
+ return a;
+}
+
+void HBAudioClose( HBAudio ** _a )
+{
+ HBAudio * a = *_a;
+
+ free( a->language );
+ free( a );
+
+ *_a = NULL;
+}
+
diff --git a/core/Utils.h b/core/Utils.h
new file mode 100644
index 000000000..ba1a9101e
--- /dev/null
+++ b/core/Utils.h
@@ -0,0 +1,213 @@
+/* $Id: Utils.h,v 1.6 2003/11/07 21:22:17 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_UTILS_H
+#define HB_UTILS_H
+
+/* Standard headers */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+typedef uint8_t byte_t;
+#ifdef SYS_BEOS
+# include <OS.h>
+#endif
+
+/* Handy macros */
+#ifndef MIN
+#define MIN( a, b ) ( ( (a) > (b) ) ? (b) : (a) )
+#endif
+#ifndef MAX
+#define MAX( a, b ) ( ( (a) > (b) ) ? (a) : (b) )
+#endif
+#ifndef EVEN
+#define EVEN( a ) ( ( (a) & 0x1 ) ? ( (a) + 1 ) : (a) )
+#endif
+#ifndef MULTIPLE_16
+#define MULTIPLE_16( a ) ( 16 * ( ( (a) + 8 ) / 16 ) )
+#endif
+#ifndef VOUT_ASPECT_FACTOR
+#define VOUT_ASPECT_FACTOR 432000
+#endif
+
+typedef struct HBAc3Dec HBAc3Dec;
+typedef struct HBAudio HBAudio;
+typedef struct HBAviMux HBAviMux;
+typedef struct HBBuffer HBBuffer;
+typedef struct HBDVDRead HBDVDRead;
+typedef struct HBFifo HBFifo;
+typedef struct HBList HBList;
+typedef struct HBLock HBLock;
+typedef struct HBHandle HBHandle;
+typedef struct HBMp3Enc HBMp3Enc;
+typedef struct HBMpeg2Dec HBMpeg2Dec;
+typedef struct HBFfmpegEnc HBFfmpegEnc;
+typedef struct HBMadDec HBMadDec;
+typedef struct HBScale HBScale;
+typedef struct HBScan HBScan;
+typedef struct HBStatus HBStatus;
+typedef struct HBThread HBThread;
+typedef struct HBTitle HBTitle;
+typedef struct HBWork HBWork;
+typedef struct HBWorkThread HBWorkThread;
+typedef struct HBXvidEnc HBXvidEnc;
+
+/* Misc functions which may be used from anywhere */
+void HBSnooze( int time );
+void HBLog( char * log, ... );
+uint64_t HBGetDate();
+int HBPStoES( HBBuffer ** psBuffer, HBList * esBufferList );
+
+/* HBList functions */
+HBList * HBListInit();
+int HBListCountItems( HBList * );
+void HBListAdd( HBList *, void * item );
+void HBListRemove( HBList *, void * item );
+void * HBListItemAt( HBList *, int index );
+void HBListClose( HBList ** );
+
+/* HBTitle function */
+HBTitle * HBTitleInit();
+void HBTitleClose( HBTitle ** );
+
+/* HBAudio functions */
+HBAudio * HBAudioInit( int id, char * language );
+void HBAudioClose( HBAudio ** );
+
+/* Possible states */
+typedef enum
+{
+ HB_MODE_UNDEF = 00000,
+ HB_MODE_NEED_DEVICE = 00001,
+ HB_MODE_SCANNING = 00002,
+ HB_MODE_INVALID_DEVICE = 00004,
+ HB_MODE_READY_TO_RIP = 00010,
+ HB_MODE_ENCODING = 00020,
+ HB_MODE_PAUSED = 00040,
+ HB_MODE_STOPPING = 00100,
+ HB_MODE_DONE = 00200,
+ HB_MODE_CANCELED = 00400,
+ HB_MODE_ERROR = 01000,
+ HB_MODE_EXITING = 02000
+} 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;
+
+/* Possible codecs */
+typedef enum
+{
+ HB_CODEC_FFMPEG = 0,
+ HB_CODEC_XVID
+} HBCodec;
+
+struct HBStatus
+{
+ HBMode mode;
+
+ /* HB_MODE_SCANNING */
+ int scannedTitle;
+
+ /* HB_MODE_SCANDONE */
+ HBList * titleList;
+
+ /* HB_MODE_ENCODING || HB_MODE_PAUSED */
+ float position;
+ int pass;
+ int passCount;
+ float frameRate;
+ float avFrameRate;
+ uint32_t remainingTime; /* in seconds */
+
+ /* HB_MODE_ERROR */
+ HBError error;
+};
+
+struct HBTitle
+{
+ char * device;
+ int index;
+ int length;
+ char * file;
+
+ /* Video input */
+ int inWidth;
+ int inHeight;
+ int aspect;
+ int rate;
+ int rateBase;
+
+ /* Video output */
+ int outWidth;
+ int outHeight;
+ int outWidthMax;
+ int outHeightMax;
+ int topCrop;
+ int bottomCrop;
+ int leftCrop;
+ int rightCrop;
+ int deinterlace;
+ HBCodec codec;
+ int bitrate;
+ int twoPass;
+
+ /* Audio infos */
+ HBList * audioList;
+
+ /* Fifos */
+ HBFifo * mpeg2Fifo;
+ HBFifo * rawFifo;
+ HBFifo * scaledFifo;
+ HBFifo * mpeg4Fifo;
+
+ /* Threads */
+ HBDVDRead * dvdRead;
+ HBMpeg2Dec * mpeg2Dec;
+ HBScale * scale;
+ HBFfmpegEnc * ffmpegEnc;
+ HBXvidEnc * xvidEnc;
+ HBAviMux * aviMux;
+ HBWorkThread * workThreads[8];
+};
+
+struct HBAudio
+{
+ /* Ident */
+ uint32_t id;
+ char * language;
+
+ /* Settings */
+ int inSampleRate;
+ int outSampleRate;
+ int inBitrate;
+ int outBitrate;
+
+ int delay; /* in ms */
+
+ /* Fifos */
+ HBFifo * ac3Fifo;
+ HBFifo * rawFifo;
+ HBFifo * mp3Fifo;
+
+ /* Threads */
+ HBAc3Dec * ac3Dec;
+ HBMp3Enc * mp3Enc;
+};
+
+
+
+#endif
diff --git a/core/Work.c b/core/Work.c
new file mode 100644
index 000000000..b15e50839
--- /dev/null
+++ b/core/Work.c
@@ -0,0 +1,187 @@
+/* $Id: Work.c,v 1.4 2003/11/06 12:33:11 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "Thread.h"
+#include "Work.h"
+
+/* Local prototypes */
+static void WorkThread( void * t );
+
+struct HBWork
+{
+ HB_WORK_COMMON_MEMBERS
+};
+
+struct HBWorkThread
+{
+ HBHandle * handle;
+
+ HBList * workList;
+ int firstThread;
+
+ int die;
+ HBThread * thread;
+};
+
+HBWorkThread * HBWorkThreadInit( HBHandle * handle, HBTitle * title,
+ HBAudio * audio, HBAudio * optAudio,
+ int firstThread )
+{
+ int i;
+ HBWork * w;
+
+ HBWorkThread * t;
+ if( !( t = malloc( sizeof( HBWorkThread ) ) ) )
+ {
+ HBLog( "HBWorkThreadInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ t->handle = handle;
+
+ /* Build a list of work objects. They all include
+ HB_WORK_COMMON_MEMBERS, so we'll be able to do the job without
+ knowing what each one actually do */
+ t->workList = HBListInit();
+ HBListAdd( t->workList, title->mpeg2Dec );
+ HBListAdd( t->workList, title->scale );
+
+ if( title->codec == HB_CODEC_FFMPEG )
+ HBListAdd( t->workList, title->ffmpegEnc );
+ else if( title->codec == HB_CODEC_XVID )
+ HBListAdd( t->workList, title->xvidEnc );
+
+ HBListAdd( t->workList, audio->ac3Dec );
+ HBListAdd( t->workList, audio->mp3Enc );
+ if( optAudio )
+ {
+ HBListAdd( t->workList, optAudio->ac3Dec );
+ HBListAdd( t->workList, optAudio->mp3Enc );
+ }
+
+ t->firstThread = firstThread;
+
+ /* Work objects are not thread-safe, so let's init locks so each
+ one can not be called anymore when it's doing something. This
+ is done by the first worker thread (see HBStartRip) */
+ if( t->firstThread )
+ {
+ for( i = 0; i < HBListCountItems( t->workList ); i++ )
+ {
+ w = (HBWork*) HBListItemAt( t->workList, i );
+ w->lock = HBLockInit();
+ w->used = 0;
+ w->time = 0;
+ }
+ }
+
+ /* Actually launch the thread */
+ t->die = 0;
+ t->thread = HBThreadInit( "work thread", WorkThread, t,
+ HB_LOW_PRIORITY );
+
+ return t;
+}
+
+void HBWorkThreadClose( HBWorkThread ** _t )
+{
+ HBWorkThread * t = (*_t);
+ HBWork * w;
+
+ /* Stop the thread */
+ t->die = 1;
+ HBThreadClose( &t->thread );
+
+ /* Destroy locks, show stats */
+ if( t->firstThread )
+ {
+ int i;
+ uint64_t total = 0;
+
+ for( i = 0; i < HBListCountItems( t->workList ); i++ )
+ {
+ w = (HBWork*) HBListItemAt( t->workList, i );
+ HBLockClose( &w->lock );
+ total += w->time;
+ }
+
+ for( i = 0; i < HBListCountItems( t->workList ); i++ )
+ {
+ w = (HBWork*) HBListItemAt( t->workList, i );
+ HBLog( "HBWorkThreadClose: %- 9s = %05.2f %%", w->name,
+ 100.0 * w->time / total );
+ }
+
+ }
+
+ /* Free memory */
+ HBListClose( &t->workList );
+ free( t );
+
+ (*_t) = NULL;
+}
+
+static void WorkThread( void * _t )
+{
+ HBWorkThread * t = (HBWorkThread*) _t;
+ HBWork * w;
+ int didSomething, i;
+ uint64_t date;
+
+ for( ;; )
+ {
+ HBCheckPaused( t->handle );
+
+ didSomething = 0;
+
+ for( i = 0; i < HBListCountItems( t->workList ); i++ )
+ {
+ if( t->die )
+ {
+ break;
+ }
+
+ w = (HBWork*) HBListItemAt( t->workList, i );
+
+ /* Check if another thread isn't using this work object.
+ If not, lock it */
+ HBLockLock( w->lock );
+ if( w->used )
+ {
+ HBLockUnlock( w->lock );
+ continue;
+ }
+ w->used = 1;
+ HBLockUnlock( w->lock );
+
+ /* Actually do the job */
+ date = HBGetDate();
+ if( w->work( w ) )
+ {
+ w->time += HBGetDate() - date;
+ didSomething = 1;
+ }
+
+ /* Unlock */
+ HBLockLock( w->lock );
+ w->used = 0;
+ HBLockUnlock( w->lock );
+ }
+
+ if( t->die )
+ {
+ break;
+ }
+
+ /* If nothing could be done, wait a bit to prevent a useless
+ CPU-consuming loop */
+ if( !didSomething )
+ {
+ HBSnooze( 10000 );
+ }
+ }
+}
+
diff --git a/core/Work.h b/core/Work.h
new file mode 100644
index 000000000..8d3cfba15
--- /dev/null
+++ b/core/Work.h
@@ -0,0 +1,27 @@
+/* $Id: Work.h,v 1.1 2003/11/03 12:08:01 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_WORK_H
+#define HB_WORK_H
+
+#include "HandBrakeInternal.h"
+
+#define HB_WORK_COMMON_MEMBERS \
+ char * name; \
+ HBLock * lock; \
+ int used; \
+ uint64_t time; \
+ int (*work) ( HBWork * );
+
+void HBWorkLock( HBWork * );
+void HBWorkWork( HBWork * );
+void HBWorkUnlock( HBWork * );
+
+HBWorkThread * HBWorkThreadInit( HBHandle *, HBTitle *, HBAudio *,
+ HBAudio *, int firstThread );
+void HBWorkThreadClose( HBWorkThread ** );
+
+#endif
diff --git a/core/Worker.cpp b/core/Worker.cpp
deleted file mode 100644
index 4310e46f4..000000000
--- a/core/Worker.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/* $Id: Worker.cpp,v 1.11 2003/10/16 13:36:17 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;
-
- for( ;; )
- {
- while( fSuspend )
- {
- Snooze( 10000 );
- }
-
- 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 );
- }
- }
-
- tmpDate = mpegDemux + mpeg2Decoder + resizer + mpeg4Encoder +
- ac3Decoder1 + mp3Encoder1 + ac3Decoder2 + mp3Encoder2;
- Log( "HBWorker stopped. CPU utilization:" );
- Log( "- MPEG demuxer: %.2f %%", 100.0 * mpegDemux / tmpDate );
- Log( "- MPEG-2 decoder: %.2f %%", 100.0 * mpeg2Decoder / tmpDate );
- Log( "- Resizer: %.2f %%", 100.0 * resizer / tmpDate );
- Log( "- MPEG-4 encoder: %.2f %%", 100.0 * mpeg4Encoder / tmpDate );
- if( fAudio1 )
- {
- Log( "- AC3 decoder 1: %.2f %%", 100.0 * ac3Decoder1 / tmpDate );
- Log( "- MP3 encoder 1: %.2f %%", 100.0 * mp3Encoder1 / tmpDate );
- }
- if( fAudio2 )
- {
- Log( "- AC3 decoder 2: %.2f %%", 100.0 * ac3Decoder2 / tmpDate );
- Log( "- MP3 encoder 2: %.2f %%", 100.0 * mp3Encoder2 / tmpDate );
- }
-}
-
diff --git a/core/Worker.h b/core/Worker.h
deleted file mode 100644
index 5df8f648b..000000000
--- a/core/Worker.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* $Id: Worker.h,v 1.3 2003/10/16 13:36:17 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 );
- void WaitUntilDone();
-
- private:
- void DoWork();
-
- HBTitle * fTitle;
- HBAudio * fAudio1;
- HBAudio * fAudio2;
-};
-
-#endif
diff --git a/core/XvidEnc.c b/core/XvidEnc.c
new file mode 100644
index 000000000..8f16ad4ba
--- /dev/null
+++ b/core/XvidEnc.c
@@ -0,0 +1,170 @@
+/* $Id: XvidEnc.c,v 1.5 2003/11/05 19:14:37 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "XvidEnc.h"
+#include "Fifo.h"
+#include "Work.h"
+
+#include <xvid.h>
+
+/* Local prototypes */
+static int XvidEncWork( HBWork * );
+
+struct HBXvidEnc
+{
+ HB_WORK_COMMON_MEMBERS
+
+ HBHandle * handle;
+ HBTitle * title;
+
+ void * xvid;
+ HBBuffer * mpeg4Buffer;
+ int pass;
+};
+
+HBXvidEnc * HBXvidEncInit( HBHandle * handle, HBTitle * title )
+{
+ HBXvidEnc * x;
+ if( !( x = malloc( sizeof( HBXvidEnc ) ) ) )
+ {
+ HBLog( "HBXvidEncInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ x->name = strdup( "XvidEnc" );
+ x->work = XvidEncWork;
+
+ x->handle = handle;
+ x->title = title;
+
+ x->xvid = NULL;
+ x->mpeg4Buffer = NULL;
+ x->pass = 42;
+
+ return x;
+}
+
+void HBXvidEncClose( HBXvidEnc ** _x )
+{
+ HBXvidEnc * x = *_x;
+ free( x );
+ *_x = NULL;
+}
+
+static int XvidEncWork( HBWork * w )
+{
+ HBXvidEnc * x = (HBXvidEnc*) w;
+ HBTitle * title = x->title;
+ HBBuffer * scaledBuffer;
+ HBBuffer * mpeg4Buffer;
+ XVID_ENC_FRAME xframe;
+
+ int didSomething = 0;
+
+ if( x->mpeg4Buffer )
+ {
+ if( HBFifoPush( title->mpeg4Fifo, &x->mpeg4Buffer ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+ }
+
+ if( ( scaledBuffer = HBFifoPop( title->scaledFifo ) ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+
+ /* Init or re-init if needed */
+ if( scaledBuffer->pass != x->pass )
+ {
+ XVID_INIT_PARAM xinit;
+ XVID_ENC_PARAM xparam;
+
+ x->pass = scaledBuffer->pass;;
+
+ HBLog( "HBXvidEnc: opening libxvidcore (pass %d)", x->pass );
+
+ xinit.cpu_flags = 0;
+ xvid_init( NULL, 0, &xinit, NULL );
+
+ xparam.width = title->outWidth;
+ xparam.height = title->outHeight;
+
+ xparam.fincr = title->rateBase;
+ xparam.fbase = title->rate;
+
+ xparam.rc_bitrate = title->bitrate * 1000;
+
+ /* Default values should be ok */
+ xparam.rc_reaction_delay_factor = -1;
+ xparam.rc_averaging_period = -1;
+ xparam.rc_buffer = -1;
+ xparam.max_quantizer = -1;
+ xparam.min_quantizer = -1;
+ xparam.max_key_interval = -1;
+
+ if( xvid_encore( NULL, XVID_ENC_CREATE, &xparam, NULL ) )
+ {
+ HBLog( "HBXvidEnc: xvid_encore() failed" );
+ }
+
+ x->xvid = xparam.handle;
+ }
+
+ /* TODO implement 2-pass encoding */
+ if( x->pass == 1 )
+ {
+ HBPosition( x->handle, scaledBuffer->position );
+ HBBufferClose( &scaledBuffer );
+ return didSomething;
+ }
+
+ mpeg4Buffer = HBBufferInit( title->outWidth *
+ title->outHeight * 3 / 2 );
+ mpeg4Buffer->position = scaledBuffer->position;
+
+ xframe.general = XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V;
+ xframe.motion = PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
+ PMV_EXTSEARCH16 | PMV_EARLYSTOP8 |
+ PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8 |
+ PMV_USESQUARES16;
+ xframe.bitstream = mpeg4Buffer->data;
+
+ xframe.image = scaledBuffer->data;
+ xframe.colorspace = XVID_CSP_I420;
+
+ xframe.quant_intra_matrix = NULL;
+ xframe.quant_inter_matrix = NULL;
+ xframe.quant = 0;
+ xframe.intra = -1;
+
+ xframe.hint.hintstream = NULL;
+
+ if( xvid_encore( x->xvid, XVID_ENC_ENCODE, &xframe, NULL ) )
+ {
+ HBLog( "HBXvidEnc: xvid_encore() failed" );
+ }
+
+ mpeg4Buffer->size = xframe.length;
+ mpeg4Buffer->keyFrame = xframe.intra;
+
+ /* Inform the GUI about the current position */
+ HBPosition( x->handle, scaledBuffer->position );
+
+ HBBufferClose( &scaledBuffer );
+ x->mpeg4Buffer = mpeg4Buffer;
+
+ return didSomething;
+}
+
diff --git a/core/XvidEnc.h b/core/XvidEnc.h
new file mode 100644
index 000000000..01cb6f4d4
--- /dev/null
+++ b/core/XvidEnc.h
@@ -0,0 +1,15 @@
+/* $Id: XvidEnc.h,v 1.1 2003/11/03 12:08:01 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#ifndef HB_XVID_ENC_H
+#define HB_XVID_ENC_H
+
+#include "HandBrakeInternal.h"
+
+HBXvidEnc * HBXvidEncInit( HBHandle *, HBTitle * );
+void HBXvidEncClose( HBXvidEnc ** );
+
+#endif