summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorhandbrake <[email protected]>2006-01-14 13:21:55 +0000
committerhandbrake <[email protected]>2006-01-14 13:21:55 +0000
commitdc8de40de13c3f3e643b980a95ef48ccafb542e3 (patch)
tree953b97afe7082bbe2ce4247c703a51aa8e29a3c9 /core
parent4beb6a8b483c9d84677b21cc271ce315f136335c (diff)
HandBrake 0.6.0-test1
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@10 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'core')
-rw-r--r--core/Ac3Dec.c68
-rw-r--r--core/Ac3Dec.h15
-rw-r--r--core/AviMux.c425
-rw-r--r--core/AviMux.h15
-rw-r--r--core/DVDRead.c214
-rw-r--r--core/DVDRead.h16
-rw-r--r--core/FaacEnc.c214
-rw-r--r--core/FfmpegEnc.c293
-rw-r--r--core/FfmpegEnc.h15
-rw-r--r--core/Fifo.c24
-rw-r--r--core/Fifo.h85
-rw-r--r--core/HBInternal.h81
-rw-r--r--core/HandBrake.c599
-rw-r--r--core/HandBrake.h50
-rw-r--r--core/HandBrakeInternal.h35
-rw-r--r--core/Jamfile47
-rw-r--r--core/MadDec.c5
-rw-r--r--core/MadDec.h15
-rw-r--r--core/Mp3Enc.c118
-rw-r--r--core/Mp3Enc.h15
-rw-r--r--core/Mp4Mux.c210
-rw-r--r--core/Mpeg2Dec.c62
-rw-r--r--core/Mpeg2Dec.h15
-rw-r--r--core/OgmMux.c471
-rw-r--r--core/Scale.c73
-rw-r--r--core/Scale.h15
-rw-r--r--core/Scan.c254
-rw-r--r--core/Scan.h15
-rw-r--r--core/Thread.c77
-rw-r--r--core/Thread.h105
-rw-r--r--core/Utils.c94
-rw-r--r--core/Utils.h260
-rw-r--r--core/VorbisEnc.c257
-rw-r--r--core/Work.c120
-rw-r--r--core/Work.h12
-rw-r--r--core/X264Enc.c167
-rw-r--r--core/XvidEnc.c227
-rw-r--r--core/XvidEnc.h15
-rw-r--r--core/XvidVbr.c1648
-rw-r--r--core/XvidVbr.h231
40 files changed, 3145 insertions, 3532 deletions
diff --git a/core/Ac3Dec.c b/core/Ac3Dec.c
index d5430d49e..e1b027887 100644
--- a/core/Ac3Dec.c
+++ b/core/Ac3Dec.c
@@ -1,23 +1,18 @@
-/* $Id: Ac3Dec.c,v 1.4 2003/11/04 20:16:44 titer Exp $
+/* $Id: Ac3Dec.c,v 1.12 2004/01/16 19:04:03 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 "HBInternal.h"
-#include <a52dec/a52.h>
+/* liba52 */
+#include "a52dec/a52.h"
-/* Local prototypes */
-static int Ac3DecWork( HBWork * );
-static int GetBytes( HBAc3Dec *, int );
-
-struct HBAc3Dec
+typedef struct HBAc3Dec
{
HB_WORK_COMMON_MEMBERS
-
+
HBHandle * handle;
HBAudio * audio;
@@ -35,9 +30,13 @@ struct HBAc3Dec
int nextFrameSize; /* In bytes */
float position;
HBBuffer * rawBuffer;
-};
+} HBAc3Dec;
+
+/* Local prototypes */
+static int Ac3DecWork( HBWork * );
+static int GetBytes( HBAc3Dec *, int );
-HBAc3Dec * HBAc3DecInit( HBHandle * handle, HBAudio * audio )
+HBWork * HBAc3DecInit( HBHandle * handle, HBAudio * audio )
{
HBAc3Dec * a;
if( !( a = malloc( sizeof( HBAc3Dec ) ) ) )
@@ -59,8 +58,15 @@ HBAc3Dec * HBAc3DecInit( HBHandle * handle, HBAudio * audio )
/* Let it do the downmixing */
a->outFlags = A52_STEREO;
- /* Lame wants samples from -32768 to 32768 */
- a->sampleLevel = 32768.0;
+ if( audio->codec == HB_CODEC_MP3 )
+ /* Lame wants 16 bits samples */
+ a->sampleLevel = 32768.0;
+ else if( audio->codec == HB_CODEC_AAC )
+ /* Faac wants 24 bits samples */
+ a->sampleLevel = 8388608.0;
+ else if( audio->codec == HB_CODEC_VORBIS )
+ /* Vorbis wants FIXME bits samples */
+ a->sampleLevel = 32768.0;
a->ac3FrameSize = 0;
a->ac3Buffer = NULL;
@@ -69,13 +75,13 @@ HBAc3Dec * HBAc3DecInit( HBHandle * handle, HBAudio * audio )
a->position = 0.0;
a->rawBuffer = NULL;
- return a;
+ return (HBWork*) a;
}
-void HBAc3DecClose( HBAc3Dec ** _a )
+void HBAc3DecClose( HBWork ** _a )
{
- HBAc3Dec * a = *_a;
-
+ HBAc3Dec * a = (HBAc3Dec*) *_a;
+
if( a->ac3Buffer ) HBBufferClose( &a->ac3Buffer );
if( a->rawBuffer ) HBBufferClose( &a->rawBuffer );
a52_free( a->state );
@@ -89,7 +95,7 @@ static int Ac3DecWork( HBWork * w )
{
HBAc3Dec * a = (HBAc3Dec*) w;
HBAudio * audio = a->audio;
-
+
int didSomething = 0;
/* Push decoded buffer */
@@ -135,7 +141,7 @@ static int Ac3DecWork( HBWork * w )
sample_t * samples;
HBBuffer * rawBuffer;
int i;
-
+
if( GetBytes( a, a->nextFrameSize ) )
{
didSomething = 1;
@@ -153,6 +159,9 @@ static int Ac3DecWork( HBWork * w )
/* 6 blocks per frame, 256 samples per block, 2 channels */
rawBuffer = HBBufferInit( 12 * 256 * sizeof( float ) );
rawBuffer->position = a->position;
+ rawBuffer->samples = 6 * 256;
+ rawBuffer->left = (float*) rawBuffer->data;
+ rawBuffer->right = rawBuffer->left + 6 * 256;
for( i = 0; i < 6; i++ )
{
@@ -163,41 +172,34 @@ static int Ac3DecWork( HBWork * w )
samples = a52_samples( a->state );
/* Copy left channel data */
- memcpy( rawBuffer->data + i * 256 * sizeof( float ),
- samples,
+ memcpy( rawBuffer->left + i * 256, samples,
256 * sizeof( float ) );
/* Copy right channel data */
- memcpy( rawBuffer->data + ( 6 + i ) * 256 * sizeof( float ),
- samples + 256,
+ memcpy( rawBuffer->right + i * 256, 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 ) ) )
+ if( !( a->ac3Buffer = HBFifoPop( a->audio->inFifo ) ) )
{
return 0;
}
a->ac3BufferPos = 0;
a->position = a->ac3Buffer->position;
-
- if( a->ac3Buffer->last )
- {
- HBDone( a->handle );
- }
}
i = MIN( size - a->ac3FrameSize,
diff --git a/core/Ac3Dec.h b/core/Ac3Dec.h
deleted file mode 100644
index a1ecaff66..000000000
--- a/core/Ac3Dec.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $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/AviMux.c b/core/AviMux.c
index ca34d3cab..71238425e 100644
--- a/core/AviMux.c
+++ b/core/AviMux.c
@@ -1,42 +1,38 @@
-/* $Id: AviMux.c,v 1.6 2003/11/13 01:18:52 titer Exp $
+/* $Id: AviMux.c,v 1.15 2004/02/18 17:07:20 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"
+#include "HBInternal.h"
-/* Local structures */
-typedef struct AviMainHeader AviMainHeader;
-typedef struct AviStreamHeader AviStreamHeader;
-typedef struct BitmapInfo BitmapInfo;
-typedef struct WaveFormatEx WaveFormatEx;
+int64_t videoFrames;
+int64_t videoBytes;
+int64_t audioFrames;
+int64_t audioBytes;
/* Local prototypes */
static void AviMuxThread( void * );
static void InitAviHeaders( HBAviMux * );
-static void AddChunk( HBAviMux *, HBBuffer **, uint32_t,
- AviStreamHeader * );
+static void AddChunk( HBAviMux *, HBBuffer *, uint32_t,
+ HBAviStreamHeader * );
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 WriteMainHeader( FILE *, HBAviMainHeader * );
+static void WriteStreamHeader( FILE *, HBAviStreamHeader * );
+static void WriteHBBitmapInfo( FILE *, HBBitmapInfo * );
+static void WriteHBWaveFormatEx( FILE *, HBWaveFormatEx * );
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
+struct __attribute__((__packed__)) HBAviMainHeader
{
uint32_t FourCC;
uint32_t BytesCount;
@@ -53,7 +49,7 @@ struct __attribute__((__packed__)) AviMainHeader
uint32_t Reserved[4];
};
-struct __attribute__((__packed__)) AviStreamHeader
+struct __attribute__((__packed__)) HBAviStreamHeader
{
uint32_t FourCC;
uint32_t BytesCount;
@@ -76,7 +72,7 @@ struct __attribute__((__packed__)) AviStreamHeader
int16_t Bottom;
};
-struct __attribute__((__packed__)) BitmapInfo
+struct __attribute__((__packed__)) HBBitmapInfo
{
uint32_t FourCC;
uint32_t BytesCount;
@@ -91,13 +87,9 @@ struct __attribute__((__packed__)) BitmapInfo
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
+struct __attribute__((__packed__)) HBWaveFormatEx
{
uint32_t FourCC;
uint32_t BytesCount;
@@ -121,28 +113,18 @@ 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;
+ volatile int die;
HBThread * thread;
};
-HBAviMux * HBAviMuxInit( HBHandle * handle, HBTitle * title,
- HBAudio * audio, HBAudio * optAudio )
+HBAviMux * HBAviMuxInit( HBHandle * handle, HBTitle * title )
{
HBAviMux * a;
if( !( a = malloc( sizeof( HBAviMux ) ) ) )
@@ -153,8 +135,11 @@ HBAviMux * HBAviMuxInit( HBHandle * handle, HBTitle * title,
a->handle = handle;
a->title = title;
- a->audio = audio;
- a->optAudio = optAudio;
+
+ videoFrames = 0;
+ videoBytes = 0;
+ audioFrames = 0;
+ audioBytes = 0;
a->size = 0;
a->file = NULL;
@@ -170,9 +155,23 @@ HBAviMux * HBAviMuxInit( HBHandle * handle, HBTitle * title,
void HBAviMuxClose( HBAviMux ** _a )
{
HBAviMux * a = *_a;
+ FILE * file;
+ long size;
a->die = 1;
HBThreadClose( &a->thread );
+
+ file = fopen( a->title->file, "r" );
+ fseek( file, 0, SEEK_END );
+ size = ftell( file );
+ fclose( file );
+
+ HBLog( "HBAviMux: videoFrames=%lld, %lld bytes", videoFrames, videoBytes );
+ HBLog( "HBAviMux: audioFrames=%lld, %lld bytes", audioFrames, audioBytes );
+ HBLog( "HBAviMux: overhead=%.2f bytes / frame",
+ ( (float) size - videoBytes - audioBytes ) /
+ ( videoFrames + audioFrames ) );
+
free( a );
*_a = NULL;
@@ -180,14 +179,13 @@ void HBAviMuxClose( HBAviMux ** _a )
static void AviMuxThread( void * _a )
{
- HBAviMux * a = (HBAviMux*) _a;
- HBTitle * title = a->title;
- HBAudio * audio = a->audio;
- HBAudio * optAudio = a->optAudio;
+ HBAviMux * a = (HBAviMux*) _a;
+ HBTitle * title = a->title;
+ int audioCount = HBListCount( title->ripAudioList );
- HBBuffer * videoBuffer = NULL;
- HBBuffer * audioBuffer = NULL;
- HBBuffer * optAudioBuffer = NULL;
+ HBAudio * audio;
+ HBBuffer * buffer;
+ int i;
/* Open destination file */
HBLog( "HBAviMux: opening %s", title->file );
@@ -198,21 +196,25 @@ static void AviMuxThread( void * _a )
return;
}
- /* Get a buffer for each track */
- videoBuffer = Pop( a, title->mpeg4Fifo );
- audioBuffer = Pop( a, audio->mp3Fifo );
- if( optAudio )
+ /* Wait until we have one encoded frame for each track */
+ while( !a->die && !HBFifoSize( title->outFifo ) )
{
- optAudioBuffer = Pop( a, optAudio->mp3Fifo );
+ HBSnooze( 10000 );
+ }
+ for( i = 0; i < audioCount; i++ )
+ {
+ audio = HBListItemAt( title->ripAudioList, i );
+ while( !a->die && !HBFifoSize( audio->outFifo ) )
+ {
+ HBSnooze( 10000 );
+ }
}
- /* Failed ? Then forget it */
- if( !videoBuffer || !audioBuffer ||
- ( optAudio && !optAudioBuffer ) )
+ if( a->die )
{
fclose( a->file );
a->file = NULL;
-
+
HBLog( "HBAviMux: deleting %s", title->file );
unlink( title->file );
return;
@@ -222,48 +224,56 @@ static void AviMuxThread( void * _a )
for( ;; )
{
- /* Get a buffer for each track */
- if( !videoBuffer )
- {
- videoBuffer = Pop( a, title->mpeg4Fifo );
- }
- if( !audioBuffer )
+ /* Wait until we have one encoded frame for each track */
+ if( !HBFifoWait( title->outFifo ) )
{
- audioBuffer = Pop( a, audio->mp3Fifo );
+ a->die = 1;
}
- if( optAudio && !optAudioBuffer )
+ for( i = 0; i < audioCount; i++ )
{
- optAudioBuffer = Pop( a, optAudio->mp3Fifo );
+ audio = HBListItemAt( title->ripAudioList, i );
+ if( !HBFifoWait( audio->outFifo ) )
+ {
+ a->die = 1;
+ break;
+ }
}
- if( !videoBuffer && !audioBuffer && !optAudioBuffer )
+ if( a->die )
{
- /* 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 ) )
+ audio = NULL;
+ for( i = 0; i < audioCount; i++ )
{
- AddChunk( a, &videoBuffer, FOURCC( "00dc" ),
- &a->videoHeader );
+ HBAudio * otherAudio;
+ otherAudio = HBListItemAt( title->ripAudioList, i );
+ if( !audio || HBFifoPosition( otherAudio->outFifo ) <
+ HBFifoPosition( audio->outFifo ) )
+ {
+ audio = otherAudio;
+ }
}
- else if( audioBuffer &&
- ( !optAudioBuffer ||
- audioBuffer->position < optAudioBuffer->position ) )
+
+ if( audio == NULL ||
+ HBFifoPosition( title->outFifo ) < HBFifoPosition( audio->outFifo ) )
{
- AddChunk( a, &audioBuffer, FOURCC( "01wb" ),
- &a->audioHeader );
+ buffer = HBFifoPop( title->outFifo );
+ AddChunk( a, buffer, FOURCC( "00dc" ), title->aviVideoHeader );
+ videoFrames++;
+ videoBytes += buffer->size;
+ HBBufferClose( &buffer );
}
else
{
- AddChunk( a, &optAudioBuffer, FOURCC( "02wb" ),
- &a->optAudioHeader );
+ buffer = HBFifoPop( audio->outFifo );
+ AddChunk( a, buffer, audio->aviFourCC, audio->aviAudioHeader );
+ audioFrames++;
+ audioBytes += buffer->size;
+ HBBufferClose( &buffer );
}
}
@@ -275,49 +285,57 @@ static void AviMuxThread( void * _a )
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;
+ HBTitle * title = a->title;
+ FILE * file = a->file;
+ int audioCount = HBListCount( title->ripAudioList );
+
+ HBAudio * audio;
+ HBAviMainHeader * mainHeader;
+ HBAviStreamHeader * videoHeader;
+ HBBitmapInfo * videoFormat;
+ HBAviStreamHeader * audioHeader;
+ HBWaveFormatEx * audioFormat;
+ int hdrlBytes;
+ int i;
/* AVI main header */
- memset( mainHeader, 0, sizeof( AviMainHeader ) );
+ mainHeader = calloc( sizeof( HBAviMainHeader ), 1 );
+
mainHeader->FourCC = FOURCC( "avih" );
- mainHeader->BytesCount = sizeof( AviMainHeader ) - 8;
+ mainHeader->BytesCount = sizeof( HBAviMainHeader ) - 8;
mainHeader->MicroSecPerFrame = (uint64_t) 1000000 *
title->rateBase / title->rate;
- mainHeader->Streams = optAudio ? 3 : 2;
+ mainHeader->Streams = 1 + audioCount;
mainHeader->Width = title->outWidth;
mainHeader->Height = title->outHeight;
+ title->aviMainHeader = mainHeader;
+
/* Video stream header */
- memset( videoHeader, 0, sizeof( AviStreamHeader ) );
+ videoHeader = calloc( sizeof( HBAviStreamHeader ), 1 );
+
videoHeader->FourCC = FOURCC( "strh" );
- videoHeader->BytesCount = sizeof( AviStreamHeader ) - 8;
+ videoHeader->BytesCount = sizeof( HBAviStreamHeader ) - 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" );
-
+ else if( title->codec == HB_CODEC_X264 )
+ videoHeader->Handler = FOURCC( "H264" );
+
videoHeader->Scale = title->rateBase;
videoHeader->Rate = title->rate;
+ title->aviVideoHeader = videoHeader;
+
/* Video stream format */
- memset( videoFormat, 0, sizeof( BitmapInfo ) );
+ videoFormat = calloc( sizeof( HBBitmapInfo ), 1 );
+
videoFormat->FourCC = FOURCC( "strf" );
- videoFormat->BytesCount = sizeof( BitmapInfo ) - 8;
- videoFormat->Size = sizeof( BitmapInfo ) - 8;
+ videoFormat->BytesCount = sizeof( HBBitmapInfo ) - 8;
+ videoFormat->Size = sizeof( HBBitmapInfo ) - 8;
videoFormat->Width = title->outWidth;
videoFormat->Height = title->outHeight;
videoFormat->Planes = 1;
@@ -326,66 +344,51 @@ static void InitAviHeaders( HBAviMux * a )
videoFormat->Compression = FOURCC( "DX50" );
else if( title->codec == HB_CODEC_XVID )
videoFormat->Compression = FOURCC( "XVID" );
+ else if( title->codec == HB_CODEC_X264 )
+ videoFormat->Compression = FOURCC( "H264" );
- /* 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 )
+ title->aviVideoFormat = videoFormat;
+
+ for( i = 0; i < audioCount; i++ )
{
- /* 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;
+ audio = HBListItemAt( title->ripAudioList, i );
+
+ /* Audio stream header */
+ audioHeader = calloc( sizeof( HBAviStreamHeader ), 1 );
+
+ audioHeader->FourCC = FOURCC( "strh" );
+ audioHeader->BytesCount = sizeof( HBAviStreamHeader ) - 8;
+ audioHeader->Type = FOURCC( "auds" );
+ audioHeader->InitialFrames = 1;
+ audioHeader->Scale = 1152;
+ audioHeader->Rate = audio->outSampleRate;
+ audioHeader->Quality = 0xFFFFFFFF;
+
+ audio->aviAudioHeader = audioHeader;
+
+ /* Audio stream format */
+ audioFormat = calloc( sizeof( HBWaveFormatEx ), 1 );
+
+ audioFormat->FourCC = FOURCC( "strf" );
+ audioFormat->BytesCount = sizeof( HBWaveFormatEx ) - 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;
+
+ audio->aviAudioFormat = audioFormat;
}
- hdrlBytes = 4 + sizeof( AviMainHeader ) +
- ( optAudio ? 3 : 2 ) * ( 12 + sizeof( AviStreamHeader ) ) +
- sizeof( BitmapInfo ) +
- ( optAudio ? 2 : 1 ) * sizeof( WaveFormatEx );
+ hdrlBytes = 4 + sizeof( HBAviMainHeader ) + ( 1 + audioCount ) *
+ ( 12 + sizeof( HBAviStreamHeader ) ) + sizeof( HBBitmapInfo ) +
+ audioCount * sizeof( HBWaveFormatEx );
/* Here we really start to write into the file */
@@ -395,28 +398,31 @@ static void InitAviHeaders( HBAviMux * a )
WriteInt32( file, FOURCC( "LIST" ) );
WriteInt32( file, hdrlBytes );
WriteInt32( file, FOURCC( "hdrl" ) );
- WriteMainHeader( file, mainHeader );
+ WriteMainHeader( file, title->aviMainHeader );
WriteInt32( file, FOURCC( "LIST" ) );
- WriteInt32( file, 4 + sizeof( AviStreamHeader ) +
- sizeof( BitmapInfo ) );
+ WriteInt32( file, 4 + sizeof( HBAviStreamHeader ) +
+ sizeof( HBBitmapInfo ) );
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 )
+ WriteStreamHeader( file, title->aviVideoHeader );
+ WriteHBBitmapInfo( file, title->aviVideoFormat );
+
+ for( i = 0; i < audioCount; i++ )
{
+ char fourCC[5];
+
+ audio = HBListItemAt( title->ripAudioList, i );
+
+ snprintf( fourCC, 5, "%02dwb", i + 1 );
+ audio->aviFourCC = FOURCC( fourCC );
+
WriteInt32( file, FOURCC( "LIST" ) );
- WriteInt32( file, 4 + sizeof( AviStreamHeader ) +
- sizeof( WaveFormatEx ) );
+ WriteInt32( file, 4 + sizeof( HBAviStreamHeader ) +
+ sizeof( HBWaveFormatEx ) );
WriteInt32( file, FOURCC( "strl" ) );
- WriteStreamHeader( file, optAudioHeader );
- WriteWaveFormatEx( file, optAudioFormat );
+ WriteStreamHeader( file, audio->aviAudioHeader );
+ WriteHBWaveFormatEx( file, audio->aviAudioFormat );
}
+
WriteInt32( file, FOURCC( "JUNK" ) );
WriteInt32( file, 2008 - hdrlBytes );
for( i = 0; i < 2008 - hdrlBytes; i++ )
@@ -428,11 +434,14 @@ static void InitAviHeaders( HBAviMux * a )
WriteInt32( file, FOURCC( "movi" ) );
}
-static void AddChunk( HBAviMux * a, HBBuffer ** _buffer,
- uint32_t fourCC, AviStreamHeader * header )
+static void AddChunk( HBAviMux * a, HBBuffer * buffer,
+ uint32_t fourCC, HBAviStreamHeader * header )
{
- HBBuffer * buffer = *_buffer;
-
+ HBTitle * title = a->title;
+
+ HBAudio * audio;
+ int i;
+
/* Update index */
IndexAddInt32( a->index, fourCC );
IndexAddInt32( a->index, buffer->keyFrame ? AVIIF_KEYFRAME : 0 );
@@ -459,28 +468,28 @@ static void AddChunk( HBAviMux * a, HBBuffer ** _buffer,
fseek( a->file, 4, SEEK_SET );
WriteInt32( a->file, 2040 + a->size );
- /* AviStreamHeader's length */
+ /* HBAviStreamHeader's lengths */
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 )
+ WriteInt32( a->file, title->aviVideoHeader->Length );
+
+ for( i = 0; i < HBListCount( title->ripAudioList ); i++ )
{
- fseek( a->file, 382, SEEK_SET );
- WriteInt32( a->file, a->optAudioHeader.Length );
+ audio = (HBAudio*) HBListItemAt( title->ripAudioList, i );
+ fseek( a->file, 268 + i * 114, SEEK_SET );
+ WriteInt32( a->file, audio->aviAudioHeader->Length );
}
/* movi size */
fseek( a->file, 2040, SEEK_SET );
WriteInt32( a->file, 4 + a->size );
-
- HBBufferClose( _buffer );
}
static void AddIndex( HBAviMux * a )
{
+ HBTitle * title = a->title;
+
fseek( a->file, 0, SEEK_END );
-
+
WriteInt32( a->file, FOURCC( "idx1" ) );
WriteInt32( a->file, a->index->size );
WriteBuffer( a->file, a->index );
@@ -488,9 +497,9 @@ static void AddIndex( HBAviMux * a )
a->size += 8 + a->index->size;
fseek( a->file, 4, SEEK_SET );
WriteInt32( a->file, 2040 + a->size );
- a->mainHeader.Flags |= AVIF_HASINDEX;
+ title->aviMainHeader->Flags |= AVIF_HASINDEX;
fseek( a->file, 24, SEEK_SET );
- WriteMainHeader( a->file, &a->mainHeader );
+ WriteMainHeader( a->file, title->aviMainHeader );
}
static void WriteInt8( FILE * file, uint8_t val )
@@ -517,7 +526,7 @@ static void WriteBuffer( FILE * file, HBBuffer * buffer )
fwrite( buffer->data, buffer->size, 1, file );
}
-static void WriteBitmapInfo( FILE * file, BitmapInfo * bitmapInfo )
+static void WriteHBBitmapInfo( FILE * file, HBBitmapInfo * bitmapInfo )
{
WriteInt32( file, bitmapInfo->FourCC );
WriteInt32( file, bitmapInfo->BytesCount );
@@ -532,13 +541,15 @@ static void WriteBitmapInfo( FILE * file, BitmapInfo * bitmapInfo )
WriteInt32( file, bitmapInfo->YPelsPerMeter );
WriteInt32( file, bitmapInfo->ClrUsed );
WriteInt32( file, bitmapInfo->ClrImportant );
+#if 0
WriteInt8( file, bitmapInfo->Blue );
WriteInt8( file, bitmapInfo->Green );
WriteInt8( file, bitmapInfo->Red );
WriteInt8( file, bitmapInfo->Reserved );
+#endif
}
-static void WriteWaveFormatEx( FILE * file, WaveFormatEx * waveFormatEx )
+static void WriteHBWaveFormatEx( FILE * file, HBWaveFormatEx * waveFormatEx )
{
WriteInt32( file, waveFormatEx->FourCC );
WriteInt32( file, waveFormatEx->BytesCount );
@@ -556,7 +567,7 @@ static void WriteWaveFormatEx( FILE * file, WaveFormatEx * waveFormatEx )
WriteInt16( file, waveFormatEx->CodecDelay );
}
-static void WriteMainHeader( FILE * file, AviMainHeader * mainHeader )
+static void WriteMainHeader( FILE * file, HBAviMainHeader * mainHeader )
{
WriteInt32( file, mainHeader->FourCC );
WriteInt32( file, mainHeader->BytesCount );
@@ -576,7 +587,7 @@ static void WriteMainHeader( FILE * file, AviMainHeader * mainHeader )
WriteInt32( file, mainHeader->Reserved[3] );
}
-static void WriteStreamHeader( FILE * file, AviStreamHeader * streamHeader )
+static void WriteStreamHeader( FILE * file, HBAviStreamHeader * streamHeader )
{
WriteInt32( file, streamHeader->FourCC );
WriteInt32( file, streamHeader->BytesCount );
@@ -614,27 +625,3 @@ static void IndexAddInt32( HBBuffer * b, uint32_t val )
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
deleted file mode 100644
index 1fccbe971..000000000
--- a/core/AviMux.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $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/DVDRead.c b/core/DVDRead.c
index 58e8f1031..f90660948 100644
--- a/core/DVDRead.c
+++ b/core/DVDRead.c
@@ -1,18 +1,17 @@
-/* $Id: DVDRead.c,v 1.4 2003/11/06 13:03:19 titer Exp $
+/* $Id: DVDRead.c,v 1.9 2004/01/16 19:04:03 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 "HBInternal.h"
-#include <dvdread/ifo_types.h>
-#include <dvdplay/dvdplay.h>
-#include <dvdplay/info.h>
-#include <dvdplay/state.h>
-#include <dvdplay/nav.h>
+/* libdvdplay */
+#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 * );
@@ -22,30 +21,21 @@ 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;
+ HBHandle * handle;
+
+ dvdplay_ptr vmg;
+ HBTitle * title;
+ int beginPosition;
+ int endPosition;
+ int pass;
+ HBBuffer * psBuffer;
+ HBList * esBufferList;
+
+ volatile int die;
+ HBThread * thread;
};
-HBDVDRead * HBDVDReadInit( HBHandle * handle, HBTitle * t,
- HBAudio * a1, HBAudio * a2 )
+HBDVDRead * HBDVDReadInit( HBHandle * handle, HBTitle * title )
{
HBDVDRead * d;
if( !( d = malloc( sizeof( HBDVDRead ) ) ) )
@@ -57,20 +47,12 @@ HBDVDRead * HBDVDReadInit( HBHandle * handle, HBTitle * t,
/* Initializations */
d->handle = handle;
d->vmg = NULL;
- d->title = t;
- d->audio = a1;
- d->optAudio = a2;
+ d->title = title;
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;
@@ -83,13 +65,13 @@ HBDVDRead * HBDVDReadInit( HBHandle * handle, HBTitle * t,
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 ) ) )
{
@@ -98,72 +80,58 @@ void HBDVDReadClose( HBDVDRead ** _d )
}
HBListClose( &d->esBufferList ) ;
free( d );
-
+
(*_d) = NULL;
}
static void DVDReadThread( void * _d )
{
- HBDVDRead * d = (HBDVDRead*) _d;
+ HBDVDRead * d = (HBDVDRead*) _d;
+ HBTitle * title = d->title;
+
uint8_t dummy[DVD_VIDEO_LB_LEN];
int i;
/* Open the device */
- d->vmg = dvdplay_open( d->title->device, NULL, NULL );
+ d->vmg = dvdplay_open( 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 );
+ dvdplay_start( d->vmg, 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++ )
+ for( i = 0; i < ( 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;
+ title->twoPass ? 2 : 1 );
+
+ d->pass = 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 );
- }
+ HBDone( d->handle );
}
/* Clean up */
@@ -180,20 +148,20 @@ static int DoPass( HBDVDRead * d )
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 );
@@ -211,7 +179,11 @@ static int DoPass( HBDVDRead * d )
static int Demux( HBDVDRead * d )
{
+ HBTitle * title = d->title;
+
+ HBAudio * audio;
HBBuffer * esBuffer;
+ int i;
/* Demux */
HBPStoES( &d->psBuffer, d->esBufferList );
@@ -229,72 +201,48 @@ static int Demux( HBDVDRead * d )
if( esBuffer->streamId == 0xE0 )
{
- if( d->videoStart < 0 )
+ if( title->start < 0 )
{
- d->videoStart = esBuffer->pts / 90;
+ title->start = esBuffer->pts / 90;
HBLog( "HBDVDRead: got first 0xE0 packet (%d)",
- d->videoStart );
+ title->start );
}
- if( d->videoBuf )
+ HBListRemove( d->esBufferList, esBuffer );
+ if( !Push( d, title->inFifo, &esBuffer ) )
{
- d->videoBuf->last = 0;
- if( !Push( d, d->title->mpeg2Fifo, &d->videoBuf ) )
- {
- return 0;
- }
+ return 0;
}
-
- HBListRemove( d->esBufferList, esBuffer );
- d->videoBuf = esBuffer;
+ continue;
}
- 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;
- }
+ for( i = 0; i < HBListCount( title->ripAudioList ); i++ )
+ {
+ audio = (HBAudio*) HBListItemAt( title->ripAudioList, i );
- if( d->audioBuf )
+ if( esBuffer->streamId != audio->id )
{
- d->audioBuf->last = 0;
- if( !Push( d, d->audio->ac3Fifo, &d->audioBuf ) )
- {
- return 0;
- }
+ continue;
}
- HBListRemove( d->esBufferList, esBuffer );
- d->audioBuf = esBuffer;
- }
- else if( d->optAudio && esBuffer->streamId == d->optAudio->id )
- {
- if( d->optAudioStart < 0 )
+ if( audio->start < 0 )
{
- d->optAudioStart = esBuffer->pts / 90;
+ audio->start = esBuffer->pts / 90;
HBLog( "HBDVDRead: got first 0x%x packet (%d)",
- d->optAudio->id, d->optAudioStart );
+ audio->id, audio->start );
- d->optAudio->delay = d->optAudioStart - d->videoStart;
+ audio->delay = audio->start - title->start;
}
- if( d->optAudioBuf )
+ HBListRemove( d->esBufferList, esBuffer );
+ if( !Push( d, audio->inFifo, &esBuffer ) )
{
- d->optAudioBuf->last = 0;
- if( !Push( d, d->optAudio->ac3Fifo, &d->optAudioBuf ) )
- {
- return 0;
- }
+ return 0;
}
-
- HBListRemove( d->esBufferList, esBuffer );
- d->optAudioBuf = esBuffer;
+ break;
}
- else
+
+ if( esBuffer )
{
HBListRemove( d->esBufferList, esBuffer );
HBBufferClose( &esBuffer );
@@ -303,24 +251,16 @@ static int Demux( HBDVDRead * d )
return 1;
}
-
+
static int Push( HBDVDRead * d, HBFifo * fifo, HBBuffer ** buffer )
{
- for( ;; )
+ while( !d->die )
{
- HBCheckPaused( d->handle );
-
if( HBFifoPush( fifo, buffer ) )
{
return 1;
}
-
- if( d->die )
- {
- break;
- }
-
- HBSnooze( 10000 );
+ HBSnooze( 5000 );
}
return 0;
diff --git a/core/DVDRead.h b/core/DVDRead.h
deleted file mode 100644
index 7a9aa7e21..000000000
--- a/core/DVDRead.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* $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/FaacEnc.c b/core/FaacEnc.c
new file mode 100644
index 000000000..b55a9deb6
--- /dev/null
+++ b/core/FaacEnc.c
@@ -0,0 +1,214 @@
+/* $Id: FaacEnc.c,v 1.15 2004/02/18 17:07:20 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 "HBInternal.h"
+
+/* libfaac */
+#include "faac.h"
+
+typedef struct HBFaacEnc
+{
+ HB_WORK_COMMON_MEMBERS
+
+ HBHandle * handle;
+ HBAudio * audio;
+
+ faacEncHandle * faac;
+ unsigned long inputSamples;
+ unsigned long maxOutputBytes;
+ int32_t * inputBuffer;
+ unsigned long samplesGot;
+ HBBuffer * rawBuffer;
+ int rawBufferPos; /* in bytes */
+ float position;
+ HBBuffer * aacBuffer;
+
+ /* Stats */
+ int64_t samples;
+ int64_t bytes;
+} HBFaacEnc;
+
+/* Local prototypes */
+static int FaacEncWork( HBWork * );
+static int GetSamples( HBFaacEnc * );
+
+HBWork * HBFaacEncInit( HBHandle * handle, HBAudio * audio )
+{
+ HBFaacEnc * f;
+ if( !( f = calloc( sizeof( HBFaacEnc ), 1 ) ) )
+ {
+ HBLog( "HBFaacEncInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ f->name = strdup( "FaacEnc" );
+ f->work = FaacEncWork;
+
+ f->handle = handle;
+ f->audio = audio;
+
+ return (HBWork*) f;
+}
+
+void HBFaacEncClose( HBWork ** _f )
+{
+ HBFaacEnc * f = (HBFaacEnc*) *_f;
+
+ if( f->faac )
+ {
+ faacEncClose( f->faac );
+ free( f->inputBuffer );
+ }
+
+ if( f->samples )
+ {
+ int64_t bytes = 128 * f->audio->outBitrate * f->samples /
+ f->audio->outSampleRate;
+ float bitrate = (float) f->bytes * f->audio->inSampleRate /
+ f->samples / 128;
+
+ HBLog( "HBFaacEnc: %lld samples encoded (%lld bytes), %.2f kbps",
+ f->samples, f->bytes, bitrate );
+ HBLog( "HBFaacEnc: error is %lld bytes", f->bytes - bytes );
+ }
+
+ free( f->name );
+ free( f );
+
+ *_f = NULL;
+}
+
+static int FaacEncWork( HBWork * w )
+{
+ HBFaacEnc * f = (HBFaacEnc*) w;
+ HBAudio * audio = f->audio;
+
+ int didSomething = 0;
+
+ if( !f->faac )
+ {
+ faacEncConfigurationPtr config;
+
+ /* Get a first buffer so we know that audio->inSampleRate is
+ correct */
+ if( ( f->rawBuffer = HBFifoPop( audio->rawFifo ) ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+ f->rawBufferPos = 0;
+ f->position = f->rawBuffer->position;
+
+ HBLog( "HBFaacEnc: opening libfaac (%x)", audio->id );
+
+ /* No resampling */
+ audio->outSampleRate = audio->inSampleRate;
+
+ f->faac = faacEncOpen( audio->outSampleRate, 2,
+ &f->inputSamples, &f->maxOutputBytes );
+ f->inputBuffer = malloc( f->inputSamples * sizeof( int32_t ) );
+ config = faacEncGetCurrentConfiguration( f->faac );
+ config->mpegVersion = MPEG4;
+ config->aacObjectType = LOW;
+ config->allowMidside = 1;
+ config->useLfe = 0;
+ config->useTns = 0;
+ config->bitRate = audio->outBitrate * 512;
+ config->bandWidth = 0;
+ config->outputFormat = 0;
+ faacEncSetConfiguration( f->faac, config );
+ faacEncGetDecoderSpecificInfo( f->faac, &audio->esConfig,
+ &audio->esConfigLength );
+ }
+
+ /* Push encoded buffer */
+ if( f->aacBuffer )
+ {
+ if( HBFifoPush( audio->outFifo, &f->aacBuffer ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+ }
+
+ if( GetSamples( f ) )
+ {
+ didSomething = 1;
+ }
+ else
+ {
+ return didSomething;
+ }
+
+ f->samplesGot = 0;
+
+ f->aacBuffer = HBBufferInit( f->maxOutputBytes );
+ f->aacBuffer->position = f->position;
+ f->aacBuffer->size = faacEncEncode( f->faac, f->inputBuffer,
+ f->inputSamples, f->aacBuffer->data, f->maxOutputBytes );
+
+ f->samples += f->inputSamples / 2;
+
+ if( !f->aacBuffer->size )
+ {
+ HBBufferClose( &f->aacBuffer );
+ }
+ else if( f->aacBuffer->size < 0 )
+ {
+ HBLog( "HBFaacEnc: faacEncEncode() failed" );
+ }
+ else
+ {
+ f->bytes += f->aacBuffer->size;
+ }
+
+ return didSomething;
+}
+
+static int GetSamples( HBFaacEnc * f )
+{
+ while( f->samplesGot < f->inputSamples )
+ {
+ int i, copy;
+
+ if( !f->rawBuffer )
+ {
+ if( !( f->rawBuffer = HBFifoPop( f->audio->rawFifo ) ) )
+ {
+ return 0;
+ }
+
+ f->rawBufferPos = 0;
+ f->position = f->rawBuffer->position;
+ }
+
+ copy = MIN( f->inputSamples - f->samplesGot,
+ ( f->rawBuffer->samples - f->rawBufferPos ) * 2 );
+
+ for( i = 0; i < copy; i += 2 )
+ {
+ f->inputBuffer[f->samplesGot++] =
+ f->rawBuffer->left[f->rawBufferPos];
+ f->inputBuffer[f->samplesGot++] =
+ f->rawBuffer->right[f->rawBufferPos];
+ f->rawBufferPos++;
+ }
+
+ if( f->rawBufferPos == f->rawBuffer->samples )
+ {
+ HBBufferClose( &f->rawBuffer );
+ }
+ }
+
+ return 1;
+}
+
diff --git a/core/FfmpegEnc.c b/core/FfmpegEnc.c
index 2118c29d6..4028dc5fb 100644
--- a/core/FfmpegEnc.c
+++ b/core/FfmpegEnc.c
@@ -1,38 +1,40 @@
-/* $Id: FfmpegEnc.c,v 1.5 2003/11/06 13:03:19 titer Exp $
+/* $Id: FfmpegEnc.c,v 1.18 2004/01/21 17:59:33 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 "HBInternal.h"
-#include <ffmpeg/avcodec.h>
+/* libavcodec */
+#include "ffmpeg/avcodec.h"
-/* Extern functions */
-void HBSetPosition( HBHandle *, float );
-
-/* Local prototypes */
-static int FfmpegEncWork( HBWork * );
-
-struct HBFfmpegEnc
+typedef struct HBFfmpegEnc
{
HB_WORK_COMMON_MEMBERS
- HBHandle * handle;
- HBTitle * title;
+ HBHandle * handle;
+ HBTitle * title;
- HBBuffer * mpeg4Buffer;
- int pass;
+ HBBuffer * mpeg4Buffer;
+ int pass;
AVCodecContext * context;
- FILE * file;
-};
+ FILE * file;
+
+ /* Stats */
+ int frames;
+ int64_t bytes;
+} HBFfmpegEnc;
-HBFfmpegEnc * HBFfmpegEncInit( HBHandle * handle, HBTitle * title )
+/* Local prototypes */
+static int FfmpegEncWork( HBWork * );
+static int InitAvcodec( HBFfmpegEnc * );
+static void CloseAvcodec( HBFfmpegEnc * );
+
+HBWork * HBFfmpegEncInit( HBHandle * handle, HBTitle * title )
{
HBFfmpegEnc * f;
- if( !( f = malloc( sizeof( HBFfmpegEnc ) ) ) )
+ if( !( f = calloc( sizeof( HBFfmpegEnc ), 1 ) ) )
{
HBLog( "HBFfmpegEncInit: malloc() failed, gonna crash" );
return NULL;
@@ -42,31 +44,32 @@ HBFfmpegEnc * HBFfmpegEncInit( HBHandle * handle, HBTitle * title )
f->work = FfmpegEncWork;
f->handle = handle;
- f->title = title;
-
- f->mpeg4Buffer = NULL;
- f->pass = 42;
- f->context = NULL;
- f->file = NULL;
+ f->title = title;
+ f->pass = 42;
- return f;
+ return (HBWork*) f;
}
-void HBFfmpegEncClose( HBFfmpegEnc ** _f )
+void HBFfmpegEncClose( HBWork ** _f )
{
- HBFfmpegEnc * f = *_f;
+ HBFfmpegEnc * f = (HBFfmpegEnc*) *_f;
if( f->context )
{
- HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)",
- f->pass );
+ CloseAvcodec( f );
+ }
- avcodec_close( f->context );
- if( f->file )
- {
- fclose( f->file );
- f->file = NULL;
- }
+ /* Stats */
+ if( f->frames )
+ {
+ float bitrate = (float) f->bytes * f->title->rate /
+ f->frames / f->title->rateBase / 128;
+ int64_t bytes = (int64_t) f->frames * f->title->bitrate * 128 *
+ f->title->rateBase / f->title->rate;
+
+ HBLog( "HBFfmpegEnc: %d frames encoded (%lld bytes), %.2f kbps",
+ f->frames, f->bytes, bitrate );
+ HBLog( "HBFfmpegEnc: error is %lld bytes", f->bytes - bytes );
}
free( f->name );
free( f );
@@ -87,7 +90,7 @@ static int FfmpegEncWork( HBWork * w )
if( f->mpeg4Buffer )
{
- if( HBFifoPush( title->mpeg4Fifo, &f->mpeg4Buffer ) )
+ if( HBFifoPush( title->outFifo, &f->mpeg4Buffer ) )
{
didSomething = 1;
}
@@ -109,94 +112,26 @@ static int FfmpegEncWork( HBWork * w )
/* 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;
- }
+ CloseAvcodec( f );
}
-
+
f->pass = scaledBuffer->pass;
-
- HBLog( "HBFfmpegEnc: opening libavcodec (pass %d)", f->pass );
- codec = avcodec_find_encoder( CODEC_ID_MPEG4 );
- if( !codec )
+
+ if( !InitAvcodec( f ) )
{
- 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 = 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;
@@ -204,9 +139,8 @@ static int FfmpegEncWork( HBWork * w )
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->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 */
@@ -220,11 +154,128 @@ static int FfmpegEncWork( HBWork * w )
}
HBBufferClose( &mpeg4Buffer );
}
+ else
+ {
+ f->mpeg4Buffer = mpeg4Buffer;
+
+ /* Stats */
+ f->frames++;
+ f->bytes += mpeg4Buffer->size;
+ }
HBBufferClose( &scaledBuffer );
free( frame );
- f->mpeg4Buffer = mpeg4Buffer;
-
return didSomething;
}
+
+static int InitAvcodec( HBFfmpegEnc * f )
+{
+ AVCodec * codec;
+ AVCodecContext * context;
+ HBTitle * title = f->title;
+
+ 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 0;
+ }
+
+ context = avcodec_alloc_context();
+ context->bit_rate = 1024 * title->bitrate;
+ context->bit_rate_tolerance = 10 * context->bit_rate;
+ 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( title->mux == HB_MUX_MP4 && f->pass != 1 )
+ {
+ context->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ }
+
+ 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;
+ }
+ }
+
+#ifdef HB_NOMMX
+ context->dct_algo = FF_DCT_INT;
+ context->idct_algo = FF_IDCT_INT;
+ context->dsp_mask = 0x1F;
+#endif
+
+ if( avcodec_open( context, codec ) < 0 )
+ {
+ HBLog( "HBFfmpegEnc: avcodec_open() failed" );
+ return 0;
+ }
+
+ if( title->mux == HB_MUX_MP4 && f->pass != 1 )
+ {
+ /* UGLY */
+ title->esConfig = malloc( 15 );
+ title->esConfigLength = 15;
+ memcpy( title->esConfig, context->extradata + 15, 15 );
+ }
+
+ f->context = context;
+ return 1;
+}
+
+static void CloseAvcodec( HBFfmpegEnc * f )
+{
+ HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)",
+ f->pass );
+
+ if( f->context->stats_in )
+ {
+ free( f->context->stats_in );
+ }
+ avcodec_close( f->context );
+ if( f->file )
+ {
+ fclose( f->file );
+ f->file = NULL;
+ }
+ if( f->title->esConfig )
+ {
+ free( f->title->esConfig );
+ f->title->esConfigLength = 0;
+ }
+}
+
diff --git a/core/FfmpegEnc.h b/core/FfmpegEnc.h
deleted file mode 100644
index 8ab622011..000000000
--- a/core/FfmpegEnc.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $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
index 74658d5d8..af6d90cfe 100644
--- a/core/Fifo.c
+++ b/core/Fifo.c
@@ -1,4 +1,4 @@
-/* $Id: Fifo.c,v 1.3 2003/11/09 14:27:56 titer Exp $
+/* $Id: Fifo.c,v 1.8 2004/01/16 19:04:03 titer Exp $
This file is part of the HandBrake source code.
Homepage: <http://handbrake.m0k.org/>.
@@ -9,7 +9,7 @@
HBBuffer * HBBufferInit( int size )
{
HBBuffer * b;
- if( !( b = malloc( sizeof( HBBuffer ) ) ) )
+ if( !( b = calloc( sizeof( HBBuffer ), 1 ) ) )
{
HBLog( "HBBufferInit: malloc() failed, gonna crash" );
return NULL;
@@ -26,11 +26,6 @@ HBBuffer * HBBufferInit( int size )
}
b->position = 0.0;
- b->streamId = 0;
- b->keyFrame = 0;
- b->pts = 0;
- b->pass = 0;
- b->last = 0;
return b;
}
@@ -49,7 +44,7 @@ void HBBufferReAlloc( HBBuffer * b, int size )
void HBBufferClose( HBBuffer ** _b )
{
HBBuffer * b = *_b;
-
+
free( b->data );
free( b );
@@ -65,6 +60,7 @@ HBFifo * HBFifoInit( int capacity )
return NULL;
}
+ f->die = 0;
f->capacity = capacity;
f->whereToPush = 0;
f->whereToPop = 0;
@@ -75,22 +71,23 @@ HBFifo * HBFifoInit( int capacity )
free( f );
return NULL;
}
-
+
f->lock = HBLockInit();
+ f->cond = HBCondInit();
return f;
}
-int HBFifoSize( HBFifo * f )
+void HBFifoDie( HBFifo * f )
{
- return ( f->capacity + 1 + f->whereToPush - f->whereToPop ) %
- ( f->capacity + 1 );
+ f->die = 1;
+ HBCondSignal( f->cond );
}
void HBFifoClose( HBFifo ** _f )
{
HBFifo * f = (*_f);
-
+
HBLog( "HBFifoClose: trashing %d buffer%s",
HBFifoSize( f ), ( HBFifoSize( f ) > 1 ) ? "s" : "" );
@@ -102,6 +99,7 @@ void HBFifoClose( HBFifo ** _f )
}
HBLockClose( &f->lock );
+ HBCondClose( &f->cond );
free( f->buffers );
free( f );
diff --git a/core/Fifo.h b/core/Fifo.h
index 758125ebd..d9240fb25 100644
--- a/core/Fifo.h
+++ b/core/Fifo.h
@@ -1,4 +1,4 @@
-/* $Id: Fifo.h,v 1.3 2003/11/06 13:07:52 titer Exp $
+/* $Id: Fifo.h,v 1.10 2004/01/16 19:04:04 titer Exp $
This file is part of the HandBrake source code.
Homepage: <http://handbrake.m0k.org/>.
@@ -12,16 +12,27 @@
struct HBBuffer
{
+ /* Members used everywhere */
int alloc;
int size;
uint8_t * data;
-
float position;
+ int pass;
+
+ /* Only used for PStoES */
int streamId;
- int keyFrame;
uint64_t pts;
- int pass;
- int last;
+
+ /* NTSC suxx */
+ int repeat;
+
+ /* Only used for raw audio buffers */
+ int samples; /* Number of samples for each track */
+ float * left;
+ float * right;
+
+ /* Only used for MPEG-4, MP3 and AAC buffers */
+ int keyFrame;
};
HBBuffer * HBBufferInit( int size );
@@ -30,24 +41,40 @@ void HBBufferClose( HBBuffer ** );
struct HBFifo
{
+ int die;
int capacity;
int whereToPush;
int whereToPop;
HBBuffer ** buffers;
HBLock * lock;
+ HBCond * cond;
};
HBFifo * HBFifoInit( int capacity );
-int HBFifoSize( HBFifo * );
+static inline int HBFifoSize( HBFifo * );
static inline int HBFifoPush( HBFifo *, HBBuffer ** );
static inline HBBuffer * HBFifoPop( HBFifo * );
+static inline int HBFifoWait( HBFifo * );
+static inline float HBFifoPosition( HBFifo * );
+void HBFifoDie( HBFifo * );
void HBFifoClose( HBFifo ** );
-static inline int HBFifoPush( HBFifo * f, HBBuffer ** b )
+static inline int HBFifoSize( HBFifo * f )
{
+ int size;
HBLockLock( f->lock );
+ size = ( f->capacity + 1 + f->whereToPush - f->whereToPop ) %
+ ( f->capacity + 1 );
+ HBLockUnlock( f->lock );
+ return size;
+}
- if( HBFifoSize( f ) < f->capacity )
+static inline int HBFifoPush( HBFifo * f, HBBuffer ** b )
+{
+ HBLockLock( f->lock );
+ HBCondSignal( f->cond );
+ if( ( f->capacity + 1 + f->whereToPush - f->whereToPop ) %
+ ( f->capacity + 1 ) != f->capacity )
{
f->buffers[f->whereToPush] = *b;
f->whereToPush++;
@@ -56,7 +83,6 @@ static inline int HBFifoPush( HBFifo * f, HBBuffer ** b )
*b = NULL;
return 1;
}
-
HBLockUnlock( f->lock );
return 0;
}
@@ -64,7 +90,6 @@ static inline int HBFifoPush( HBFifo * f, HBBuffer ** b )
static inline HBBuffer * HBFifoPop( HBFifo * f )
{
HBLockLock( f->lock );
-
if( f->whereToPush != f->whereToPop )
{
HBBuffer * b = f->buffers[f->whereToPop];
@@ -73,9 +98,47 @@ static inline HBBuffer * HBFifoPop( HBFifo * f )
HBLockUnlock( f->lock );
return b;
}
-
HBLockUnlock( f->lock );
return NULL;
}
+static inline int HBFifoWait( HBFifo * f )
+{
+ HBLockLock( f->lock );
+ if( f->whereToPush != f->whereToPop )
+ {
+ HBLockUnlock( f->lock );
+ return 1;
+ }
+ if( f->die )
+ {
+ HBLockUnlock( f->lock );
+ return 0;
+ }
+ HBCondWait( f->cond, f->lock );
+ if( f->whereToPush != f->whereToPop )
+ {
+ HBLockUnlock( f->lock );
+ return 1;
+ }
+ HBLockUnlock( f->lock );
+ return 0;
+}
+
+static inline float HBFifoPosition( HBFifo * f )
+{
+ float pos;
+ HBLockLock( f->lock );
+ if( f->whereToPush != f->whereToPop )
+ {
+ pos = f->buffers[f->whereToPop]->position;
+ }
+ else
+ {
+ pos = 0.0;
+ }
+ HBLockUnlock( f->lock );
+ return pos;
+}
+
#endif
diff --git a/core/HBInternal.h b/core/HBInternal.h
new file mode 100644
index 000000000..169451980
--- /dev/null
+++ b/core/HBInternal.h
@@ -0,0 +1,81 @@
+/* $Id: HBInternal.h,v 1.4 2004/01/16 20:55:21 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_INTERNAL_H
+#define HB_INTERNAL_H
+
+#include "HandBrake.h"
+#include "Fifo.h"
+#include "Thread.h"
+#include "Work.h"
+
+/* Demuxer */
+HBDVDRead * HBDVDReadInit( HBHandle *, HBTitle * );
+void HBDVDReadClose( HBDVDRead ** );
+
+/* Decoders */
+HBWork * HBMpeg2DecInit( HBHandle *, HBTitle * );
+void HBMpeg2DecClose( HBWork ** );
+HBWork * HBAc3DecInit( HBHandle *, HBAudio * );
+void HBAc3DecClose( HBWork ** );
+HBWork * HBMadDecInit( HBHandle *, HBAudio * );
+void HBMadDecClose( HBWork ** );
+
+/* Scaler */
+HBWork * HBScaleInit( HBHandle *, HBTitle * );
+void HBScaleClose( HBWork ** );
+
+/* Encoders */
+HBWork * HBFfmpegEncInit( HBHandle *, HBTitle * );
+void HBFfmpegEncClose( HBWork ** );
+HBWork * HBXvidEncInit( HBHandle *, HBTitle * );
+void HBXvidEncClose( HBWork ** );
+HBWork * HBX264EncInit( HBHandle *, HBTitle * );
+void HBX264EncClose( HBWork ** );
+HBWork * HBMp3EncInit( HBHandle *, HBAudio * );
+void HBMp3EncClose( HBWork ** );
+HBWork * HBFaacEncInit( HBHandle *, HBAudio * );
+void HBFaacEncClose( HBWork ** );
+HBWork * HBVorbisEncInit ( HBHandle *, HBAudio * );
+void HBVorbisEncClose( HBWork ** );
+
+/* Muxers */
+HBAviMux * HBAviMuxInit( HBHandle *, HBTitle * );
+void HBAviMuxClose( HBAviMux ** );
+HBMp4Mux * HBMp4MuxInit( HBHandle *, HBTitle * );
+void HBMp4MuxClose( HBMp4Mux ** );
+HBOgmMux * HBOgmMuxInit( HBHandle *, HBTitle * );
+void HBOgmMuxClose( HBOgmMux ** );
+
+/* Scanner */
+HBScan * HBScanInit( HBHandle *, const char * device, int title );
+void HBScanClose( HBScan ** );
+
+/* Called by HBScan to tell the GUI how far we've been */
+void HBScanning( HBHandle *, int title, int titleCount );
+
+/* 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 until the rip is resumed
+ otherwise */
+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 asks to stop */
+void HBErrorOccured( HBHandle *, int error );
+
+#endif
diff --git a/core/HandBrake.c b/core/HandBrake.c
index c76a27b3c..010f1a3cf 100644
--- a/core/HandBrake.c
+++ b/core/HandBrake.c
@@ -1,25 +1,13 @@
-/* $Id: HandBrake.c,v 1.18 2003/11/13 01:17:33 titer Exp $
+/* $Id: HandBrake.c,v 1.42 2004/02/18 17:07:20 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 "HBInternal.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"
+/* libavcodec */
+#include "ffmpeg/avcodec.h"
/* Local prototypes */
static void HandBrakeThread( void * );
@@ -29,39 +17,37 @@ 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;
+ int cpuCount;
+ HBCallbacks cb;
+
+ int stopScan;
+ int stopRip;
+ int ripDone;
+ int error;
+
+ HBScan * scan;
+ HBList * titleList;
+ HBTitle * curTitle;
+ uint64_t beginDate;
+ uint64_t pauseDate;
+ uint64_t lastPosUpdate;
+ uint64_t lastFpsUpdate;
+ int framesSinceBegin;
+ int framesSinceFps;
+ float curFrameRate;
+ float avgFrameRate;
+ int remainingTime;
+
+ HBLock * pauseLock;
+ volatile int die;
+ HBThread * thread;
+ int pid;
};
HBHandle * HBInit( int debug, int cpuCount )
{
HBHandle * h;
- if( !( h = malloc( sizeof( HBHandle ) ) ) )
+ if( !( h = calloc( sizeof( HBHandle ), 1 ) ) )
{
HBLog( "HBInit: malloc() failed, gonna crash" );
return NULL;
@@ -105,190 +91,105 @@ HBHandle * HBInit( int debug, int cpuCount )
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->status.titleList = NULL;
- h->curTitle = NULL;
- h->curAudio = NULL;
- h->curOptAudio = NULL;
h->pauseLock = HBLockInit();
-
- h->die = 0;
- h->thread = HBThreadInit( "libhb", HandBrakeThread, h,
- HB_NORMAL_PRIORITY );
-
+ h->thread = HBThreadInit( "libhb", HandBrakeThread, h,
+ HB_NORMAL_PRIORITY );
return h;
}
-int HBGetStatus( HBHandle * h, HBStatus * status )
+void HBSetCallbacks( HBHandle * h, HBCallbacks callbacks )
{
- 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;
+ h->cb = callbacks;
}
-void HBScanDevice( HBHandle * h, char * device, int title )
+void HBScanDVD( HBHandle * h, const char * dvd, 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 );
+ h->scan = HBScanInit( h, dvd, title );
}
-void HBStartRip( HBHandle * h, HBTitle * t,
- HBAudio * a1, HBAudio * a2 )
+void HBStartRip( HBHandle * h, HBTitle * title )
{
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;
+ HBAudio * audio;
+
+ h->beginDate = HBGetDate();
+ h->lastPosUpdate = 0;
+ h->lastFpsUpdate = 0;
+ h->framesSinceBegin = 0;
+ h->framesSinceFps = 0;
+
+ FixPictureSettings( title );
+
+ /* Video fifos */
+ title->inFifo = HBFifoInit( 1024 );
+ title->rawFifo = HBFifoInit( 1 );
+ title->scaledFifo = HBFifoInit( 1 );
+ title->outFifo = HBFifoInit( 1 );
+
+ /* Video work objects */
+ title->decoder = HBMpeg2DecInit( h, title );
+ title->scale = HBScaleInit( h, title );
+ if( title->codec == HB_CODEC_FFMPEG )
+ title->encoder = HBFfmpegEncInit( h, title );
+ else if( title->codec == HB_CODEC_XVID )
+ title->encoder = HBXvidEncInit( h, title );
+ else if( title->codec == HB_CODEC_X264 )
+ title->encoder = HBX264EncInit( h, title );
+
+ for( i = 0; i < HBListCount( title->ripAudioList ); i++ )
+ {
+ audio = HBListItemAt( title->ripAudioList, i );
+
+ /* Audio fifos */
+ audio->inFifo = HBFifoInit( 1024 );
+ audio->rawFifo = HBFifoInit( 1 );
+ audio->outFifo = HBFifoInit( 4 ); /* At least 4 for Vorbis */
+
+ /* Audio work objects */
+ audio->decoder = HBAc3DecInit( h, audio );
+ if( audio->codec == HB_CODEC_MP3 )
+ audio->encoder = HBMp3EncInit( h, audio );
+ else if( audio->codec == HB_CODEC_AAC )
+ audio->encoder = HBFaacEncInit( h, audio );
+ else if( audio->codec == HB_CODEC_VORBIS )
+ audio->encoder = HBVorbisEncInit( h, audio );
}
- 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 threads */
+ title->dvdRead = HBDVDReadInit( h, title );
- /* Create fifos */
- t->mpeg2Fifo = HBFifoInit( 1024 );
- t->rawFifo = HBFifoInit( 1 );
- t->scaledFifo = HBFifoInit( 1 );
- t->mpeg4Fifo = HBFifoInit( 1 );
- a1->ac3Fifo = HBFifoInit( 1024 );
- a1->rawFifo = HBFifoInit( 1 );
- a1->mp3Fifo = HBFifoInit( 1 );
- if( a2 )
- {
- a2->ac3Fifo = HBFifoInit( 1024 );
- a2->rawFifo = HBFifoInit( 1 );
- a2->mp3Fifo = HBFifoInit( 1 );
- }
+ if( title->mux == HB_MUX_AVI )
+ title->aviMux = HBAviMuxInit( h, title );
+ else if( title->mux == HB_MUX_MP4 )
+ title->mp4Mux = HBMp4MuxInit( h, title );
+ else if( title->mux == HB_MUX_OGM )
+ title->ogmMux = HBOgmMuxInit( h, title );
- /* 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 );
+ title->workThreads[i] = HBWorkThreadInit( h, title, i ? 0 : 1 );
}
- h->curTitle = t;
- h->curAudio = a1;
- h->curOptAudio = a2;
+ h->curTitle = title;
}
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->lastPosUpdate += 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;
}
@@ -314,7 +215,7 @@ uint8_t * HBGetPreview( HBHandle * h, HBTitle * t, int picture )
HBLog( "HBGetPreview: malloc() failed, gonna crash" );
return NULL;
}
-
+
/* Original YUV picture */
avpicture_fill( &pic1, buf1, PIX_FMT_YUV420P, t->inWidth,
t->inHeight );
@@ -393,7 +294,7 @@ uint8_t * HBGetPreview( HBHandle * h, HBTitle * t, int picture )
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 );
@@ -415,48 +316,90 @@ uint8_t * HBGetPreview( HBHandle * h, HBTitle * t, int picture )
return NULL;
}
+int HBGetBitrateForSize( HBTitle * title, int size, int muxer,
+ int audioCount, int audioBitrate )
+{
+ int64_t available;
+ int overheadPerFrame;
+ int sampleRate;
+ int samplesPerFrame;
+
+ switch( muxer )
+ {
+ case HB_MUX_MP4:
+ overheadPerFrame = 5; /* hopefully */
+ sampleRate = 48000; /* No resampling */
+ samplesPerFrame = 1024; /* AAC */
+ break;
+ case HB_MUX_AVI:
+ overheadPerFrame = 24;
+ sampleRate = 44100; /* Resampling */
+ samplesPerFrame = 1152; /* MP3 */
+ break;
+ case HB_MUX_OGM:
+ overheadPerFrame = 0; /* XXX */
+ sampleRate = 48000; /* No resampling */
+ samplesPerFrame = 1024; /* Vorbis */
+ break;
+ default:
+ return 0;
+ }
+
+ /* Actually target 1 MB less */
+ available = (int64_t) ( size - 1 ) * 1024 * 1024;
+
+ /* Audio data */
+ available -= audioCount * title->length * audioBitrate * 128;
+
+ /* Video headers */
+ available -= (int64_t) title->length * title->rate *
+ overheadPerFrame / title->rateBase;
+
+ /* Audio headers */
+ available -= (int64_t) audioCount * title->length * sampleRate *
+ overheadPerFrame / samplesPerFrame;
+
+ if( available < 0 )
+ {
+ return 0;
+ }
+ return( available / ( 128 * title->length ) );
+}
+
void HBClose( HBHandle ** _h )
{
char command[1024];
-
+
HBHandle * h = *_h;
-
+
h->die = 1;
HBThreadClose( &h->thread );
- if( h->status.mode == HB_MODE_SCANNING )
+ if( h->scan )
{
HBScanClose( &h->scan );
}
- else if( h->status.mode == HB_MODE_PAUSED )
+ if( h->curTitle )
{
- HBLockUnlock( h->pauseLock );
_StopRip( h );
}
- else if( h->status.mode == HB_MODE_ENCODING )
+ if( h->titleList )
{
- _StopRip( h );
+ HBTitle * title;
+ while( ( title = (HBTitle*) HBListItemAt( h->titleList, 0 ) ) )
+ {
+ HBListRemove( h->titleList, title );
+ HBTitleClose( &title );
+ }
}
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;
}
@@ -467,17 +410,16 @@ void HBCheckPaused( HBHandle * h )
HBLockUnlock( h->pauseLock );
}
-void HBScanning( HBHandle * h, int title )
+void HBScanning( HBHandle * h, int title, int titleCount )
{
- HBLockLock( h->lock );
- h->status.scannedTitle = title;
- HBLockUnlock( h->lock );
+ h->cb.scanning( h->cb.data, title, titleCount );
}
void HBScanDone( HBHandle * h, HBList * titleList )
{
- h->status.titleList = titleList;
- h->stopScan = 1;
+ h->stopScan = 1;
+ h->titleList = titleList;
+ h->cb.scanDone( h->cb.data, titleList );
}
int HBGetPid( HBHandle * h )
@@ -492,59 +434,47 @@ void HBDone( HBHandle * h )
void HBPosition( HBHandle * h, float position )
{
- if( !h->frames )
- {
- h->beginDate = HBGetDate();
- h->lastFpsUpdate = h->beginDate;
- }
-
- h->frames++;
- h->framesSinceFpsUpdate++;
-
- HBLockLock( h->lock );
- h->status.position = position;
+ int pass, passCount;
+
+ h->framesSinceBegin++;
+ h->framesSinceFps++;
+
if( h->curTitle->twoPass )
{
- h->status.pass = ( position < 0.5 ) ? 1 : 2;
+ pass = ( position < 0.5 ) ? 1 : 2;
+ passCount = 2;
}
else
{
- h->status.pass = 1;
+ passCount = pass = 1;
}
+ if( HBGetDate() - h->lastPosUpdate < 200000 )
+ return;
+
+ h->lastPosUpdate = HBGetDate();
+
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( "Progress: %.2f %%", position * 100 );
- 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;
+ h->curFrameRate = 1000000.0 * h->framesSinceFps /
+ ( HBGetDate() - h->lastFpsUpdate );
+ h->avgFrameRate = 1000000.0 * h->framesSinceBegin /
+ ( HBGetDate() - h->beginDate );
+ h->remainingTime = ( 1.0 - position ) *
+ ( HBGetDate() - h->beginDate ) / position / 1000000;
+
+ h->lastFpsUpdate = HBGetDate();
+ h->framesSinceFps = 0;
}
- HBLockUnlock( h->lock );
+
+ h->cb.encoding( h->cb.data, position, pass, passCount,
+ h->curFrameRate, h->avgFrameRate,
+ h->remainingTime );
}
-void HBErrorOccured( HBHandle * h, HBError error )
+void HBErrorOccured( HBHandle * h, int error )
{
- if( !( h->status.mode & ( HB_MODE_ENCODING | HB_MODE_PAUSED ) ) )
- {
- return;
- }
-
- h->status.error = error;
- h->error = 1;
+ h->error = error;
}
/* Local functions */
@@ -559,49 +489,55 @@ static void HandBrakeThread( void * _h )
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->cb.ripDone( h->cb.data, HB_CANCELED );
h->stopRip = 0;
}
if( h->ripDone )
{
- /* Wait a bit */
- HBSnooze( 500000 );
+ HBTitle * title = h->curTitle;
+ HBAudio * audio;
+ int i, ok = 0;
+
+ /* Wait until we're done with the decoding of one track */
+ for( ;; )
+ {
+ if( !HBFifoSize( title->inFifo ) &&
+ !HBFifoSize( title->rawFifo ) &&
+ !HBFifoSize( title->scaledFifo ) )
+ {
+ break;
+ }
+ for( i = 0; i < HBListCount( title->ripAudioList ); i++ )
+ {
+ audio = (HBAudio*) HBListItemAt( title->ripAudioList, i );
+ if( !HBFifoSize( title->inFifo ) &&
+ !HBFifoSize( title->rawFifo ) )
+ {
+ ok = 1;
+ break;
+ }
+ }
+ HBSnooze( 5000 );
+ }
+ HBSnooze( 500000 );
_StopRip( h );
- HBLockLock( h->lock );
- h->modeChanged = 1;
- h->status.mode = HB_MODE_DONE;
- HBLockUnlock( h->lock );
-
+ h->cb.ripDone( h->cb.data, HB_SUCCESS );
+
h->ripDone = 0;
}
if( h->error )
{
_StopRip( h );
-
- HBLockLock( h->lock );
- h->modeChanged = 1;
- h->status.mode = HB_MODE_ERROR;
- HBLockUnlock( h->lock );
-
+ h->cb.ripDone( h->cb.data, h->error );
h->error = 0;
}
@@ -611,52 +547,77 @@ static void HandBrakeThread( void * _h )
static void _StopRip( HBHandle * h )
{
+ HBTitle * title = h->curTitle;
+ HBAudio * audio;
int i;
+ /* Invalidate fifos */
+ HBFifoDie( title->outFifo );
+ for( i = 0; i < HBListCount( title->ripAudioList ); i++ )
+ {
+ audio = HBListItemAt( title->ripAudioList, i );
+ HBFifoDie( audio->outFifo );
+ }
+
/* Stop threads */
- HBDVDReadClose( &h->curTitle->dvdRead );
- HBAviMuxClose( &h->curTitle->aviMux );
+ HBDVDReadClose( &title->dvdRead );
+
+ if( title->mux == HB_MUX_AVI )
+ HBAviMuxClose( &title->aviMux );
+ else if( title->mux == HB_MUX_MP4 )
+ HBMp4MuxClose( &title->mp4Mux );
+ else if( title->mux == HB_MUX_OGM )
+ HBOgmMuxClose( &title->ogmMux );
+
for( i = 0; i < h->cpuCount; i++ )
{
- HBWorkThreadClose( &h->curTitle->workThreads[h->cpuCount-i-1] );
+ HBWorkThreadClose( &title->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 );
- }
+ HBMpeg2DecClose( &title->decoder );
+ HBScaleClose( &title->scale );
- /* 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 )
+ if( title->codec == HB_CODEC_FFMPEG )
+ HBFfmpegEncClose( &title->encoder );
+ else if( title->codec == HB_CODEC_XVID )
+ HBXvidEncClose( &title->encoder );
+ else if( title->codec == HB_CODEC_X264 )
+ HBX264EncClose( &title->encoder );
+
+ HBFifoClose( &title->inFifo );
+ HBFifoClose( &title->rawFifo );
+ HBFifoClose( &title->scaledFifo );
+ HBFifoClose( &title->outFifo );
+
+ for( i = 0; i < HBListCount( title->ripAudioList ); i++ )
{
- HBFifoClose( &h->curOptAudio->ac3Fifo );
- HBFifoClose( &h->curOptAudio->rawFifo );
- HBFifoClose( &h->curOptAudio->mp3Fifo );
+ audio = HBListItemAt( title->ripAudioList, i );
+
+ /* Audio work objects */
+ HBAc3DecClose( &audio->decoder );
+ if( audio->codec == HB_CODEC_MP3 )
+ HBMp3EncClose( &audio->encoder );
+ else if( audio->codec == HB_CODEC_AAC )
+ HBFaacEncClose( &audio->encoder );
+ else if( audio->codec == HB_CODEC_VORBIS )
+ HBVorbisEncClose( &audio->encoder );
+
+ /* Audio fifos */
+ HBFifoClose( &audio->inFifo );
+ HBFifoClose( &audio->rawFifo );
+ HBFifoClose( &audio->outFifo );
+
+ HBListRemove( title->ripAudioList, audio );
}
+
+ h->curTitle = NULL;
}
static void FixPictureSettings( HBTitle * t )
{
/* Sanity checks */
+ t->outWidth = MULTIPLE_16( t->outWidth );
t->topCrop = EVEN( t->topCrop );
t->bottomCrop = EVEN( t->bottomCrop );
t->leftCrop = EVEN( t->leftCrop );
@@ -693,12 +654,12 @@ static int GetCPUCount()
{
int CPUCount = 1;
-#if defined( SYS_BEOS )
+#if defined( HB_BEOS )
system_info info;
get_system_info( &info );
CPUCount = info.cpu_count;
-#elif defined( SYS_MACOSX )
+#elif defined( HB_MACOSX )
FILE * info;
char buffer[256];
@@ -726,8 +687,8 @@ static int GetCPUCount()
{
HBLog( "GetCPUCount: popen() failed" );
}
-
-#elif defined( SYS_LINUX )
+
+#elif defined( HB_LINUX )
FILE * info;
char buffer[256];
@@ -755,11 +716,11 @@ static int GetCPUCount()
{
HBLog( "GetCPUCount: fopen() failed" );
}
-
-#elif defined( SYS_CYGWIN )
+
+#elif defined( HB_CYGWIN )
/* TODO */
CPUCount = 1;
-
+
#endif
CPUCount = MAX( 1, CPUCount );
CPUCount = MIN( CPUCount, 8 );
diff --git a/core/HandBrake.h b/core/HandBrake.h
index 35ec0fc0a..9d84d39dc 100644
--- a/core/HandBrake.h
+++ b/core/HandBrake.h
@@ -1,4 +1,4 @@
-/* $Id: HandBrake.h,v 1.3 2003/11/06 13:03:19 titer Exp $
+/* $Id: HandBrake.h,v 1.10 2004/01/21 18:40:36 titer Exp $
This file is part of the HandBrake source code.
Homepage: <http://handbrake.m0k.org/>.
@@ -13,36 +13,56 @@ extern "C" {
#include "Utils.h"
+/* Interface callbacks */
+typedef struct HBCallbacks
+{
+ void * data;
+
+ void (*scanning) ( void * data, int title, int titleCount );
+ void (*scanDone) ( void * data, HBList * titleList );
+ void (*encoding) ( void * data, float position, int pass,
+ int passCount, float curFrameRate,
+ float avgFrameRate, int remainingTime );
+ void (*ripDone) ( void * data, int result );
+
+} HBCallbacks;
+
/* 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 * );
+/* Tell libhb what functions should be called when a GUI should be
+ updated. */
+void HBSetCallbacks( HBHandle *, HBCallbacks callbacks );
-/* Launch a thread which scans the specified device and title. Use
+/* Launch a thread which scans the specified DVD and title. Use
title = 0 to scan all titles. Returns immediately */
-void HBScanDevice( HBHandle *, char * device, int title );
+void HBScanDVD( HBHandle *, const char * dvd, int title );
+
+/* Calculate bitrate so the output file fits in X MB */
+int HBGetBitrateForSize( HBTitle * title, int size, int muxer,
+ int audioCount, int audioBitrate );
-/* Start ripping the specified title with specified audio tracks.
- Returns immediatly */
-void HBStartRip( HBHandle *, HBTitle *, HBAudio *, HBAudio * );
+/* Start ripping the specified title. Returns immediatly */
+void HBStartRip( HBHandle *, HBTitle * );
-/* Suspend rip. Returns immediatly */
+/* Suspend rip */
void HBPauseRip( HBHandle * );
-/* Resume rip. Returns immediatly */
+/* Resume rip */
void HBResumeRip( HBHandle * );
-/* Cancel rip. Returns immediatly */
+/* Cancel rip. Returns immediatly - you'll be noticed by the ripDone
+ callback when it's really stopped.
+ If the rip was paused, you _must_ call HBResumeRip() first. */
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 ) */
+ pointer to raw RGBA data that _has_ to be freed by the calling
+ function. The picture includes the white border around the picture,
+ so its size is ( maxWidth + 2 ) x ( maxHeight + 2 ).
+ The data belongs to the caller, who must free it. */
uint8_t * HBGetPreview( HBHandle *, HBTitle *, int picture );
/* Clean up things */
diff --git a/core/HandBrakeInternal.h b/core/HandBrakeInternal.h
deleted file mode 100644
index 7c10512c9..000000000
--- a/core/HandBrakeInternal.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* $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/Jamfile b/core/Jamfile
new file mode 100644
index 000000000..d33688722
--- /dev/null
+++ b/core/Jamfile
@@ -0,0 +1,47 @@
+# $Id: Jamfile,v 1.5 2004/01/16 19:04:04 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.
+
+SubDir TOP core ;
+
+SOURCES_HBCORE =
+Ac3Dec.c
+AviMux.c
+DVDRead.c
+FaacEnc.c
+FfmpegEnc.c
+Fifo.c
+HandBrake.c
+MadDec.c
+Mp3Enc.c
+Mp4Mux.c
+Mpeg2Dec.c
+OgmMux.c
+Scale.c
+Scan.c
+Thread.c
+Utils.c
+VorbisEnc.c
+Work.c
+X264Enc.c
+XvidEnc.c ;
+
+ObjectCcFlags $(SOURCES_HBCORE) :
+ -I$(TOP)/contrib/liba52
+ -I$(TOP)/contrib/libavcodec
+ -I$(TOP)/contrib/libdvdplay
+ -I$(TOP)/contrib/libdvdread
+ -I$(TOP)/contrib/libfaac
+ -I$(TOP)/contrib/libmp3lame
+ -I$(TOP)/contrib/libmp4v2
+ -I$(TOP)/contrib/libmpeg2
+ -I$(TOP)/contrib/libogg
+ -I$(TOP)/contrib/libvorbis
+ -I$(TOP)/contrib/libx264
+ -I$(TOP)/contrib/libxvidcore
+ -g -Wall ;
+
+Library libhb.a : $(SOURCES_HBCORE) ;
+
diff --git a/core/MadDec.c b/core/MadDec.c
index deecfeebd..da79ad886 100644
--- a/core/MadDec.c
+++ b/core/MadDec.c
@@ -1,9 +1,8 @@
-/* $Id: MadDec.c,v 1.1 2003/11/03 12:08:01 titer Exp $
+/* $Id: MadDec.c,v 1.2 2003/12/26 20:03:27 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"
+#include "HBInternal.h"
diff --git a/core/MadDec.h b/core/MadDec.h
deleted file mode 100644
index b1624338f..000000000
--- a/core/MadDec.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $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/Mp3Enc.c b/core/Mp3Enc.c
index 70693467f..bd62df4ae 100644
--- a/core/Mp3Enc.c
+++ b/core/Mp3Enc.c
@@ -1,20 +1,15 @@
-/* $Id: Mp3Enc.c,v 1.5 2003/11/07 21:52:57 titer Exp $
+/* $Id: Mp3Enc.c,v 1.13 2004/01/21 17:59:33 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 "HBInternal.h"
-#include <lame/lame.h>
+/* libmp3lame */
+#include "lame/lame.h"
-/* Local prototypes */
-static int Mp3EncWork( HBWork * );
-static int GetBytes( HBMp3Enc * );
-
-struct HBMp3Enc
+typedef struct HBMp3Enc
{
HB_WORK_COMMON_MEMBERS
@@ -24,17 +19,25 @@ struct HBMp3Enc
HBBuffer * rawBuffer;
int rawBufferPos;
float position;
- int samplesNeeded;
+ int inputSamples;
int samplesGot;
float * left;
float * right;
HBBuffer * mp3Buffer;
-};
-HBMp3Enc * HBMp3EncInit( HBHandle * handle, HBAudio * audio )
+ /* Stats */
+ int64_t samples;
+ int64_t bytes;
+} HBMp3Enc;
+
+/* Local prototypes */
+static int Mp3EncWork( HBWork * );
+static int GetSamples( HBMp3Enc * );
+
+HBWork * HBMp3EncInit( HBHandle * handle, HBAudio * audio )
{
HBMp3Enc * m;
- if( !( m = malloc( sizeof( HBMp3Enc ) ) ) )
+ if( !( m = calloc( sizeof( HBMp3Enc ), 1 ) ) )
{
HBLog( "HBMp3EncInit: malloc() failed, gonna crash" );
return NULL;
@@ -42,31 +45,35 @@ HBMp3Enc * HBMp3EncInit( HBHandle * handle, HBAudio * audio )
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;
+
+ return (HBWork*) m;
}
-void HBMp3EncClose( HBMp3Enc ** _m )
+void HBMp3EncClose( HBWork ** _m )
{
- HBMp3Enc * m = *_m;
-
+ HBMp3Enc * m = (HBMp3Enc*) *_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 );
+
+ if( m->samples )
+ {
+ int64_t bytes = 128 * m->audio->outBitrate * m->samples /
+ m->audio->inSampleRate;
+ float bitrate = (float) m->bytes * m->audio->inSampleRate /
+ m->samples / 128;
+
+ HBLog( "HBMp3Enc: %lld samples encoded (%lld bytes), %.2f kbps",
+ m->samples, m->bytes, bitrate );
+ HBLog( "HBFaacEnc: error is %lld bytes", m->bytes - bytes );
+ }
+
free( m->name );
free( m );
@@ -86,7 +93,7 @@ static int Mp3EncWork( HBWork * w )
if( !m->globalFlags )
{
int i;
-
+
/* Get a first buffer so we know that audio->inSampleRate is
correct */
if( ( m->rawBuffer = HBFifoPop( audio->rawFifo ) ) )
@@ -105,7 +112,8 @@ static int Mp3EncWork( HBWork * w )
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 = 44100;
+ m->inputSamples = 1152 * audio->inSampleRate /
audio->outSampleRate / 2;
HBLog( "HBMp3Enc: opening lame (%d->%d Hz, %d kbps)",
@@ -123,15 +131,15 @@ static int Mp3EncWork( HBWork * w )
return didSomething;
}
- m->left = malloc( m->samplesNeeded * sizeof( float ) );
- m->right = malloc( m->samplesNeeded * sizeof( float ) );
+ m->left = malloc( m->inputSamples * sizeof( float ) );
+ m->right = malloc( m->inputSamples * sizeof( float ) );
if( !m->left || !m->right )
{
HBLog( "HBMp3Enc: malloc() failed, gonna crash" );
}
- for( i = 0; i < m->samplesNeeded; i++ )
+ for( i = 0; i < m->inputSamples; i++ )
{
m->left[i] = 0.0;
m->right[i] = 0.0;
@@ -141,7 +149,7 @@ static int Mp3EncWork( HBWork * w )
/* Push encoded buffer */
if( m->mp3Buffer )
{
- if( HBFifoPush( audio->mp3Fifo, &m->mp3Buffer ) )
+ if( HBFifoPush( audio->outFifo, &m->mp3Buffer ) )
{
didSomething = 1;
}
@@ -156,12 +164,12 @@ static int Mp3EncWork( HBWork * w )
if( audio->delay > 0 )
{
/* Audio starts later - insert some silence */
- int length = m->samplesNeeded * 1000 / audio->inSampleRate;
-
+ int length = m->inputSamples * 1000 / audio->inSampleRate;
+
if( audio->delay > length )
{
HBLog( "HBMp3Enc: adding %d ms of silence", length );
- m->samplesGot = m->samplesNeeded;
+ m->samplesGot = m->inputSamples;
audio->delay -= length;
}
else
@@ -172,11 +180,11 @@ static int Mp3EncWork( HBWork * w )
else if( audio->delay < 0 )
{
/* Audio starts sooner - trash some */
- int length = m->samplesNeeded * 1000 / audio->inSampleRate;
+ int length = m->inputSamples * 1000 / audio->inSampleRate;
if( - audio->delay > length )
{
- if( GetBytes( m ) )
+ if( GetSamples( m ) )
{
didSomething = 1;
HBLog( "HBMp3Enc: trashing %d ms", length );
@@ -196,7 +204,7 @@ static int Mp3EncWork( HBWork * w )
}
/* Get new samples */
- if( GetBytes( m ) )
+ if( GetSamples( m ) )
{
didSomething = 1;
}
@@ -209,9 +217,11 @@ static int Mp3EncWork( HBWork * w )
mp3Buffer = HBBufferInit( LAME_MAXMP3BUFFER );
ret = lame_encode_buffer_float( m->globalFlags, m->left,
- m->right, m->samplesNeeded,
+ m->right, m->inputSamples,
mp3Buffer->data,
mp3Buffer->size );
+ /* Stats */
+ m->samples += m->inputSamples;
if( ret < 0 )
{
@@ -232,19 +242,21 @@ static int Mp3EncWork( HBWork * w )
mp3Buffer->size = ret;
mp3Buffer->keyFrame = 1;
mp3Buffer->position = m->position;
-
m->mp3Buffer = mp3Buffer;
+
+ /* Stats */
+ m->bytes += ret;
}
return didSomething;
}
-static int GetBytes( HBMp3Enc * m )
+static int GetSamples( HBMp3Enc * m )
{
- while( m->samplesGot < m->samplesNeeded )
+ while( m->samplesGot < m->inputSamples )
{
int i;
-
+
if( !m->rawBuffer )
{
if( !( m->rawBuffer = HBFifoPop( m->audio->rawFifo ) ) )
@@ -256,22 +268,20 @@ static int GetBytes( HBMp3Enc * m )
m->position = m->rawBuffer->position;
}
- i = MIN( m->samplesNeeded - m->samplesGot,
- ( m->rawBuffer->size / 2 -
- m->rawBufferPos ) / sizeof( float ) );
+ i = MIN( m->inputSamples - m->samplesGot,
+ m->rawBuffer->samples - m->rawBufferPos );
memcpy( m->left + m->samplesGot,
- m->rawBuffer->data + m->rawBufferPos,
+ m->rawBuffer->left + m->rawBufferPos,
i * sizeof( float ) );
memcpy( m->right + m->samplesGot,
- m->rawBuffer->data + m->rawBuffer->size / 2 +
- m->rawBufferPos,
+ m->rawBuffer->right + m->rawBufferPos,
i * sizeof( float ) );
m->samplesGot += i;
- m->rawBufferPos += i * sizeof( float );
+ m->rawBufferPos += i;
- if( m->rawBufferPos == m->rawBuffer->size / 2 )
+ if( m->rawBufferPos == m->rawBuffer->samples )
{
HBBufferClose( &m->rawBuffer );
}
diff --git a/core/Mp3Enc.h b/core/Mp3Enc.h
deleted file mode 100644
index db02f4f44..000000000
--- a/core/Mp3Enc.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $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/Mp4Mux.c b/core/Mp4Mux.c
new file mode 100644
index 000000000..f780cab01
--- /dev/null
+++ b/core/Mp4Mux.c
@@ -0,0 +1,210 @@
+/* $Id: Mp4Mux.c,v 1.22 2004/02/18 17:07:20 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 "HBInternal.h"
+
+/* libmp4v2 */
+#include "mp4.h"
+
+int64_t videoFrames;
+int64_t videoBytes;
+int64_t audioFrames;
+int64_t audioBytes;
+
+/* Local prototypes */
+static void Mp4MuxThread( void * );
+
+struct HBMp4Mux
+{
+ HBHandle * handle;
+ HBTitle * title;
+
+ volatile int die;
+ HBThread * thread;
+};
+
+HBMp4Mux * HBMp4MuxInit( HBHandle * handle, HBTitle * title )
+{
+ HBMp4Mux * m;
+ if( !( m = malloc( sizeof( HBMp4Mux ) ) ) )
+ {
+ HBLog( "HBMp4MuxInit: malloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ videoFrames = 0;
+ videoBytes = 0;
+ audioFrames = 0;
+ audioBytes = 0;
+
+ m->handle = handle;
+ m->title = title;
+
+ m->die = 0;
+ m->thread = HBThreadInit( "mp4 muxer", Mp4MuxThread, m,
+ HB_NORMAL_PRIORITY );
+ return m;
+}
+
+void HBMp4MuxClose( HBMp4Mux ** _m )
+{
+ HBMp4Mux * m = *_m;
+ FILE * file;
+ long size;
+
+ m->die = 1;
+ HBThreadClose( &m->thread );
+
+ file = fopen( m->title->file, "r" );
+ fseek( file, 0, SEEK_END );
+ size = ftell( file );
+ fclose( file );
+
+ HBLog( "HBMp4Mux: videoFrames=%lld, %lld bytes", videoFrames, videoBytes );
+ HBLog( "HBMp4Mux: audioFrames=%lld, %lld bytes", audioFrames, audioBytes );
+ HBLog( "HBMp4Mux: overhead=%.2f bytes / frame",
+ ( (float) size - videoBytes - audioBytes ) /
+ ( videoFrames + audioFrames ) );
+
+ free( m );
+
+ *_m = NULL;
+}
+
+static void Mp4MuxThread( void * _m )
+{
+ HBMp4Mux * m = (HBMp4Mux*) _m;
+ HBTitle * title = m->title;
+ HBAudio * audio;
+ HBBuffer * buffer;
+ char tmpFile[1024];
+
+ int audioCount = HBListCount( m->title->ripAudioList );
+ int i;
+
+ MP4FileHandle file;
+
+ /* Wait until we have one encoded frame for each track */
+ while( !m->die && !HBFifoSize( title->outFifo ) )
+ {
+ HBSnooze( 10000 );
+ }
+ for( i = 0; i < audioCount; i++ )
+ {
+ audio = HBListItemAt( title->ripAudioList, i );
+ while( !m->die && !HBFifoSize( audio->outFifo ) )
+ {
+ HBSnooze( 10000 );
+ }
+ }
+
+ if( m->die )
+ {
+ return;
+ }
+
+ /* Write file headers */
+ file = MP4Create( title->file, 0, 0 );
+ MP4SetTimeScale( file, 90000 );
+ title->track = MP4AddVideoTrack( file, 90000,
+ MP4_INVALID_DURATION,
+ title->outWidth, title->outHeight,
+ MP4_MPEG4_VIDEO_TYPE );
+ MP4SetVideoProfileLevel( file, 0x03 );
+ MP4SetTrackESConfiguration( file, title->track, title->esConfig,
+ title->esConfigLength );
+
+ for( i = 0; i < audioCount; i++ )
+ {
+ audio = HBListItemAt( title->ripAudioList, i );
+ audio->track = MP4AddAudioTrack( file, audio->outSampleRate,
+ 1024, MP4_MPEG4_AUDIO_TYPE );
+ MP4SetAudioProfileLevel( file, 0x0F );
+ MP4SetTrackESConfiguration( file, audio->track, audio->esConfig,
+ audio->esConfigLength );
+ }
+
+ for( ;; )
+ {
+ /* Wait until we have one encoded frame for each track */
+ if( !HBFifoWait( title->outFifo ) )
+ {
+ m->die = 1;
+ break;
+ }
+ for( i = 0; i < audioCount; i++ )
+ {
+ audio = HBListItemAt( title->ripAudioList, i );
+ if( !HBFifoWait( audio->outFifo ) )
+ {
+ m->die = 1;
+ break;
+ }
+ }
+
+ if( m->die )
+ {
+ break;
+ }
+
+ /* Interleave frames in the same order than they were in the
+ original MPEG stream */
+ audio = NULL;
+ for( i = 0; i < audioCount; i++ )
+ {
+ HBAudio * otherAudio;
+ otherAudio = HBListItemAt( title->ripAudioList, i );
+ if( !audio || HBFifoPosition( otherAudio->outFifo ) <
+ HBFifoPosition( audio->outFifo ) )
+ {
+ audio = otherAudio;
+ }
+ }
+
+ if( !audio || HBFifoPosition( title->outFifo ) <
+ HBFifoPosition( audio->outFifo ) )
+ {
+ buffer = HBFifoPop( title->outFifo );
+ MP4WriteSample( file, title->track, buffer->data,
+ buffer->size,
+ (uint64_t) 90000 * title->rateBase / title->rate,
+ 0, buffer->keyFrame );
+ videoFrames++;
+ videoBytes += buffer->size;
+ HBBufferClose( &buffer );
+ }
+ else
+ {
+ buffer = HBFifoPop( audio->outFifo );
+ MP4WriteSample( file, audio->track, buffer->data,
+ buffer->size, MP4_INVALID_DURATION,
+ 0, buffer->keyFrame );
+ audioFrames++;
+ audioBytes += buffer->size;
+ HBBufferClose( &buffer );
+ }
+ }
+
+ MP4Close( file );
+
+ if( !MP4MakeIsmaCompliant( title->file, 0 /*MP4_DETAILS_ALL*/, 1 ) )
+ {
+ HBLog( "HBMp4Mux: MP4MakeIsmaCompliant() failed" );
+ }
+
+ sprintf( tmpFile, "%s.tmp", title->file );
+ tmpFile[strlen( title->file ) + 4] = '\0';
+ if( !MP4Optimize( title->file, tmpFile, 0 /*MP4_DETAILS_ALL*/ ) )
+ {
+ HBLog( "HBMp4Mux: MP4Optimize() failed" );
+ unlink( tmpFile );
+ }
+ else
+ {
+ rename( tmpFile, title->file );
+ }
+}
+
diff --git a/core/Mpeg2Dec.c b/core/Mpeg2Dec.c
index fb81f8080..ea3ffa2e4 100644
--- a/core/Mpeg2Dec.c
+++ b/core/Mpeg2Dec.c
@@ -1,19 +1,14 @@
-/* $Id: Mpeg2Dec.c,v 1.4 2003/11/12 21:46:59 titer Exp $
+/* $Id: Mpeg2Dec.c,v 1.12 2004/01/16 19:04:04 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 "HBInternal.h"
-#include <mpeg2dec/mpeg2.h>
+#include "mpeg2dec/mpeg2.h"
-/* Local prototypes */
-static int Mpeg2DecWork( HBWork * );
-
-struct HBMpeg2Dec
+typedef struct HBMpeg2Dec
{
HB_WORK_COMMON_MEMBERS
@@ -24,9 +19,12 @@ struct HBMpeg2Dec
mpeg2dec_t * libmpeg2;
const mpeg2_info_t * info;
int lateField;
-};
+} HBMpeg2Dec;
+
+/* Local prototypes */
+static int Mpeg2DecWork( HBWork * );
-HBMpeg2Dec * HBMpeg2DecInit( HBHandle * handle, HBTitle * title )
+HBWork * HBMpeg2DecInit( HBHandle * handle, HBTitle * title )
{
HBMpeg2Dec * m ;
if( !( m = malloc( sizeof( HBMpeg2Dec ) ) ) )
@@ -47,15 +45,15 @@ HBMpeg2Dec * HBMpeg2DecInit( HBHandle * handle, HBTitle * title )
m->info = NULL;
m->lateField = 0;
- return m;
+ return (HBWork*) m;
}
-void HBMpeg2DecClose( HBMpeg2Dec ** _m )
+void HBMpeg2DecClose( HBWork ** _m )
{
HBBuffer * buffer;
-
- HBMpeg2Dec * m = *_m;
-
+
+ HBMpeg2Dec * m = (HBMpeg2Dec*) *_m;
+
if( m->libmpeg2 )
{
HBLog( "HBMpeg2Dec: closing libmpeg2 (pass %d)", m->pass );
@@ -69,7 +67,7 @@ void HBMpeg2DecClose( HBMpeg2Dec ** _m )
HBListClose( &m->rawBufferList );
free( m->name );
free( m );
-
+
*_m = NULL;
}
@@ -81,7 +79,7 @@ static int Mpeg2DecWork( HBWork * w )
HBBuffer * rawBuffer;
HBBuffer * tmpBuffer;
mpeg2_state_t state;
-
+
int didSomething = 0;
/* Push decoded buffers */
@@ -101,7 +99,7 @@ static int Mpeg2DecWork( HBWork * w )
}
/* Get a new buffer to decode */
- if( ( mpeg2Buffer = HBFifoPop( title->mpeg2Fifo ) ) )
+ if( ( mpeg2Buffer = HBFifoPop( title->inFifo ) ) )
{
didSomething = 1;
}
@@ -122,6 +120,9 @@ static int Mpeg2DecWork( HBWork * w )
m->pass = mpeg2Buffer->pass;
HBLog( "HBMpeg2Dec: opening libmpeg2 (pass %d)", m->pass );
+#ifdef HB_NOMMX
+ mpeg2_accel( 0 );
+#endif
m->libmpeg2 = mpeg2_init();
m->info = mpeg2_info( m->libmpeg2 );
m->lateField = 0;
@@ -143,7 +144,7 @@ static int Mpeg2DecWork( HBWork * w )
m->info->display_fbuf )
{
rawBuffer = HBBufferInit( 3 * title->inWidth *
- title->outWidth );
+ title->inHeight );
/* TODO: make libmpeg2 write directly in our buffer */
memcpy( rawBuffer->data, m->info->display_fbuf->buf[0],
@@ -164,16 +165,12 @@ static int Mpeg2DecWork( HBWork * w )
/* 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;
- memcpy( tmpBuffer->data, rawBuffer->data,
- tmpBuffer->size );
- HBListAdd( m->rawBufferList, tmpBuffer );
- }
- m->lateField = !m->lateField;
+ rawBuffer->repeat = m->lateField;
+ m->lateField = !m->lateField;
+ }
+ else
+ {
+ rawBuffer->repeat = 0;
}
}
else if( state == STATE_INVALID )
@@ -183,11 +180,6 @@ static int Mpeg2DecWork( HBWork * w )
}
}
- if( mpeg2Buffer->last )
- {
- HBDone( m->handle );
- }
-
HBBufferClose( &mpeg2Buffer );
return didSomething;
diff --git a/core/Mpeg2Dec.h b/core/Mpeg2Dec.h
deleted file mode 100644
index af7f18c44..000000000
--- a/core/Mpeg2Dec.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $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/OgmMux.c b/core/OgmMux.c
new file mode 100644
index 000000000..d4712594b
--- /dev/null
+++ b/core/OgmMux.c
@@ -0,0 +1,471 @@
+/* $Id: OgmMux.c,v 1.6 2004/02/13 15:12:09 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 "HBInternal.h"
+
+#include <ogg/ogg.h>
+
+static void OgmMuxThread( void * );
+static int OgmStart( HBOgmMux * );
+static int OgmFlush( HBOgmMux *, int );
+static int OgmEnd( HBOgmMux * );
+
+struct HBOgmMux
+{
+ HBHandle *handle;
+ HBTitle *title;
+
+ volatile int die;
+ HBThread *thread;
+
+ FILE *file;
+
+ int i_tk;
+ struct
+ {
+ HBFifo *fifo;
+
+ int codec;
+
+ ogg_stream_state os;
+ int i_packet_no;
+
+ } tk[100]; /* The first who set more than 100 stream !! */
+};
+
+HBOgmMux * HBOgmMuxInit( HBHandle * handle, HBTitle * title )
+{
+ HBOgmMux *ogm = malloc( sizeof( HBOgmMux ) );
+
+ ogm->handle = handle;
+ ogm->title = title;
+
+ ogm->file = NULL;
+ ogm->i_tk = 0;
+
+ ogm->die = 0;
+ ogm->thread = HBThreadInit( "ogm muxer", OgmMuxThread, ogm, HB_NORMAL_PRIORITY );
+ return ogm;
+}
+
+void HBOgmMuxClose( HBOgmMux ** _ogm )
+{
+ HBOgmMux *ogm = *_ogm;
+
+ ogm->die = 1;
+ HBThreadClose( &ogm->thread );
+
+ free( ogm );
+
+ *_ogm = NULL;
+}
+
+static int OgmDataWait( HBOgmMux *ogm )
+{
+ int i;
+
+ for( i = 0; i < ogm->i_tk; i++ )
+ {
+ while( !ogm->die && HBFifoSize( ogm->tk[i].fifo ) <= 0 )
+ {
+ HBSnooze( 10000 );
+ }
+ }
+ return ogm->die ? -1 : 0;
+}
+
+static void OgmMuxThread( void * _this )
+{
+ HBOgmMux *ogm = _this;
+
+ HBTitle *title = ogm->title;
+
+ int i;
+
+ /* Open output file */
+ if( ( ogm->file = fopen( title->file, "w" ) ) == NULL )
+ {
+ HBLog( "HBOgmMux: failed to open `%s'", title->file );
+ /* FIXME */
+ HBErrorOccured( ogm->handle, HB_ERROR_AVI_WRITE );
+ return;
+ }
+ HBLog( "HBOgmMux: `%s' opened", title->file );
+
+
+ /* Wait for data in each fifo */
+ HBLog( "HBOgmMux: waiting video/audio data" );
+ if( OgmDataWait( ogm ) < 0 )
+ {
+ HBLog( "HBOgmMux: exiting" );
+ fclose( ogm->file );
+ unlink( title->file );
+ return;
+ }
+
+ if( OgmStart( ogm ) < 0 )
+ {
+ HBLog( "HBOgmMux: failed to write headers" );
+ fclose( ogm->file );
+ unlink( title->file );
+ return;
+ }
+
+ HBLog( "HBOgmMux: headers written" );
+
+ for( ;; )
+ {
+ HBBuffer *buffer;
+ ogg_packet op;
+ int i_tk;
+
+ /* Wait data */
+ if( OgmDataWait( ogm ) < 0 )
+ {
+ break;
+ }
+
+ /* Choose the right track to write (interleaved data) */
+ for( i = 0, i_tk = -1; i < ogm->i_tk; i++ )
+ {
+ if( i_tk < 0 ||
+ HBFifoPosition( ogm->tk[i].fifo ) < HBFifoPosition( ogm->tk[i_tk].fifo ) )
+ {
+ i_tk = i;
+ }
+ }
+
+ buffer = HBFifoPop( ogm->tk[i_tk].fifo );
+
+ switch( ( ogm->tk[i_tk].codec ) )
+ {
+ case HB_CODEC_FFMPEG:
+ case HB_CODEC_XVID:
+ case HB_CODEC_X264:
+ op.bytes = buffer->size + 1;
+ op.packet = malloc( op.bytes );
+ op.packet[0] = buffer->keyFrame ? 0x08 : 0x00;
+ memcpy( &op.packet[1], buffer->data, buffer->size );
+ op.b_o_s = 0;
+ op.e_o_s = 0;
+ op.granulepos = ogm->tk[i_tk].i_packet_no;
+ op.packetno = ogm->tk[i_tk].i_packet_no++;
+ break;
+ case HB_CODEC_MP3:
+ op.bytes = buffer->size + 1;
+ op.packet = malloc( op.bytes );
+ op.packet[0] = 0x08;
+ memcpy( &op.packet[1], buffer->data, buffer->size );
+ op.b_o_s = 0;
+ op.e_o_s = 0;
+ op.granulepos = ogm->tk[i_tk].i_packet_no * 1152;
+ op.packetno = ogm->tk[i_tk].i_packet_no++;
+ break;
+ case HB_CODEC_VORBIS:
+ memcpy( &op, buffer->data, sizeof( ogg_packet ) );
+
+ op.packet = malloc( op.bytes );
+ memcpy( op.packet, buffer->data + sizeof( ogg_packet ), op.bytes );
+ break;
+
+ default:
+ HBLog( "HBOgmMux: unhandled codec" );
+ op.bytes = 0;
+ op.packet = NULL;
+ break;
+ }
+
+ if( op.packet )
+ {
+ ogg_stream_packetin( &ogm->tk[i_tk].os, &op );
+
+ for( ;; )
+ {
+ ogg_page og;
+ if( ogg_stream_pageout( &ogm->tk[i_tk].os, &og ) == 0 )
+ {
+ break;
+ }
+
+ if( fwrite( og.header, og.header_len, 1, ogm->file ) <= 0 ||
+ fwrite( og.body, og.body_len, 1, ogm->file ) <= 0 )
+ {
+ HBLog( "HBOgmMux: write failed" );
+ break;
+ }
+ }
+ free( op.packet );
+ }
+
+ HBBufferClose( &buffer );
+ }
+
+ if( OgmEnd( ogm ) < 0 )
+ {
+ HBLog( "HBOgmMux: flush failed" );
+ }
+
+ fclose( ogm->file );
+ HBLog( "HBOgmMux: `%s' closed", title->file );
+}
+
+typedef struct __attribute__((__packed__))
+{
+ uint8_t i_packet_type;
+
+ char stream_type[8];
+ char sub_type[4];
+
+ int32_t i_size;
+
+ int64_t i_time_unit;
+ int64_t i_samples_per_unit;
+ int32_t i_default_len;
+
+ int32_t i_buffer_size;
+ int16_t i_bits_per_sample;
+ int16_t i_padding_0; // hum hum
+ union
+ {
+ struct
+ {
+ int32_t i_width;
+ int32_t i_height;
+
+ } video;
+ struct
+ {
+ int16_t i_channels;
+ int16_t i_block_align;
+ int32_t i_avgbytespersec;
+ } audio;
+ } header;
+
+} ogg_stream_header_t;
+
+#define SetWLE( p, v ) _SetWLE( (uint8_t*)p, v)
+static void _SetWLE( uint8_t *p, uint16_t i_dw )
+{
+ p[1] = ( i_dw >> 8 )&0xff;
+ p[0] = ( i_dw )&0xff;
+}
+
+#define SetDWLE( p, v ) _SetDWLE( (uint8_t*)p, v)
+static void _SetDWLE( uint8_t *p, uint32_t i_dw )
+{
+ p[3] = ( i_dw >> 24 )&0xff;
+ p[2] = ( i_dw >> 16 )&0xff;
+ p[1] = ( i_dw >> 8 )&0xff;
+ p[0] = ( i_dw )&0xff;
+}
+#define SetQWLE( p, v ) _SetQWLE( (uint8_t*)p, v)
+static void _SetQWLE( uint8_t *p, uint64_t i_qw )
+{
+ SetDWLE( p, i_qw&0xffffffff );
+ SetDWLE( p+4, ( i_qw >> 32)&0xffffffff );
+}
+
+static int OgmFlush( HBOgmMux *ogm, int i_tk )
+{
+ for( ;; )
+ {
+ ogg_page og;
+ if( ogg_stream_flush( &ogm->tk[i_tk].os, &og ) == 0 )
+ {
+ break;
+ }
+ if( fwrite( og.header, og.header_len, 1, ogm->file ) <= 0 ||
+ fwrite( og.body, og.body_len, 1, ogm->file ) <= 0 )
+ {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int OgmStart( HBOgmMux *ogm )
+{
+ HBTitle *title = ogm->title;
+ int i;
+
+ ogg_packet op;
+
+ /* Init track */
+ ogm->tk[0].codec = title->codec;
+ ogm->tk[0].fifo = title->outFifo;
+ ogm->tk[0].i_packet_no = 0;
+ ogg_stream_init (&ogm->tk[0].os, 0 );
+
+ for( i = 1; i < HBListCount( title->ripAudioList ) + 1; i++ )
+ {
+ HBAudio *audio = HBListItemAt( title->ripAudioList, i - 1 );
+
+ ogm->tk[i].codec = audio->codec;
+ ogm->tk[i].fifo = audio->outFifo;
+ ogm->tk[i].i_packet_no = 0;
+ ogg_stream_init (&ogm->tk[i].os, i );
+
+ }
+ ogm->i_tk = 1 + HBListCount( title->ripAudioList );
+
+ /* Wait data for each track */
+ for( i = 0; i < ogm->i_tk; i++ )
+ {
+ while( !ogm->die &&
+ ( ( ogm->tk[i].codec == HB_CODEC_VORBIS && HBFifoSize( ogm->tk[i].fifo ) <= 3 ) ||
+ HBFifoSize( ogm->tk[i].fifo ) <= 0 ) )
+ {
+ HBSnooze( 10000 );
+ }
+ }
+
+ if( ogm->die )
+ {
+ return -1;
+ }
+
+ /* First pass: all b_o_s packets */
+ for( i = 0; i < ogm->i_tk; i++ )
+ {
+ ogg_stream_header_t h;
+
+ memset( &h, 0, sizeof( ogg_stream_header_t ) );
+
+ switch( ogm->tk[i].codec )
+ {
+ case HB_CODEC_FFMPEG:
+ case HB_CODEC_XVID:
+ case HB_CODEC_X264:
+ h.i_packet_type = 0x01;
+ memcpy( h.stream_type, "video ", 8 );
+ if( ogm->tk[i].codec == HB_CODEC_X264 )
+ {
+ memcpy( h.sub_type, "H264", 4 );
+ }
+ else
+ {
+ memcpy( h.sub_type, "XVID", 4 );
+ }
+
+ SetDWLE( &h.i_size, sizeof( ogg_stream_header_t ) - 1);
+ SetQWLE( &h.i_time_unit, (int64_t)10*1000*1000*(int64_t)title->rateBase/(int64_t)title->rate );
+ SetQWLE( &h.i_samples_per_unit, 1 );
+ SetDWLE( &h.i_default_len, 0 );
+ SetDWLE( &h.i_buffer_size, 1024*1024 );
+ SetWLE ( &h.i_bits_per_sample, 0 );
+ SetDWLE( &h.header.video.i_width, title->outWidth );
+ SetDWLE( &h.header.video.i_height, title->outHeight );
+
+ op.packet = (char*)&h;
+ op.bytes = sizeof( ogg_stream_header_t );
+ op.b_o_s = 1;
+ op.e_o_s = 0;
+ op.granulepos = 0;
+ op.packetno = ogm->tk[i].i_packet_no++;
+ ogg_stream_packetin( &ogm->tk[i].os, &op );
+ break;
+
+ case HB_CODEC_MP3:
+ {
+ HBAudio *audio = HBListItemAt( title->ripAudioList, i - 1 );
+
+ h.i_packet_type = 0x01;
+ memcpy( h.stream_type, "audio ", 8 );
+ memcpy( h.sub_type, "55 ", 4 );
+
+ SetDWLE( &h.i_size, sizeof( ogg_stream_header_t ) - 1);
+ SetQWLE( &h.i_time_unit, 0 );
+ SetQWLE( &h.i_samples_per_unit, audio->outSampleRate );
+ SetDWLE( &h.i_default_len, 1 );
+ SetDWLE( &h.i_buffer_size, 30*1024 );
+ SetWLE ( &h.i_bits_per_sample, 0 );
+
+ SetDWLE( &h.header.audio.i_channels, 2 );
+ SetDWLE( &h.header.audio.i_block_align, 0 );
+ SetDWLE( &h.header.audio.i_avgbytespersec, audio->outBitrate / 8 );
+
+
+ op.packet = (char*)&h;
+ op.bytes = sizeof( ogg_stream_header_t );
+ op.b_o_s = 1;
+ op.e_o_s = 0;
+ op.granulepos = 0;
+ op.packetno = ogm->tk[i].i_packet_no++;
+ ogg_stream_packetin( &ogm->tk[i].os, &op );
+ break;
+ }
+ case HB_CODEC_VORBIS:
+ {
+ HBBuffer *h = HBFifoPop( ogm->tk[i].fifo );
+
+ memcpy( &op, h->data, sizeof( ogg_packet ) );
+ op.packet = h->data + sizeof( ogg_packet );
+ ogg_stream_packetin( &ogm->tk[i].os, &op );
+ break;
+ }
+ case HB_CODEC_AAC:
+ break;
+ default:
+ HBLog( "unhandled codec" );
+ break;
+ }
+ OgmFlush( ogm, i );
+ }
+
+ /* second pass: all non b_o_s packets */
+ for( i = 0; i < ogm->i_tk; i++ )
+ {
+ if( ogm->tk[i].codec == HB_CODEC_VORBIS )
+ {
+ HBBuffer *h;
+ int j;
+
+ for( j = 0; j < 2; j++ )
+ {
+ HBFifoWait( ogm->tk[i].fifo );
+ h = HBFifoPop( ogm->tk[i].fifo );
+
+ memcpy( &op, h->data, sizeof( ogg_packet ) );
+ op.packet = h->data + sizeof( ogg_packet );
+ ogg_stream_packetin( &ogm->tk[i].os, &op );
+
+ OgmFlush( ogm, i );
+ }
+ }
+#if 0
+ else
+ {
+ /* Home made commentary */
+ op.packet = "\003Handbrake";
+ op.bytes = strlen( "\003Handbrake" );;
+ op.b_o_s = 0;
+ op.e_o_s = 0;
+ op.granulepos = 0;
+ op.packetno = ogm->tk[i].i_packet_no++;
+
+ ogg_stream_packetin( &ogm->tk[i].os, &op );
+ OgmFlush( ogm, i );
+ }
+#endif
+ }
+
+ return 0;
+}
+
+static int OgmEnd( HBOgmMux *ogm )
+{
+ int i;
+
+ for( i = 0; i < ogm->i_tk; i++ )
+ {
+ if( OgmFlush( ogm, i ) < 0 )
+ {
+ return -1;
+ }
+ }
+ return 0;
+}
+
diff --git a/core/Scale.c b/core/Scale.c
index 7e9295962..464623c1e 100644
--- a/core/Scale.c
+++ b/core/Scale.c
@@ -1,19 +1,14 @@
-/* $Id: Scale.c,v 1.4 2003/11/06 13:03:19 titer Exp $
+/* $Id: Scale.c,v 1.9 2004/01/16 19:39:23 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 "HBInternal.h"
-#include <ffmpeg/avcodec.h>
+#include "ffmpeg/avcodec.h"
-/* Local prototypes */
-static int ScaleWork( HBWork * );
-
-struct HBScale
+typedef struct HBScale
{
HB_WORK_COMMON_MEMBERS
@@ -24,11 +19,14 @@ struct HBScale
AVPicture rawPicture;
HBBuffer * deintBuffer;
AVPicture deintPicture;
- HBBuffer * scaledBuffer;
+ HBList * scaledBufferList;
AVPicture scaledPicture;
-};
+} HBScale;
-HBScale * HBScaleInit( HBHandle * handle, HBTitle * title )
+/* Local prototypes */
+static int ScaleWork( HBWork * );
+
+HBWork * HBScaleInit( HBHandle * handle, HBTitle * title )
{
HBScale * s;
if( !( s = malloc( sizeof( HBScale ) ) ) )
@@ -51,25 +49,26 @@ HBScale * HBScaleInit( HBHandle * handle, HBTitle * title )
title->leftCrop, title->rightCrop );
/* Allocate a constant buffer used for deinterlacing */
- s->deintBuffer = HBBufferInit( 3 * title->inWidth *
+ 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;
+ s->scaledBufferList = HBListInit();
- return s;
+ return (HBWork*) s;
}
-void HBScaleClose( HBScale ** _s )
+void HBScaleClose( HBWork ** _s )
{
- HBScale * s = *_s;
-
+ HBScale * s = (HBScale*) *_s;
+
img_resample_close( s->context );
+ HBListClose( &s->scaledBufferList );
HBBufferClose( &s->deintBuffer );
free( s->name );
free( s );
-
+
*_s = NULL;
}
@@ -78,15 +77,20 @@ static int ScaleWork( HBWork * w )
HBScale * s = (HBScale*) w;
HBTitle * title = s->title;
HBBuffer * rawBuffer;
+ HBBuffer * scaledBuffer;
+ HBBuffer * tmpBuffer;
int didSomething = 0;
- /* Push scaled buffer */
- if( s->scaledBuffer )
+ /* Push scaled buffer(s) */
+ while( ( scaledBuffer = (HBBuffer*)
+ HBListItemAt( s->scaledBufferList, 0 ) ) )
{
- if( HBFifoPush( title->scaledFifo, &s->scaledBuffer ) )
+ tmpBuffer = scaledBuffer;
+ if( HBFifoPush( title->scaledFifo, &scaledBuffer ) )
{
didSomething = 1;
+ HBListRemove( s->scaledBufferList, tmpBuffer );
}
else
{
@@ -105,15 +109,15 @@ static int ScaleWork( HBWork * w )
}
/* 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;
+ scaledBuffer = HBBufferInit( 3 * title->outWidth *
+ title->outHeight / 2 );
+ scaledBuffer->position = rawBuffer->position;
+ 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,
+ avpicture_fill( &s->scaledPicture, scaledBuffer->data,
PIX_FMT_YUV420P, title->outWidth,
title->outHeight );
@@ -131,9 +135,22 @@ static int ScaleWork( HBWork * w )
img_resample( s->context, &s->scaledPicture, &s->rawPicture );
}
+ HBListAdd( s->scaledBufferList, scaledBuffer );
+
+ if( rawBuffer->repeat )
+ {
+ tmpBuffer = HBBufferInit( scaledBuffer->size );
+ tmpBuffer->position = scaledBuffer->position;
+ tmpBuffer->pass = scaledBuffer->pass;
+ memcpy( tmpBuffer->data, scaledBuffer->data,
+ scaledBuffer->size );
+
+ HBListAdd( s->scaledBufferList, tmpBuffer );
+ }
+
/* Free memory */
HBBufferClose( &rawBuffer );
-
+
return didSomething;
}
diff --git a/core/Scale.h b/core/Scale.h
deleted file mode 100644
index cf06ad661..000000000
--- a/core/Scale.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $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
index 7a62a97e0..f2afd5e6c 100644
--- a/core/Scan.c
+++ b/core/Scan.c
@@ -1,21 +1,19 @@
-/* $Id: Scan.c,v 1.5 2003/11/09 21:28:22 titer Exp $
+/* $Id: Scan.c,v 1.14 2004/01/18 13:21:12 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 "HBInternal.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 "dvdread/ifo_types.h"
+#include "dvdplay/dvdplay.h"
+#include "dvdplay/info.h"
+#include "dvdplay/state.h"
+#include "dvdplay/nav.h"
-#include <mpeg2dec/mpeg2.h>
+#include "mpeg2dec/mpeg2.h"
/* Local prototypes */
static void ScanThread( void * );
@@ -26,14 +24,14 @@ static char * LanguageForCode( int code );
struct HBScan
{
- HBHandle * handle;
- char * device;
- int title;
- int die;
- HBThread * thread;
+ HBHandle * handle;
+ char * device;
+ int title;
+ volatile int die;
+ HBThread * thread;
};
-HBScan * HBScanInit( HBHandle * handle, char * device, int title )
+HBScan * HBScanInit( HBHandle * handle, const char * device, int title )
{
HBScan * s;
if( !( s = malloc( sizeof( HBScan ) ) ) )
@@ -55,7 +53,7 @@ HBScan * HBScanInit( HBHandle * handle, char * device, int title )
void HBScanClose( HBScan ** _s )
{
HBScan * s = *_s;
-
+
s->die = 1;
HBThreadClose( &s->thread );
@@ -66,65 +64,77 @@ void HBScanClose( HBScan ** _s )
static void ScanThread( void * _s )
{
- HBScan * s = (HBScan*) _s;
- dvdplay_ptr vmg;
- HBList * titleList = HBListInit();
- HBTitle * title;
- int i;
+ 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 );
+ HBListClose( &titleList );
+ HBScanDone( s->handle, NULL );
return;
}
/* Detect titles */
- for( i = ( s->title ? s->title - 1 : 0 );
- i < ( s->title ? s->title : dvdplay_title_nr( vmg ) );
- i++ )
+ i = s->title ? ( s->title - 1 ) : 0;
+ while( !s->die )
{
- if( s->die )
+ if( ( title = ScanTitle( s, vmg, i + 1 ) ) )
{
- break;
+ HBListAdd( titleList, title );
}
-
- if( !( title = ScanTitle( s, vmg, i + 1 ) ) )
+ if( s->title || i == dvdplay_title_nr( vmg ) - 1 )
{
- continue;
+ break;
}
-
- HBListAdd( titleList, title );
+ i++;
}
HBLog( "HBScan: closing device %s", s->device );
dvdplay_close( vmg );
+ if( s->die )
+ {
+ while( ( title = HBListItemAt( titleList, 0 ) ) )
+ {
+ HBListRemove( titleList, title );
+ HBTitleClose( &title );
+ }
+ HBListClose( &titleList );
+ return;
+ }
+
+ if( !HBListCount( titleList ) )
+ {
+ HBListClose( &titleList );
+ }
HBScanDone( s->handle, titleList );
}
static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index )
{
- HBTitle * title;
- int audio_nr, foo;
+ 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 );
+ HBAudio * audio;
+ int i;
+ uint8_t dummy[DVD_VIDEO_LB_LEN];
+
+ HBScanning( s->handle, index, dvdplay_title_nr( vmg ) );
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 );
+ HBLog( "HBScan: title %d: length is %d seconds", index,
+ title->length );
/* Discard titles under 10 seconds */
if( title->length < 10 )
@@ -139,9 +149,8 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index )
for( i = 0; i < audio_nr; i++ )
{
- int id;
- int j;
-
+ int id, j;
+
if( s->die )
{
break;
@@ -156,13 +165,14 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index )
if( ( id & 0xF0FF ) != 0x80BD )
{
- HBLog( "HBScan: non-AC3 audio track detected, ignoring" );
+ HBLog( "HBScan: title %d: non-AC3 audio track detected, "
+ "ignoring", index );
continue;
}
/* Check if we don't already found an track with the same id */
audio = NULL;
- for( j = 0; j < HBListCountItems( title->audioList ); j++ )
+ for( j = 0; j < HBListCount( title->audioList ); j++ )
{
audio = (HBAudio*) HBListItemAt( title->audioList, j );
if( id == audio->id )
@@ -177,28 +187,29 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index )
if( audio )
{
- HBLog( "HBScan: discarding duplicate track %x", id );
+ HBLog( "HBScan: title %d: discarding duplicate track %x",
+ index, id );
continue;
}
- attr = dvdplay_audio_attr( vmg, j );
+ attr = dvdplay_audio_attr( vmg, j );
audio = HBAudioInit( id, LanguageForCode( attr->lang_code ) );
- HBLog( "HBScan: new language (%x, %s)", id, audio->language );
+ HBLog( "HBScan: title %d: new language (%x, %s)", index, id,
+ audio->language );
HBListAdd( title->audioList, audio );
}
/* Discard titles with no audio tracks */
- if( !HBListCountItems( title->audioList ) )
+ if( !HBListCount( 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 */
+ /* Kludge : libdvdplay wants us to read a first block before seeking */
dvdplay_read( vmg, dummy, 1 );
-
for( i = 0; i < 10; i++ )
{
if( s->die )
@@ -215,6 +226,7 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index )
}
}
+ /* Handle ratio */
if( title->inHeight * title->aspect >
title->inWidth * VOUT_ASPECT_FACTOR )
{
@@ -248,8 +260,9 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg,
mpeg2dec_t * handle;
const mpeg2_info_t * info;
mpeg2_state_t state;
- char fileName[1024];
- FILE * file;
+ char fileName[1024];
+ FILE * file;
+ int ret = 1;
HBList * esBufferList = HBListInit();
HBBuffer * psBuffer = NULL;
@@ -259,43 +272,34 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg,
dvdplay_seek( vmg, pictureStart );
/* Init libmpeg2 */
+#ifdef HB_NOMMX
+ mpeg2_accel( 0 );
+#endif
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 ),
+ 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 ) )
+ while( !HBListCount( esBufferList ) )
{
psBuffer = HBBufferInit( DVD_VIDEO_LB_LEN );
if( dvdplay_read( vmg, psBuffer->data, 1 ) != 1 ||
@@ -303,18 +307,21 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg,
{
HBLog( "HBScan: failed to get a valid PS "
"packet" );
- CLEANUP;
- return 0;
+ break;
}
if( dvdplay_position( vmg ) >= pictureEnd )
{
HBLog( "HBScan: gone too far, aborting" );
- CLEANUP;
- return 0;
+ break;
}
}
+ if( !HBListCount( esBufferList ) )
+ {
+ break;
+ }
+
esBuffer = (HBBuffer*) HBListItemAt( esBufferList, 0 );
HBListRemove( esBufferList, esBuffer );
@@ -324,27 +331,80 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg,
}
}
+ if( !esBuffer )
+ {
+ ret = 0;
+ break;
+ }
+
/* 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;
+ if( !which )
+ {
+ /* 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;
+
+ title->autoTopCrop = title->inHeight / 2;
+ title->autoBottomCrop = title->inHeight / 2;
+ title->autoLeftCrop = title->inWidth / 2;
+ title->autoRightCrop = title->inWidth / 2;
+ }
}
else if( ( state == STATE_SLICE || state == STATE_END ) &&
( info->display_fbuf ) &&
( info->display_picture->flags & PIC_MASK_CODING_TYPE )
== PIC_FLAG_CODING_TYPE_I )
{
+#define Y info->display_fbuf->buf[0]
+#define DARK 64
+ /* Detect black borders */
+ int i, j;
+ for( i = 0; i < title->inWidth; i++ )
+ {
+ for( j = 0; j < title->autoTopCrop; j++ )
+ if( Y[ j * title->inWidth + i ] > DARK )
+ {
+ title->autoTopCrop = j;
+ break;
+ }
+ for( j = 0; j < title->autoBottomCrop; j++ )
+ if( Y[ ( title->inHeight - j - 1 ) *
+ title->inWidth + i ] > DARK )
+ {
+ title->autoBottomCrop = j;
+ break;
+ }
+ }
+ for( i = 0; i < title->inHeight; i++ )
+ {
+ for( j = 0; j < title->autoLeftCrop; j++ )
+ if( Y[ i * title->inWidth + j ] > DARK )
+ {
+ title->autoLeftCrop = j;
+ break;
+ }
+ for( j = 0; j < title->autoRightCrop; j++ )
+ if( Y[ i * title->inWidth +
+ title->inWidth - j - 1 ] > DARK )
+ {
+ title->autoRightCrop = j;
+ break;
+ }
+ }
+#undef Y
+#undef DARK
+
/* Write the raw picture to a file */
fwrite( info->display_fbuf->buf[0],
title->inWidth * title->inHeight, 1, file );
@@ -358,15 +418,25 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg,
{
/* Reset libmpeg2 */
mpeg2_close( handle );
+#ifdef HB_NOMMX
+ mpeg2_accel( 0 );
+#endif
handle = mpeg2_init();
}
}
- CLEANUP;
-
- return 1;
+ 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 );
-#undef CLEANUP
+ return ret;
}
static char * LanguageForCode( int code )
diff --git a/core/Scan.h b/core/Scan.h
deleted file mode 100644
index 5cc8542e7..000000000
--- a/core/Scan.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $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/Thread.c b/core/Thread.c
index f0d8e628b..01af1b0b6 100644
--- a/core/Thread.c
+++ b/core/Thread.c
@@ -1,13 +1,10 @@
-/* $Id: Thread.c,v 1.5 2003/11/12 16:09:34 titer Exp $
+/* $Id: Thread.c,v 1.10 2004/01/14 21:37:25 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"
-#ifdef SYS_CYGWIN
-# include <windows.h>
-#endif
struct HBThread
{
@@ -15,12 +12,12 @@ struct HBThread
int priority;
void (*function) ( void * );
void * arg;
-
-#if defined( SYS_BEOS )
+
+#if defined( HB_BEOS )
int thread;
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
pthread_t thread;
-#elif defined( SYS_CYGWIN )
+#elif defined( HB_CYGWIN )
HANDLE thread;
#endif
};
@@ -42,14 +39,14 @@ HBThread * HBThreadInit( char * name, void (* function)(void *),
t->function = function;
t->arg = arg;
-#if defined( SYS_BEOS )
+#if defined( HB_BEOS )
t->thread = spawn_thread( (int32 (*)( void * )) ThreadFunc,
name, priority, t );
resume_thread( t->thread );
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
pthread_create( &t->thread, NULL,
(void * (*)( void * )) ThreadFunc, t );
-#elif defined( SYS_CYGWIN )
+#elif defined( HB_CYGWIN )
t->thread = CreateThread( NULL, 0,
(LPTHREAD_START_ROUTINE) ThreadFunc, t, 0, NULL );
#endif
@@ -64,7 +61,7 @@ static void ThreadFunc( void * _t )
{
HBThread * t = (HBThread*) _t;
-#if defined( SYS_MACOSX )
+#if defined( HB_MACOSX )
struct sched_param param;
memset( &param, 0, sizeof( struct sched_param ) );
param.sched_priority = t->priority;
@@ -80,13 +77,13 @@ static void ThreadFunc( void * _t )
void HBThreadClose( HBThread ** _t )
{
HBThread * t = *_t;
-
-#if defined( SYS_BEOS )
+
+#if defined( HB_BEOS )
long exitValue;
wait_for_thread( t->thread, &exitValue );
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
pthread_join( t->thread, NULL );
-#elif defined( SYS_CYGWIN )
+#elif defined( HB_CYGWIN )
WaitForSingleObject( t->thread, INFINITE );
#endif
@@ -107,12 +104,12 @@ HBLock * HBLockInit()
return NULL;
}
-#if defined( SYS_BEOS )
+#if defined( HB_BEOS )
l->sem = create_sem( 1, "sem" );
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
pthread_mutex_init( &l->mutex, NULL );
-#elif defined( SYS_CYGWIN )
- /* TODO */
+#elif defined( HB_CYGWIN )
+ l->mutex = CreateMutex( 0, FALSE, 0 );
#endif
return l;
@@ -121,16 +118,46 @@ HBLock * HBLockInit()
void HBLockClose( HBLock ** _l )
{
HBLock * l = *_l;
-
-#if defined( SYS_BEOS )
+
+#if defined( HB_BEOS )
delete_sem( l->sem );
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
pthread_mutex_destroy( &l->mutex );
-#elif defined( SYS_CYGWIN )
- /* TODO */
+#elif defined( HB_CYGWIN )
+ CloseHandle( l->mutex );
#endif
free( l );
*_l = NULL;
}
+HBCond * HBCondInit()
+{
+ HBCond * c = malloc( sizeof( HBCond ) );
+
+#if defined( HB_BEOS )
+ c->thread = -1;
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
+ pthread_cond_init( &c->cond, NULL );
+#elif defined( HB_CYGWIN )
+ /* TODO */
+#endif
+
+ return c;
+}
+
+void HBCondClose( HBCond ** _c )
+{
+ HBCond * c = *_c;
+
+#if defined( HB_BEOS )
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
+ pthread_cond_destroy( &c->cond );
+#elif defined( HB_CYGWIN )
+ /* TODO */
+#endif
+ free( c );
+
+ *_c = NULL;
+}
+
diff --git a/core/Thread.h b/core/Thread.h
index 58700aae1..4d6288e5b 100644
--- a/core/Thread.h
+++ b/core/Thread.h
@@ -1,4 +1,4 @@
-/* $Id: Thread.h,v 1.3 2003/11/06 15:51:36 titer Exp $
+/* $Id: Thread.h,v 1.8 2004/01/14 21:37:25 titer Exp $
This file is part of the HandBrake source code.
Homepage: <http://handbrake.m0k.org/>.
@@ -7,64 +7,125 @@
#ifndef HB_THREAD_H
#define HB_THREAD_H
-#if defined( SYS_BEOS )
+/* System headers */
+#if defined( HB_BEOS )
# include <OS.h>
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
# include <pthread.h>
+#elif defined( HB_CYGWIN )
+# include <windows.h>
#endif
#include "Utils.h"
-#if defined( SYS_BEOS )
+/* Thread priorities */
+#if defined( HB_BEOS )
# define HB_LOW_PRIORITY 5
# define HB_NORMAL_PRIORITY 10
-#elif defined( SYS_MACOSX )
+#elif defined( HB_MACOSX )
# define HB_LOW_PRIORITY 0
# define HB_NORMAL_PRIORITY 31
-#elif defined( SYS_LINUX ) || defined( SYS_CYGWIN )
+#elif defined( HB_LINUX ) || defined( HB_CYGWIN )
/* Actually unused */
# define HB_LOW_PRIORITY 0
# define HB_NORMAL_PRIORITY 0
#endif
+/* Functions declarations */
HBThread * HBThreadInit( char * name, void (* function)(void *),
void * arg, int priority );
void HBThreadClose( HBThread ** );
+HBLock * HBLockInit();
+static inline void HBLockLock( HBLock * );
+static inline void HBLockUnlock( HBLock * );
+void HBLockClose( HBLock ** );
+
+HBCond * HBCondInit();
+static inline void HBCondWait( HBCond *, HBLock * );
+static inline void HBCondSignal( HBCond * );
+void HBCondClose( HBCond ** );
+
+/* Inlined stuff */
struct HBLock
{
-#if defined( SYS_BEOS )
+#if defined( HB_BEOS )
sem_id sem;
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
pthread_mutex_t mutex;
-#elif defined( SYS_CYGWIN )
- /* TODO */
+#elif defined( HB_CYGWIN )
+ HANDLE mutex;
#endif
};
-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 )
+#if defined( HB_BEOS )
acquire_sem( l->sem );
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
pthread_mutex_lock( &l->mutex );
-#elif defined( SYS_CYGWIN )
- /* TODO */
+#elif defined( HB_CYGWIN )
+ WaitForSingleObject( l->mutex, INFINITE );
#endif
}
static inline void HBLockUnlock( HBLock * l )
{
-#if defined( SYS_BEOS )
+#if defined( HB_BEOS )
release_sem( l->sem );
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
pthread_mutex_unlock( &l->mutex );
-#elif defined( SYS_CYGWIN )
+#elif defined( HB_CYGWIN )
+ ReleaseMutex( l->mutex );
+#endif
+}
+
+struct HBCond
+{
+#if defined( HB_BEOS )
+ int thread;
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
+ pthread_cond_t cond;
+#elif defined( HB_CYGWIN )
+ /* TODO */
+#endif
+
+};
+
+static inline void HBCondWait( HBCond * c, HBLock * lock )
+{
+#if defined( HB_BEOS )
+ c->thread = find_thread( NULL );
+ release_sem( lock->sem );
+ suspend_thread( c->thread );
+ acquire_sem( lock->sem );
+ c->thread = -1;
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
+ pthread_cond_wait( &c->cond, &lock->mutex );
+#elif defined( HB_CYGWIN )
+ /* TODO */
+#endif
+}
+
+static inline void HBCondSignal( HBCond * c )
+{
+#if defined( HB_BEOS )
+ while( c->thread != -1 )
+ {
+ thread_info info;
+ get_thread_info( c->thread, &info );
+ if( info.state == B_THREAD_SUSPENDED )
+ {
+ resume_thread( c->thread );
+ break;
+ }
+ /* In case HBCondSignal is called between HBCondWait's
+ release_sem() and suspend_thread() lines, wait a bit */
+ snooze( 5000 );
+ }
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
+ pthread_cond_signal( &c->cond );
+#elif defined( HB_CYGWIN )
/* TODO */
#endif
}
diff --git a/core/Utils.c b/core/Utils.c
index 566979901..f9451bb9a 100644
--- a/core/Utils.c
+++ b/core/Utils.c
@@ -1,4 +1,4 @@
-/* $Id: Utils.c,v 1.8 2003/11/12 16:09:34 titer Exp $
+/* $Id: Utils.c,v 1.14 2004/01/16 19:04:04 titer Exp $
This file is part of the HandBrake source code.
Homepage: <http://handbrake.m0k.org/>.
@@ -7,7 +7,7 @@
#include <stdarg.h>
#include <time.h>
#include <sys/time.h>
-#ifdef SYS_CYGWIN
+#ifdef HB_CYGWIN
# include <windows.h>
#endif
@@ -23,22 +23,22 @@ struct HBList
void HBSnooze( int time )
{
-#if defined( SYS_BEOS )
+#if defined( HB_BEOS )
snooze( time );
-#elif defined( SYS_MACOSX ) || defined( SYS_LINUX )
+#elif defined( HB_MACOSX ) || defined( HB_LINUX )
usleep( time );
-#elif defined( SYS_CYGWIN )
+#elif defined( HB_CYGWIN )
Sleep( time / 1000 );
#endif
}
void HBLog( char * log, ... )
{
- char string[81];
- time_t _now;
+ char string[80];
+ time_t _now;
struct tm * now;
- va_list args;
- int ret;
+ va_list args;
+ int ret;
if( !getenv( "HB_DEBUG" ) )
{
@@ -47,13 +47,13 @@ void HBLog( char * log, ... )
/* Show the time */
_now = time( NULL );
- now = localtime( &_now );
+ 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 );
+ ret = vsnprintf( string + 11, 67, log, args );
va_end( args );
/* Add the end of line */
@@ -66,7 +66,7 @@ void HBLog( char * log, ... )
uint64_t HBGetDate()
{
-#ifndef SYS_CYGWIN
+#ifndef HB_CYGWIN
struct timeval tv;
gettimeofday( &tv, NULL );
return( (uint64_t) tv.tv_sec * 1000000 + (uint64_t) tv.tv_usec );
@@ -112,11 +112,11 @@ int HBPStoES( HBBuffer ** _psBuffer, HBList * esBufferList )
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 streamId;
+ int PES_packet_length;
+ int PES_packet_end;
+ int PES_header_d_length;
+ int PES_header_end;
int hasPTS;
uint64_t PTS = 0;
@@ -163,11 +163,10 @@ int HBPStoES( HBBuffer ** _psBuffer, HBList * esBufferList )
/* 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 );
@@ -183,6 +182,8 @@ int HBPStoES( HBBuffer ** _psBuffer, HBList * esBufferList )
pos = PES_packet_end;
}
+#undef d
+
HBBufferClose( _psBuffer );
return 1;
@@ -204,14 +205,14 @@ HBList * HBListInit()
free( l );
return NULL;
}
-
+
l->allocItems = HBLIST_DEFAULT_SIZE;
l->nbItems = 0;
-
+
return l;
}
-int HBListCountItems( HBList * l )
+int HBListCount( HBList * l )
{
return l->nbItems;
}
@@ -278,7 +279,7 @@ void * HBListItemAt( HBList * l, int index )
void HBListClose( HBList ** _l )
{
HBList * l = *_l;
-
+
free( l->items );
free( l );
@@ -287,23 +288,32 @@ void HBListClose( HBList ** _l )
HBTitle * HBTitleInit( char * device, int index )
{
- HBTitle * t = calloc( sizeof( HBTitle ), 1 );
+ HBTitle * t;
+
+ if( !( t = calloc( sizeof( HBTitle ), 1 ) ) )
+ {
+ HBLog( "HBTitleInit: calloc() failed, gonna crash" );
+ return NULL;
+ }
+
+ t->device = strdup( device );
+ t->index = index;
+
+ t->codec = HB_CODEC_FFMPEG;
+ t->mux = HB_MUX_MP4;
+
+ t->audioList = HBListInit();
+ t->ripAudioList = HBListInit();
- t->device = strdup( device );
- t->index = index;
+ t->start = -1;
- 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 ) ) )
{
@@ -311,7 +321,8 @@ void HBTitleClose( HBTitle ** _t )
HBAudioClose( &audio );
}
HBListClose( &t->audioList );
-
+ HBListClose( &t->ripAudioList );
+
if( t->file ) free( t->file );
free( t->device );
free( t );
@@ -322,30 +333,23 @@ void HBTitleClose( HBTitle ** _t )
HBAudio * HBAudioInit( int id, char * language )
{
HBAudio * a;
- if( !( a = malloc( sizeof( HBAudio ) ) ) )
+ if( !( a = calloc( sizeof( HBAudio ), 1 ) ) )
{
- HBLog( "HBAudioInit: malloc() failed, gonna crash" );
+ HBLog( "HBAudioInit: calloc() 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;
-
+ a->start = -1;
+
return a;
}
void HBAudioClose( HBAudio ** _a )
{
HBAudio * a = *_a;
-
+
free( a->language );
free( a );
diff --git a/core/Utils.h b/core/Utils.h
index ba1a9101e..a83c36c65 100644
--- a/core/Utils.h
+++ b/core/Utils.h
@@ -1,4 +1,4 @@
-/* $Id: Utils.h,v 1.6 2003/11/07 21:22:17 titer Exp $
+/* $Id: Utils.h,v 1.22 2004/01/21 18:40:36 titer Exp $
This file is part of the HandBrake source code.
Homepage: <http://handbrake.m0k.org/>.
@@ -14,7 +14,7 @@
#include <unistd.h>
#include <inttypes.h>
typedef uint8_t byte_t;
-#ifdef SYS_BEOS
+#ifdef HB_BEOS
# include <OS.h>
#endif
@@ -35,27 +35,33 @@ typedef uint8_t byte_t;
#define VOUT_ASPECT_FACTOR 432000
#endif
-typedef struct HBAc3Dec HBAc3Dec;
+typedef struct HBHandle HBHandle;
+
+/* Utils */
typedef struct HBAudio HBAudio;
-typedef struct HBAviMux HBAviMux;
typedef struct HBBuffer HBBuffer;
-typedef struct HBDVDRead HBDVDRead;
+typedef struct HBCond HBCond;
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 HBThread HBThread;
+
+/* (De)Muxers */
+typedef struct HBAviMux HBAviMux;
+typedef struct HBOgmMux HBOgmMux;
+typedef struct HBDVDRead HBDVDRead;
+typedef struct HBMp4Mux HBMp4Mux;
+typedef struct HBScan HBScan;
+
typedef struct HBWork HBWork;
typedef struct HBWorkThread HBWorkThread;
-typedef struct HBXvidEnc HBXvidEnc;
+
+/* AVI stuff */
+typedef struct HBAviMainHeader HBAviMainHeader;
+typedef struct HBAviStreamHeader HBAviStreamHeader;
+typedef struct HBBitmapInfo HBBitmapInfo;
+typedef struct HBWaveFormatEx HBWaveFormatEx;
/* Misc functions which may be used from anywhere */
void HBSnooze( int time );
@@ -65,7 +71,7 @@ int HBPStoES( HBBuffer ** psBuffer, HBList * esBufferList );
/* HBList functions */
HBList * HBListInit();
-int HBListCountItems( HBList * );
+int HBListCount( HBList * );
void HBListAdd( HBList *, void * item );
void HBListRemove( HBList *, void * item );
void * HBListItemAt( HBList *, int index );
@@ -79,135 +85,143 @@ void HBTitleClose( HBTitle ** );
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;
+#define HB_SUCCESS 0x00
+#define HB_CANCELED 0x01
+#define HB_ERROR_A52_SYNC 0x02
+#define HB_ERROR_AVI_WRITE 0x04
+#define HB_ERROR_DVD_OPEN 0x08
+#define HB_ERROR_DVD_READ 0x10
+#define HB_ERROR_MP3_INIT 0x20
+#define HB_ERROR_MP3_ENCODE 0x40
+#define HB_ERROR_MPEG4_INIT 0x80
/* Possible codecs */
-typedef enum
-{
- HB_CODEC_FFMPEG = 0,
- HB_CODEC_XVID
-} HBCodec;
+#define HB_CODEC_MPEG2 0x00
+#define HB_CODEC_FFMPEG 0x01
+#define HB_CODEC_XVID 0x02
+#define HB_CODEC_AC3 0x04
+#define HB_CODEC_MP3 0x08
+#define HB_CODEC_AAC 0x10
+#define HB_CODEC_X264 0x20
+#define HB_CODEC_VORBIS 0x40
+
+/* Possible muxers */
+#define HB_MUX_AVI 0x00
+#define HB_MUX_MP4 0x01
+#define HB_MUX_OGM 0x02
-struct HBStatus
+struct HBTitle
{
- HBMode mode;
-
- /* HB_MODE_SCANNING */
- int scannedTitle;
+ /* DVD info */
+ char * device;
+ int index;
+ int length;
- /* 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 */
+ /* Audio infos */
+ HBList * audioList;
+ HBList * ripAudioList;
- /* HB_MODE_ERROR */
- HBError error;
-};
-
-struct HBTitle
-{
- char * device;
- int index;
- int length;
- char * file;
+ /* See DVDRead.c */
+ int64_t start;
/* Video input */
- int inWidth;
- int inHeight;
- int aspect;
- int rate;
- int rateBase;
+ 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;
+ int outWidth;
+ int outHeight;
+ int outWidthMax;
+ int outHeightMax;
+ int topCrop;
+ int bottomCrop;
+ int leftCrop;
+ int rightCrop;
+ int deinterlace;
+ int autoTopCrop;
+ int autoBottomCrop;
+ int autoLeftCrop;
+ int autoRightCrop;
+
+ /* Encoder settings */
+ int codec;
+ int bitrate;
+ int twoPass;
+
+ /* Muxer settings */
+ char * file;
+ int mux;
+
+ /* MP4 muxer specific */
+ int track;
+ uint8_t * esConfig;
+ int esConfigLength;
+
+ /* AVI muxer specific */
+ HBAviMainHeader * aviMainHeader;
+ HBAviStreamHeader * aviVideoHeader;
+ HBBitmapInfo * aviVideoFormat;
/* Fifos */
- HBFifo * mpeg2Fifo;
- HBFifo * rawFifo;
- HBFifo * scaledFifo;
- HBFifo * mpeg4Fifo;
+ HBFifo * inFifo;
+ HBFifo * rawFifo;
+ HBFifo * scaledFifo;
+ HBFifo * outFifo;
/* Threads */
HBDVDRead * dvdRead;
- HBMpeg2Dec * mpeg2Dec;
- HBScale * scale;
- HBFfmpegEnc * ffmpegEnc;
- HBXvidEnc * xvidEnc;
HBAviMux * aviMux;
+ HBMp4Mux * mp4Mux;
+ HBOgmMux * ogmMux;
HBWorkThread * workThreads[8];
+
+ /* Work objects */
+ HBWork * decoder;
+ HBWork * scale;
+ HBWork * encoder;
};
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;
-};
+ /* Ident */
+ uint32_t id;
+ char * language;
+
+ /* Settings */
+ int codec;
+ int inSampleRate;
+ int outSampleRate;
+ int inBitrate;
+ int outBitrate;
+
+ int delay; /* in ms */
+
+ /* See DVDRead.c */
+ int64_t start;
+
+ /* MPEG-4 config, used in the MP4 muxer */
+ uint8_t * esConfig;
+ unsigned long esConfigLength;
+ /* MP4 track id */
+ int track;
+ /* AVI stuff */
+ uint32_t aviFourCC;
+ HBAviStreamHeader * aviAudioHeader;
+ HBWaveFormatEx * aviAudioFormat;
+
+ /* Fifos */
+ HBFifo * inFifo;
+ HBFifo * rawFifo;
+ HBFifo * outFifo;
+
+ /* Work objects */
+ HBWork * decoder;
+ HBWork * encoder;;
+};
#endif
diff --git a/core/VorbisEnc.c b/core/VorbisEnc.c
new file mode 100644
index 000000000..a4f305720
--- /dev/null
+++ b/core/VorbisEnc.c
@@ -0,0 +1,257 @@
+/* $Id: VorbisEnc.c,v 1.4 2003/12/26 20:03:27 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 "HBInternal.h"
+
+/* libvorbis */
+#include <vorbis/vorbisenc.h>
+
+#define OGGVORBIS_FRAME_SIZE 1024
+
+typedef struct HBVorbisEnc
+{
+ HB_WORK_COMMON_MEMBERS
+
+ HBHandle * handle;
+ HBAudio * audio;
+
+ int inited;
+ vorbis_info vi;
+ vorbis_comment vc;
+ vorbis_dsp_state vd;
+ vorbis_block vb;
+
+ HBBuffer *rawBuffer;
+ int rawBufferPos; /* in bytes */
+ float position;
+ int32_t * inputBuffer;
+ unsigned long samplesGot;
+ unsigned long inputSamples;
+
+ HBBuffer *vorbisBuffer;
+
+ HBBuffer *header[3];
+} HBVorbisEnc;
+
+/* Local prototypes */
+static int VorbisEncWork( HBWork * );
+static int GetSamples( HBVorbisEnc * );
+
+HBWork *HBVorbisEncInit ( HBHandle *handle, HBAudio *audio )
+{
+ HBVorbisEnc *enc = malloc( sizeof( HBVorbisEnc ) );
+
+ enc->name = strdup( "VorbisEnc" );
+ enc->work = VorbisEncWork;
+
+ enc->handle = handle;
+ enc->audio = audio;
+
+ enc->inited = 0;
+ enc->rawBuffer = NULL;
+ enc->inputSamples = 2 * OGGVORBIS_FRAME_SIZE;
+ enc->inputBuffer = malloc( 2 * OGGVORBIS_FRAME_SIZE * sizeof( int32_t ) );
+ enc->samplesGot = 0;
+
+ enc->vorbisBuffer = NULL;
+
+ return (HBWork*) enc;
+}
+
+void HBVorbisEncClose( HBWork **_enc )
+{
+ HBVorbisEnc *enc = (HBVorbisEnc*) *_enc;
+
+ if( enc->inited )
+ {
+ vorbis_block_clear( &enc->vb );
+ vorbis_dsp_clear( &enc->vd );
+ vorbis_comment_clear( &enc->vc );
+ vorbis_info_clear( &enc->vi );
+ }
+
+ free( enc->name );
+ free( enc );
+
+ *_enc = NULL;
+}
+
+static HBBuffer *PacketToBuffer( ogg_packet *op )
+{
+ HBBuffer *buf = HBBufferInit( sizeof( ogg_packet ) + op->bytes );
+
+ memcpy( buf->data, op, sizeof( ogg_packet ) );
+ memcpy( buf->data + sizeof( ogg_packet ), op->packet, op->bytes );
+
+ return buf;
+}
+
+static int VorbisEncWork( HBWork *w )
+{
+ HBVorbisEnc *enc = (HBVorbisEnc*)w;
+ HBAudio *audio = enc->audio;
+ int didSomething = 0;
+
+ float **buffer;
+ int i;
+
+
+ if( !enc->inited )
+ {
+ ogg_packet header[3];
+
+ /* Get a first buffer so we know that audio->inSampleRate is correct */
+ if( ( enc->rawBuffer = HBFifoPop( audio->rawFifo ) ) == NULL )
+ {
+ return 0;
+ }
+ enc->inited = 1;
+
+ didSomething = 1;
+ enc->rawBufferPos = 0;
+ enc->position = enc->rawBuffer->position;
+
+ /* No resampling */
+ audio->outSampleRate = audio->inSampleRate;
+
+ /* init */
+ vorbis_info_init( &enc->vi );
+ if( vorbis_encode_setup_vbr( &enc->vi, 2 /* channel */, audio->inSampleRate, 1.0/* quality 0.0 -> 1.0*/ ) )
+ {
+ HBLog( "VorbisEnc: vorbis_encode_setup_vbr failed" );
+ return 0;
+ }
+ vorbis_encode_setup_init( &enc->vi );
+
+ /* add a comment */
+ vorbis_comment_init( &enc->vc );
+ vorbis_comment_add_tag( &enc->vc, "ENCODER", "Handbrake");
+
+ /* set up the analysis state and auxiliary encoding storage */
+ vorbis_analysis_init( &enc->vd, &enc->vi);
+ vorbis_block_init( &enc->vd, &enc->vb);
+
+
+ /* get the 3 headers */
+ vorbis_analysis_headerout( &enc->vd, &enc->vc,
+ &header[0], &header[1], &header[2] );
+
+ enc->header[0] = PacketToBuffer( &header[0] );
+ enc->header[1] = PacketToBuffer( &header[1] );
+ enc->header[2] = PacketToBuffer( &header[2] );
+ }
+
+ if( enc->header[0] )
+ {
+ HBLog( "VorbisEncWork: sending header 1" );
+ if( !HBFifoPush( audio->outFifo, &enc->header[0] ) )
+ {
+ return didSomething;
+ }
+ didSomething = 1;
+ }
+ if( enc->header[1] )
+ {
+ HBLog( "VorbisEncWork: sending header 2" );
+ if( !HBFifoPush( audio->outFifo, &enc->header[1] ) )
+ {
+ return didSomething;
+ }
+ didSomething = 1;
+ }
+ if( enc->header[2] )
+ {
+ HBLog( "VorbisEncWork: sending header 3" );
+ if( !HBFifoPush( audio->outFifo, &enc->header[2] ) )
+ {
+ return didSomething;
+ }
+ didSomething = 1;
+ }
+
+ /* Push already encoded data */
+ if( enc->vorbisBuffer )
+ {
+ if( !HBFifoPush( audio->outFifo, &enc->vorbisBuffer ) )
+ {
+ return didSomething;
+ }
+ }
+
+ /* Try to extract more data */
+ if( vorbis_analysis_blockout( &enc->vd, &enc->vb ) == 1 )
+ {
+ ogg_packet op;
+
+ vorbis_analysis( &enc->vb, NULL );
+ vorbis_bitrate_addblock( &enc->vb );
+
+ if( vorbis_bitrate_flushpacket( &enc->vd, &op ) )
+ {
+ enc->vorbisBuffer = PacketToBuffer( &op );
+ enc->vorbisBuffer->position = enc->position;
+ return 1;
+ }
+ }
+
+ didSomething = 1;
+
+ /* FUCK -Werror ! */
+ if( !GetSamples( enc ) )
+ {
+ return didSomething;
+ }
+
+ buffer = vorbis_analysis_buffer( &enc->vd, OGGVORBIS_FRAME_SIZE );
+ for( i = 0; i < OGGVORBIS_FRAME_SIZE; i++ )
+ {
+ buffer[0][i] = (float)enc->inputBuffer[2 * i + 0]/32768.f;
+ buffer[1][i] = (float)enc->inputBuffer[2 * i + 1]/32768.f;
+ }
+ vorbis_analysis_wrote( &enc->vd, OGGVORBIS_FRAME_SIZE );
+
+ enc->samplesGot = 0;
+
+ return 1;
+}
+
+static int GetSamples( HBVorbisEnc * f )
+{
+ while( f->samplesGot < f->inputSamples )
+ {
+ int i, copy;
+
+ if( !f->rawBuffer )
+ {
+ if( !( f->rawBuffer = HBFifoPop( f->audio->rawFifo ) ) )
+ {
+ return 0;
+ }
+
+ f->rawBufferPos = 0;
+ f->position = f->rawBuffer->position;
+ }
+
+ copy = MIN( f->inputSamples - f->samplesGot,
+ ( f->rawBuffer->samples - f->rawBufferPos ) * 2 );
+
+ for( i = 0; i < copy; i += 2 )
+ {
+ f->inputBuffer[f->samplesGot++] =
+ f->rawBuffer->left[f->rawBufferPos];
+ f->inputBuffer[f->samplesGot++] =
+ f->rawBuffer->right[f->rawBufferPos];
+ f->rawBufferPos++;
+ }
+
+ if( f->rawBufferPos == f->rawBuffer->samples )
+ {
+ HBBufferClose( &f->rawBuffer );
+ }
+ }
+
+ return 1;
+}
diff --git a/core/Work.c b/core/Work.c
index b15e50839..f2f05030a 100644
--- a/core/Work.c
+++ b/core/Work.c
@@ -1,11 +1,10 @@
-/* $Id: Work.c,v 1.4 2003/11/06 12:33:11 titer Exp $
+/* $Id: Work.c,v 1.12 2004/01/05 16:50:25 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"
+#include "HBInternal.h"
/* Local prototypes */
static void WorkThread( void * t );
@@ -17,22 +16,22 @@ struct HBWork
struct HBWorkThread
{
- HBHandle * handle;
+ HBHandle * handle;
- HBList * workList;
- int firstThread;
+ HBList * workList;
+ int firstThread;
- int die;
- HBThread * thread;
+ volatile int die;
+ HBThread * thread;
};
HBWorkThread * HBWorkThreadInit( HBHandle * handle, HBTitle * title,
- HBAudio * audio, HBAudio * optAudio,
int firstThread )
{
int i;
- HBWork * w;
-
+ HBWork * w;
+ HBAudio * audio;
+
HBWorkThread * t;
if( !( t = malloc( sizeof( HBWorkThread ) ) ) )
{
@@ -44,22 +43,17 @@ HBWorkThread * HBWorkThreadInit( HBHandle * handle, HBTitle * title,
/* 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 */
+ knowing what each one actually does */
t->workList = HBListInit();
- HBListAdd( t->workList, title->mpeg2Dec );
+ HBListAdd( t->workList, title->decoder );
HBListAdd( t->workList, title->scale );
+ HBListAdd( t->workList, title->encoder );
- 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 )
+ for( i = 0; i < HBListCount( title->ripAudioList ); i++ )
{
- HBListAdd( t->workList, optAudio->ac3Dec );
- HBListAdd( t->workList, optAudio->mp3Enc );
+ audio = HBListItemAt( title->ripAudioList, i );
+ HBListAdd( t->workList, audio->decoder );
+ HBListAdd( t->workList, audio->encoder );
}
t->firstThread = firstThread;
@@ -69,7 +63,7 @@ HBWorkThread * HBWorkThreadInit( HBHandle * handle, HBTitle * title,
is done by the first worker thread (see HBStartRip) */
if( t->firstThread )
{
- for( i = 0; i < HBListCountItems( t->workList ); i++ )
+ for( i = 0; i < HBListCount( t->workList ); i++ )
{
w = (HBWork*) HBListItemAt( t->workList, i );
w->lock = HBLockInit();
@@ -100,15 +94,15 @@ void HBWorkThreadClose( HBWorkThread ** _t )
{
int i;
uint64_t total = 0;
-
- for( i = 0; i < HBListCountItems( t->workList ); i++ )
+
+ for( i = 0; i < HBListCount( t->workList ); i++ )
{
w = (HBWork*) HBListItemAt( t->workList, i );
HBLockClose( &w->lock );
total += w->time;
}
- for( i = 0; i < HBListCountItems( t->workList ); i++ )
+ for( i = 0; i < HBListCount( t->workList ); i++ )
{
w = (HBWork*) HBListItemAt( t->workList, i );
HBLog( "HBWorkThreadClose: %- 9s = %05.2f %%", w->name,
@@ -116,12 +110,12 @@ void HBWorkThreadClose( HBWorkThread ** _t )
}
}
-
+
/* Free memory */
HBListClose( &t->workList );
free( t );
- (*_t) = NULL;
+ *_t = NULL;
}
static void WorkThread( void * _t )
@@ -131,57 +125,51 @@ static void WorkThread( void * _t )
int didSomething, i;
uint64_t date;
- for( ;; )
+ didSomething = 0;
+
+ for( i = 0; !t->die; i++ )
{
HBCheckPaused( t->handle );
-
- didSomething = 0;
- for( i = 0; i < HBListCountItems( t->workList ); i++ )
+ if( i == HBListCount( t->workList ) )
{
- if( t->die )
+ /* If nothing could be done, wait a bit to prevent a useless
+ CPU-consuming loop */
+ if( !didSomething )
{
- break;
+ HBSnooze( 5000 );
}
-
- w = (HBWork*) HBListItemAt( t->workList, i );
+ didSomething = 0;
+ i = 0;
+ }
- /* 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;
- }
+ w = (HBWork*) HBListItemAt( t->workList, i );
- /* Unlock */
- HBLockLock( w->lock );
- w->used = 0;
+ /* Check if another thread isn't using this work object */
+ HBLockLock( w->lock );
+ if( w->used )
+ {
+ /* It's in use. Forget about this one and try the next
+ one */
HBLockUnlock( w->lock );
+ continue;
}
+ /* It's unused, lock it */
+ w->used = 1;
+ HBLockUnlock( w->lock );
- if( t->die )
+ /* Do the job */
+ date = HBGetDate();
+ if( w->work( w ) )
{
- break;
+ w->time += HBGetDate() - date;
+ didSomething = 1;
}
- /* If nothing could be done, wait a bit to prevent a useless
- CPU-consuming loop */
- if( !didSomething )
- {
- HBSnooze( 10000 );
- }
+ /* Unlock it */
+ HBLockLock( w->lock );
+ w->used = 0;
+ HBLockUnlock( w->lock );
}
}
diff --git a/core/Work.h b/core/Work.h
index 8d3cfba15..b764e1160 100644
--- a/core/Work.h
+++ b/core/Work.h
@@ -1,4 +1,4 @@
-/* $Id: Work.h,v 1.1 2003/11/03 12:08:01 titer Exp $
+/* $Id: Work.h,v 1.4 2003/12/26 20:03:27 titer Exp $
This file is part of the HandBrake source code.
Homepage: <http://handbrake.m0k.org/>.
@@ -7,8 +7,6 @@
#ifndef HB_WORK_H
#define HB_WORK_H
-#include "HandBrakeInternal.h"
-
#define HB_WORK_COMMON_MEMBERS \
char * name; \
HBLock * lock; \
@@ -16,12 +14,8 @@
uint64_t time; \
int (*work) ( HBWork * );
-void HBWorkLock( HBWork * );
-void HBWorkWork( HBWork * );
-void HBWorkUnlock( HBWork * );
-
-HBWorkThread * HBWorkThreadInit( HBHandle *, HBTitle *, HBAudio *,
- HBAudio *, int firstThread );
+HBWorkThread * HBWorkThreadInit( HBHandle *, HBTitle *,
+ int firstThread );
void HBWorkThreadClose( HBWorkThread ** );
#endif
diff --git a/core/X264Enc.c b/core/X264Enc.c
new file mode 100644
index 000000000..50b9ab8bf
--- /dev/null
+++ b/core/X264Enc.c
@@ -0,0 +1,167 @@
+/* $Id: X264Enc.c,v 1.3 2003/12/26 20:03:27 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 "HBInternal.h"
+
+/* x264 */
+#include "x264.h"
+
+typedef struct HBX264Enc
+{
+ HB_WORK_COMMON_MEMBERS
+
+ HBHandle *handle;
+ HBTitle *title;
+
+ HBBuffer *buffer;
+
+ x264_t *h;
+ x264_picture_t picture;
+} HBX264Enc;
+
+/* Local prototypes */
+static int HBX264EncWork( HBWork * );
+
+HBWork *HBX264EncInit( HBHandle * handle, HBTitle * title )
+{
+ HBX264Enc *f = malloc( sizeof( HBX264Enc ) );
+
+ if( f )
+ {
+ x264_param_t param;
+
+ f->name = strdup( "X264Enc" );
+ f->work = HBX264EncWork;
+
+ f->handle = handle;
+ f->title = title;
+
+ f->buffer = NULL;
+
+ x264_param_default( &param );
+
+ param.i_width = title->outWidth;
+ param.i_height= title->outHeight;
+ param.i_iframe = 5 * title->rate / title->rateBase;
+ /* FIXME */
+ param.b_deblocking_filter = 0;
+ param.i_me = 1;
+
+ if( ( f->h = x264_encoder_open( &param ) ) == NULL )
+ {
+ HBLog( "x264: x264_encoder_new failed" );
+ return NULL;
+ }
+ memset( &f->picture, 0, sizeof( x264_picture_t ) );
+ f->picture.i_width = param.i_width;
+ f->picture.i_height = param.i_height;
+ f->picture.i_plane = 3;
+
+ HBLog( "x264: opening with %dx%d iframes=%d", param.i_width, param.i_height, param.i_iframe );
+ }
+
+ return (HBWork*) f;
+}
+
+void HBX264EncClose( HBWork **_f )
+{
+ HBX264Enc *f = (HBX264Enc*) *_f;
+
+ x264_encoder_close( f->h );
+
+ if( f->buffer )
+ {
+ HBBufferClose( &f->buffer );
+ }
+
+ free( f->name );
+
+ free( f );
+
+ *_f = NULL;
+}
+
+/* TODO trash buffer->pass == 1
+ * return 0 ->rien fait
+ * 1 -> sinon
+ */
+static int HBX264EncWork( HBWork * w )
+{
+ HBX264Enc * f = (HBX264Enc*) w;
+ HBTitle * title = f->title;
+
+ HBBuffer * frame;
+ int didSomething = 0;
+
+ x264_nal_t *nal;
+ int i_nal;
+ int i;
+
+ if( f->buffer )
+ {
+ if( !HBFifoPush( title->outFifo, &f->buffer ) )
+ {
+ /* nothing done */
+ return 0;
+ }
+ didSomething = 1;
+ }
+
+ if( ( frame = HBFifoPop( title->scaledFifo ) ) == NULL )
+ {
+ return didSomething;
+ }
+
+ if( frame->pass == 1 )
+ {
+ /* Trash all first pass buffer */
+ HBBufferClose( &frame );
+ return 1;
+ }
+
+ f->picture.i_stride[0] = title->outWidth;
+ f->picture.i_stride[1] = title->outWidth/2;
+ f->picture.i_stride[2] = title->outWidth/2;
+
+ f->picture.plane[0] = frame->data;
+ f->picture.plane[1] = &f->picture.plane[0][title->outWidth*title->outHeight];
+ f->picture.plane[2] = &f->picture.plane[1][title->outWidth*title->outHeight/4];
+
+ x264_encoder_encode( f->h, &nal, &i_nal, &f->picture );
+
+ f->buffer = HBBufferInit( 3 * title->outWidth * title->outHeight / 2 ); /* FIXME */
+ f->buffer->keyFrame = 0;
+ f->buffer->position = frame->position;
+ f->buffer->size = 0;
+
+ for( i = 0; i < i_nal; i++ )
+ {
+ int i_data = f->buffer->alloc - f->buffer->size;
+ int i_size;
+
+ i_size = x264_nal_encode( &f->buffer->data[f->buffer->size],
+ &i_data, 1, &nal[i] );
+ if( i_size <= 0 )
+ {
+ fprintf( stderr, "#################### error" );
+ }
+
+ f->buffer->size += i_size;
+
+ if( nal[i].i_ref_idc == NAL_PRIORITY_HIGH ||
+ nal[i].i_ref_idc == NAL_PRIORITY_HIGHEST )
+ {
+ f->buffer->keyFrame = 1;
+ }
+ }
+
+ /* Inform the GUI about the current position */
+ HBPosition( f->handle, frame->position );
+
+ HBBufferClose( &frame );
+
+ return 1;
+}
diff --git a/core/XvidEnc.c b/core/XvidEnc.c
index 2ca6bca6f..fe9e8ddbc 100644
--- a/core/XvidEnc.c
+++ b/core/XvidEnc.c
@@ -1,34 +1,33 @@
-/* $Id: XvidEnc.c,v 1.7 2003/11/09 21:26:52 titer Exp $
+/* $Id: XvidEnc.c,v 1.18 2004/01/08 22:02:29 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 "Work.h"
-#include "XvidEnc.h"
-#include "XvidVbr.h"
+#include "HBInternal.h"
-#include <xvid.h>
+#include "xvid.h"
-/* Local prototypes */
-static int XvidEncWork( HBWork * );
-
-struct HBXvidEnc
+typedef struct HBXvidEnc
{
HB_WORK_COMMON_MEMBERS
HBHandle * handle;
HBTitle * title;
+ char file[1024];
void * xvid;
- vbr_control_t xvidVbr;
- XVID_ENC_FRAME frame;
+ xvid_enc_frame_t frame;
HBBuffer * mpeg4Buffer;
int pass;
-};
+ int frames;
+ int64_t bytes;
+} HBXvidEnc;
+
+/* Local prototypes */
+static int XvidEncWork( HBWork * );
-HBXvidEnc * HBXvidEncInit( HBHandle * handle, HBTitle * title )
+HBWork * HBXvidEncInit( HBHandle * handle, HBTitle * title )
{
HBXvidEnc * x;
if( !( x = malloc( sizeof( HBXvidEnc ) ) ) )
@@ -43,38 +42,53 @@ HBXvidEnc * HBXvidEncInit( HBHandle * handle, HBTitle * title )
x->handle = handle;
x->title = title;
- x->xvid = NULL;
-
- x->frame.general = XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V;
- x->frame.motion = PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 |
- PMV_EXTSEARCH16 | PMV_EARLYSTOP8 |
- PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8 |
- PMV_USESQUARES16;
-
- x->frame.colorspace = XVID_CSP_I420;
-
- x->frame.quant_intra_matrix = NULL;
- x->frame.quant_inter_matrix = NULL;
+ memset( x->file, 0, 1024 );
+ snprintf( x->file, 1023, "/tmp/HB.%d.xvid.log",
+ HBGetPid( x->handle ) );
+ x->xvid = NULL;
x->mpeg4Buffer = NULL;
x->pass = 42;
+ x->frames = 0;
+ x->bytes = 0;
- return x;
+ return (HBWork*) x;
}
-void HBXvidEncClose( HBXvidEnc ** _x )
+void HBXvidEncClose( HBWork ** _x )
{
- HBXvidEnc * x = *_x;
+ HBXvidEnc * x = (HBXvidEnc*) *_x;
if( x->xvid )
{
HBLog( "HBXvidEnc: closing libxvidcore (pass %d)",
x->pass );
-
xvid_encore( x->xvid, XVID_ENC_DESTROY, NULL, NULL);
- vbrFinish( &x->xvidVbr );
}
-
+ if( x->frames )
+ {
+ float bitrate = (float) x->bytes * x->title->rate / x->frames /
+ x->title->rateBase / 128;
+ int64_t bytes = (int64_t) x->frames * x->title->bitrate * 128 *
+ x->title->rateBase / x->title->rate;
+
+ HBLog( "HBXvidEnc: %d frames encoded (%lld bytes), %.2f kbps",
+ x->frames, x->bytes, bitrate );
+
+ if( x->bytes > bytes )
+ {
+ HBLog( "HBXvidEnc: %lld more bytes than expected "
+ "(error=%.2f %%)", x->bytes - bytes,
+ 100.0 * ( x->bytes - bytes ) / bytes );
+ }
+ else if( x->bytes < bytes )
+ {
+ HBLog( "HBXvidEnc: %lld less bytes than expected "
+ "(error=%.2f %%)", bytes - x->bytes,
+ 100.0 * ( bytes - x->bytes ) / bytes );
+ }
+ }
+ free( x->name );
free( x );
*_x = NULL;
@@ -86,13 +100,12 @@ static int XvidEncWork( HBWork * w )
HBTitle * title = x->title;
HBBuffer * scaledBuffer;
HBBuffer * mpeg4Buffer;
- XVID_ENC_STATS stats;
int didSomething = 0;
if( x->mpeg4Buffer )
{
- if( HBFifoPush( title->mpeg4Fifo, &x->mpeg4Buffer ) )
+ if( HBFifoPush( title->outFifo, &x->mpeg4Buffer ) )
{
didSomething = 1;
}
@@ -114,8 +127,12 @@ static int XvidEncWork( HBWork * w )
/* Init or re-init if needed */
if( scaledBuffer->pass != x->pass )
{
- XVID_INIT_PARAM xinit;
- XVID_ENC_PARAM xparam;
+ xvid_gbl_init_t xvid_gbl_init;
+ xvid_enc_create_t xvid_enc_create;
+ xvid_plugin_single_t single;
+ xvid_plugin_2pass1_t rc2pass1;
+ xvid_plugin_2pass2_t rc2pass2;
+ xvid_enc_plugin_t plugins[7];
if( x->xvid )
{
@@ -123,89 +140,93 @@ static int XvidEncWork( HBWork * w )
x->pass );
xvid_encore( x->xvid, XVID_ENC_DESTROY, NULL, NULL);
- vbrFinish( &x->xvidVbr );
}
x->pass = scaledBuffer->pass;;
-
HBLog( "HBXvidEnc: opening libxvidcore (pass %d)", x->pass );
- xinit.cpu_flags = 0;
- xvid_init( NULL, 0, &xinit, NULL );
+ memset( &xvid_gbl_init, 0, sizeof( xvid_gbl_init ) );
+ xvid_gbl_init.version = XVID_VERSION;
+ xvid_global( NULL, XVID_GBL_INIT, &xvid_gbl_init, NULL );
- xparam.width = title->outWidth;
- xparam.height = title->outHeight;
+ memset(&xvid_enc_create, 0, sizeof(xvid_enc_create));
+ xvid_enc_create.version = XVID_VERSION;
+ xvid_enc_create.width = title->outWidth;
+ xvid_enc_create.height = title->outHeight;
+ xvid_enc_create.zones = NULL;
+ xvid_enc_create.num_zones = 0;
+ xvid_enc_create.plugins = plugins;
+ xvid_enc_create.num_plugins = 0;
- xparam.fincr = title->rateBase;
- xparam.fbase = title->rate;
-
- xparam.rc_bitrate = title->bitrate * 1024;
-
- /* 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;
-
- /* Init VBR engine */
- vbrSetDefaults( &x->xvidVbr );
if( !x->pass )
{
- x->xvidVbr.mode = VBR_MODE_1PASS;
+ memset( &single, 0, sizeof( single ) );
+ single.version = XVID_VERSION;
+ single.bitrate = 1024 * title->bitrate;
+ plugins[xvid_enc_create.num_plugins].func = xvid_plugin_single;
+ plugins[xvid_enc_create.num_plugins].param = &single;
+ xvid_enc_create.num_plugins++;
}
else if( x->pass == 1 )
{
- x->xvidVbr.mode = VBR_MODE_2PASS_1;
+ memset( &rc2pass1, 0, sizeof( rc2pass1 ) );
+ rc2pass1.version = XVID_VERSION;
+ rc2pass1.filename = x->file;
+ plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass1;
+ plugins[xvid_enc_create.num_plugins].param = &rc2pass1;
+ xvid_enc_create.num_plugins++;
}
- else
+ else if( x->pass == 2 )
{
- x->xvidVbr.mode = VBR_MODE_2PASS_2;
+ memset(&rc2pass2, 0, sizeof(xvid_plugin_2pass2_t));
+ rc2pass2.version = XVID_VERSION;
+ rc2pass2.filename = x->file;
+ rc2pass2.bitrate = 1024 * title->bitrate;
+ plugins[xvid_enc_create.num_plugins].func = xvid_plugin_2pass2;
+ plugins[xvid_enc_create.num_plugins].param = &rc2pass2;
+ xvid_enc_create.num_plugins++;
}
- x->xvidVbr.fps = (double) title->rate / title->rateBase;
- x->xvidVbr.debug = 0;
- x->xvidVbr.filename = malloc( 1024 );
- memset( x->xvidVbr.filename, 0, 1024 );
- snprintf( x->xvidVbr.filename, 1023, "/tmp/HB.%d.xvid.log",
- HBGetPid( x->handle ) );
- x->xvidVbr.desired_bitrate = title->bitrate * 1024;
- x->xvidVbr.max_key_interval = 10 * title->rate / title->rateBase;
-
- vbrInit( &x->xvidVbr );
+
+ xvid_enc_create.num_threads = 0;
+ xvid_enc_create.fincr = title->rateBase;
+ xvid_enc_create.fbase = title->rate;
+ xvid_enc_create.max_key_interval = 10 * title->rate / title->rateBase;
+ xvid_enc_create.max_bframes = 0;
+ xvid_enc_create.bquant_ratio = 150;
+ xvid_enc_create.bquant_offset = 100;
+ xvid_enc_create.frame_drop_ratio = 0;
+ xvid_enc_create.global = 0;
+
+ xvid_encore( NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL );
+ x->xvid = xvid_enc_create.handle;
}
mpeg4Buffer = HBBufferInit( title->outWidth *
title->outHeight * 3 / 2 );
mpeg4Buffer->position = scaledBuffer->position;
+ memset( &x->frame, 0, sizeof( x->frame ) );
+ x->frame.version = XVID_VERSION;
x->frame.bitstream = mpeg4Buffer->data;
- x->frame.length = -1;
-
- x->frame.image = scaledBuffer->data;
-
- x->frame.quant = vbrGetQuant( &x->xvidVbr );
- x->frame.intra = vbrGetIntra( &x->xvidVbr );
-
- x->frame.hint.hintstream = NULL;
-
- if( xvid_encore( x->xvid, XVID_ENC_ENCODE, &x->frame, &stats ) )
- {
- HBLog( "HBXvidEnc: xvid_encore() failed" );
- }
-
- vbrUpdate( &x->xvidVbr, stats.quant, x->frame.intra, stats.hlength,
- x->frame.length, stats.kblks, stats.mblks, stats.ublks );
+ x->frame.length = -1;
+ x->frame.input.plane[0] = scaledBuffer->data;
+ x->frame.input.csp = XVID_CSP_I420;
+ x->frame.input.stride[0] = title->outWidth;
+ x->frame.vol_flags = 0;
+ x->frame.vop_flags = XVID_VOP_HALFPEL | XVID_VOP_INTER4V |
+ XVID_VOP_TRELLISQUANT | XVID_VOP_HQACPRED;
+ x->frame.type = XVID_TYPE_AUTO;
+ x->frame.quant = 0;
+ x->frame.motion = XVID_ME_ADVANCEDDIAMOND16 | XVID_ME_HALFPELREFINE16 |
+ XVID_ME_EXTSEARCH16 | XVID_ME_ADVANCEDDIAMOND8 |
+ XVID_ME_HALFPELREFINE8 | XVID_ME_EXTSEARCH8 |
+ XVID_ME_CHROMA_PVOP | XVID_ME_CHROMA_BVOP;
+ x->frame.quant_intra_matrix = NULL;
+ x->frame.quant_inter_matrix = NULL;
- mpeg4Buffer->size = x->frame.length;
- mpeg4Buffer->keyFrame = x->frame.intra;
+ mpeg4Buffer->size = xvid_encore( x->xvid, XVID_ENC_ENCODE,
+ &x->frame, NULL );
+ mpeg4Buffer->keyFrame = ( x->frame.out_flags & XVID_KEYFRAME );
/* Inform the GUI about the current position */
HBPosition( x->handle, scaledBuffer->position );
@@ -217,8 +238,20 @@ static int XvidEncWork( HBWork * w )
HBBufferClose( &mpeg4Buffer );
return didSomething;
}
+ else
+ {
+ if( !title->esConfig )
+ {
+ /* KLUDGE */
+ title->esConfig = malloc( 15 );
+ title->esConfigLength = 15;
+ memcpy( title->esConfig, mpeg4Buffer->data + 4, 15 );
+ }
+ x->frames++;
+ x->bytes += mpeg4Buffer->size;
+ x->mpeg4Buffer = mpeg4Buffer;
+ }
- x->mpeg4Buffer = mpeg4Buffer;
return didSomething;
}
diff --git a/core/XvidEnc.h b/core/XvidEnc.h
deleted file mode 100644
index 01cb6f4d4..000000000
--- a/core/XvidEnc.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $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
diff --git a/core/XvidVbr.c b/core/XvidVbr.c
deleted file mode 100644
index ce66c3769..000000000
--- a/core/XvidVbr.c
+++ /dev/null
@@ -1,1648 +0,0 @@
-/******************************************************************************
- *
- * XviD VBR Library
- *
- * Copyright (C) 2002 Edouard Gomez <[email protected]>
- *
- * The curve treatment algorithm is based on work done by Foxer <email?> and
- * Dirk Knop <[email protected]> for the XviD vfw dynamic library.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *****************************************************************************/
-
-/* Standard Headers */
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <math.h>
-
-/* Local headers */
-#include "XvidVbr.h"
-
-/******************************************************************************
- * Build time constants
- *****************************************************************************/
-
-/*
- * Portability note
- * Perhaps the msvc headers define Pi with another constant name
- */
-#define DEG2RAD (M_PI / 180.0)
-
-/* Defaults settings will be computed with the help of these constants */
-#define DEFAULT_DESIRED_SIZE 700
-#define DEFAULT_AUDIO_BITRATE 128
-#define DEFAULT_MOVIE_LENGTH 2
-#define DEFAULT_TWOPASS_BOOST 1000
-#define DEFAULT_FPS 25.0f
-#define DEFAULT_CREDITS_SIZE 0
-
-#define DEFAULT_XVID_DBG_FILE "xvid.dbg"
-#define DEFAULT_XVID_STATS_FILE "xvid.stats"
-
-
-/******************************************************************************
- * Local prototypes
- *****************************************************************************/
-
-/* Sub vbrInit cases functions */
-static vbr_init_function vbr_init_dummy;
-static vbr_init_function vbr_init_2pass1;
-static vbr_init_function vbr_init_2pass2;
-static vbr_init_function vbr_init_fixedquant;
-
-/* Sub vbrGetQuant cases functions */
-static vbr_get_quant_function vbr_getquant_1pass;
-static vbr_get_quant_function vbr_getquant_2pass1;
-static vbr_get_quant_function vbr_getquant_2pass2;
-static vbr_get_quant_function vbr_getquant_fixedquant;
-
-/* Sub vbrGetIntra cases functions */
-static vbr_get_intra_function vbr_getintra_1pass;
-static vbr_get_intra_function vbr_getintra_2pass1;
-static vbr_get_intra_function vbr_getintra_2pass2;
-static vbr_get_intra_function vbr_getintra_fixedquant;
-
-/* Sub vbrUpdate prototypes */
-static vbr_update_function vbr_update_dummy;
-static vbr_update_function vbr_update_2pass1;
-static vbr_update_function vbr_update_2pass2;
-
-/* Sub vbrFinish cases functions */
-static vbr_finish_function vbr_finish_dummy;
-static vbr_finish_function vbr_finish_2pass1;
-static vbr_finish_function vbr_finish_2pass2;
-
-/* Is the encoder in the credits */
-#define FRAME_TYPE_NORMAL_MOVIE 0x00
-#define FRAME_TYPE_STARTING_CREDITS 0x01
-#define FRAME_TYPE_ENDING_CREDITS 0x02
-
-/******************************************************************************
- * Inline utility functions
- *****************************************************************************/
-
-static __inline int util_frametype(vbr_control_t *state)
-{
-
- if(state->credits_start) {
-
- if(state->cur_frame >= state->credits_start_begin &&
- state->cur_frame < state->credits_start_end)
- return(FRAME_TYPE_STARTING_CREDITS);
-
- }
-
- if(state->credits_end) {
-
- if(state->cur_frame >= state->credits_end_begin &&
- state->cur_frame < state->credits_end_end)
- return(FRAME_TYPE_ENDING_CREDITS);
-
- }
-
- return(FRAME_TYPE_NORMAL_MOVIE);
-
-
-}
-
-static __inline int util_creditsframes(vbr_control_t *state)
-{
-
- int frames = 0;
-
- if(state->credits_start)
- frames += state->credits_start_end - state->credits_start_begin;
- if(state->credits_end)
- frames += state->credits_end_end - state->credits_end_begin;
-
- return(frames);
-
-}
-
-/******************************************************************************
- * Functions
- *****************************************************************************/
-
-/*****************************************************************************
- * Function description :
- *
- * This function initialiazes the vbr_control_t with safe defaults for all
- * modes.
- *
- * Return Values :
- * = 0
- ****************************************************************************/
-
-int vbrSetDefaults(vbr_control_t *state)
-{
-
- /* Set all the structure to zero */
- memset(state, 0, sizeof(state));
-
- /* Default mode is CBR */
- state->mode = VBR_MODE_1PASS;
-
- /* Default statistic filename */
- state->filename = DEFAULT_XVID_STATS_FILE;
-
- /*
- * Default is a 2hour movie on 700Mo CD-ROM + 128kbit sound track
- * This represents a target bitrate of 687kbit/s
- */
- state->desired_size = DEFAULT_DESIRED_SIZE*1024*1024 -
- DEFAULT_MOVIE_LENGTH*3600*DEFAULT_AUDIO_BITRATE*1000/8;
- state->desired_bitrate = state->desired_size*8/(DEFAULT_MOVIE_LENGTH*3600);
-
- /* Credits */
- state->credits_mode = VBR_CREDITS_MODE_RATE;
- state->credits_start = 0;
- state->credits_start_begin = 0;
- state->credits_start_end = 0;
- state->credits_end = 0;
- state->credits_end_begin = 0;
- state->credits_end_end = 0;
- state->credits_quant_ratio = 20;
- state->credits_fixed_quant = 20;
- state->credits_quant_i = 20;
- state->credits_quant_p = 20;
- state->credits_start_size = DEFAULT_CREDITS_SIZE*1024*1024;
- state->credits_end_size = DEFAULT_CREDITS_SIZE*1024*1024;
-
- /* Keyframe boost */
- state->keyframe_boost = 0;
- state->kftreshold = 10;
- state->kfreduction = 30;
- state->min_key_interval = 1;
- state->max_key_interval = (int)DEFAULT_FPS*10;
-
- /* Normal curve treatment */
- state->curve_compression_high = 25;
- state->curve_compression_low = 10;
-
- /* Alt curve */
- state->use_alt_curve = 1;
- state->alt_curve_type = VBR_ALT_CURVE_LINEAR;
- state->alt_curve_low_dist = 90;
- state->alt_curve_high_dist = 500;
- state->alt_curve_min_rel_qual = 50;
- state->alt_curve_use_auto = 1;
- state->alt_curve_auto_str = 30;
- state->alt_curve_use_auto_bonus_bias = 1;
- state->alt_curve_bonus_bias = 50;
- state->bitrate_payback_method = VBR_PAYBACK_BIAS;
- state->bitrate_payback_delay = 250;
- state->twopass_max_bitrate = DEFAULT_TWOPASS_BOOST*state->desired_bitrate;
- state->twopass_max_overflow_improvement = 60;
- state->twopass_max_overflow_degradation = 60;
- state->max_iquant = 31;
- state->min_iquant = 2;
- state->max_pquant = 31;
- state->min_pquant = 2;
- state->fixed_quant = 3;
-
- state->max_framesize = (1.0/(float)DEFAULT_FPS) * state->twopass_max_bitrate / 8;
-
- state->fps = (float)DEFAULT_FPS;
-
- return(0);
-
-}
-
-/*****************************************************************************
- * Function description :
- *
- * This function initialiaze the vbr_control_t state passed in parameter.
- *
- * The initialization depends on state->mode, there are 4 modes allowed.
- * Each mode description is done in the README file shipped with the lib.
- *
- * Return values :
- *
- * = 0 on success
- * = -1 on error
- *****************************************************************************/
-
-int vbrInit(vbr_control_t *state)
-{
-
- if(state == NULL) return(-1);
-
- /* Function pointers safe initialization */
- state->init = NULL;
- state->getquant = NULL;
- state->getintra = NULL;
- state->update = NULL;
- state->finish = NULL;
-
- if(state->debug) {
-
- state->debug_file = fopen(DEFAULT_XVID_DBG_FILE, "w+");
-
- if(state->debug_file == NULL)
- return(-1);
-
- fprintf(state->debug_file, "# XviD Debug output\n");
- fprintf(state->debug_file, "# quant | intra | header bytes"
- "| total bytes | kblocks | mblocks | ublocks"
- "| vbr overflow | vbr kf overflow"
- "| vbr kf partial overflow\n\n");
- }
-
- /* Function pointers sub case initialization */
- switch(state->mode) {
- case VBR_MODE_1PASS:
- state->init = vbr_init_dummy;
- state->getquant = vbr_getquant_1pass;
- state->getintra = vbr_getintra_1pass;
- state->update = vbr_update_dummy;
- state->finish = vbr_finish_dummy;
- break;
- case VBR_MODE_2PASS_1:
- state->init = vbr_init_2pass1;
- state->getquant = vbr_getquant_2pass1;
- state->getintra = vbr_getintra_2pass1;
- state->update = vbr_update_2pass1;
- state->finish = vbr_finish_2pass1;
- break;
- case VBR_MODE_FIXED_QUANT:
- state->init = vbr_init_fixedquant;
- state->getquant = vbr_getquant_fixedquant;
- state->getintra = vbr_getintra_fixedquant;
- state->update = vbr_update_dummy;
- state->finish = vbr_finish_dummy;
- break;
- case VBR_MODE_2PASS_2:
- state->init = vbr_init_2pass2;
- state->getintra = vbr_getintra_2pass2;
- state->getquant = vbr_getquant_2pass2;
- state->update = vbr_update_2pass2;
- state->finish = vbr_finish_2pass2;
- break;
- default:
- return(-1);
- }
-
- return(state->init(state));
-
-}
-
-/******************************************************************************
- * Function description :
- *
- * This function returns an adapted quantizer according to the current vbr
- * controler state
- *
- * Return values :
- * the quantizer value (0 <= value <= 31)
- * (0 is a special case, means : let XviD decide)
- *
- *****************************************************************************/
-
-int vbrGetQuant(vbr_control_t *state)
-{
-
- /* Returns Zero, so XviD decides alone */
- if(state == NULL || state->getquant == NULL) return(0);
-
- return(state->getquant(state));
-
-}
-
-/******************************************************************************
- * Function description :
- *
- * This function returns the type of the frame to be encoded next (I or P/B)
- *
- * Return values :
- * = -1 let the XviD encoder decide wether or not the next frame is I
- * = 0 no I frame
- * = 1 force keyframe
- *
- *****************************************************************************/
-
-int vbrGetIntra(vbr_control_t *state)
-{
-
- /* Returns -1, means let XviD decide */
- if(state == NULL || state->getintra == NULL) return(-1);
-
- return(state->getintra(state));
-
-}
-
-/******************************************************************************
- * Function description :
- *
- * This function updates the vbr control state according to collected statistics
- * from XviD core
- *
- * Return values :
- *
- * = 0 on success
- * = -1 on error
- *****************************************************************************/
-
-int vbrUpdate(vbr_control_t *state,
- int quant,
- int intra,
- int header_bytes,
- int total_bytes,
- int kblocks,
- int mblocks,
- int ublocks)
-{
-
- if(state == NULL || state->update == NULL) return(-1);
-
- if(state->debug && state->debug_file != NULL) {
- int idx;
-
- fprintf(state->debug_file, "%d %d %d %d %d %d %d %d %d %d\n",
- quant, intra, header_bytes, total_bytes, kblocks,
- mblocks, ublocks, state->overflow, state->KFoverflow,
- state->KFoverflow_partial);
-
- idx = quant;
-
- if(quant < 1)
- idx = 1;
- if(quant > 31)
- idx = 31;
-
- idx--;
-
- state->debug_quant_count[idx]++;
-
- }
-
- return(state->update(state, quant, intra, header_bytes, total_bytes,
- kblocks, mblocks, ublocks));
-
-}
-
-/******************************************************************************
- * Function description :
- *
- * This function stops the vbr controller
- *
- * Return values :
- *
- * = 0 on success
- * = -1 on error
- *****************************************************************************/
-
-int vbrFinish(vbr_control_t *state)
-{
-
- if(state == NULL || state->finish == NULL) return(-1);
-
- if(state->debug && state->debug_file != NULL) {
-
- int i;
-
- fprintf(state->debug_file, "\n\n");
-
- for(i=0; i<79; i++)
- fprintf(state->debug_file, "#");
-
- fprintf(state->debug_file, "\n# Quantizer distribution :\n\n");
-
- for(i=0;i<32; i++) {
-
- fprintf(state->debug_file, "# quant %d : %d\n",
- i+1,
- state->debug_quant_count[i]);
-
- }
-
- fclose(state->debug_file);
-
- }
-
- return(state->finish(state));
-
-}
-
-/******************************************************************************
- * Dummy functions - Used when a mode does not need such a function
- *****************************************************************************/
-
-static int vbr_init_dummy(void *sstate)
-{
-
- vbr_control_t *state = sstate;
-
- state->cur_frame = 0;
-
- return(0);
-
-}
-
-static int vbr_update_dummy(void *state,
- int quant,
- int intra,
- int header_bytes,
- int total_bytes,
- int kblocks,
- int mblocks,
- int ublocks)
-{
-
- ((vbr_control_t*)state)->cur_frame++;
-
- return(0);
-
-}
-
-static int vbr_finish_dummy(void *state)
-{
-
- return(0);
-
-}
-
-/******************************************************************************
- * 1 pass mode - XviD will do its job alone.
- *****************************************************************************/
-
-static int vbr_getquant_1pass(void *state)
-{
-
- return(0);
-
-}
-
-static int vbr_getintra_1pass(void *state)
-{
-
- return(-1);
-
-}
-
-/******************************************************************************
- * 2 pass mode - first pass functions
- *****************************************************************************/
-
-static int vbr_init_2pass1(void *sstate)
-{
-
- FILE *f;
- vbr_control_t *state = sstate;
-
- /* Check the filename */
- if(state->filename == NULL || state->filename[0] == '\0')
- return(-1);
-
- /* Initialize safe defaults for 2pass 1 */
- state->pass1_file = NULL;
- state->nb_frames = 0;
- state->nb_keyframes = 0;
- state->cur_frame = 0;
-
- /* Open the 1st pass file */
- if((f = fopen(state->filename, "w+")) == NULL)
- return(-1);
-
- /*
- * The File Header
- *
- * The extra white spaces will be used during the vbrFinish to write
- * the resulting number of frames and keyframes (10 spaces == maximum
- * string length of an int on 32bit machines, i don't think anyone is
- * encoding more than 4 billion frames :-)
- */
- fprintf(f, "# ASCII XviD vbr stat file version %d\n#\n", VBR_VERSION);
- fprintf(f, "# frames : \n");
- fprintf(f, "# keyframes : \n");
- fprintf(f, "#\n# quant | intra | header bytes | total bytes | kblocks |"
- " mblocks | ublocks\n\n");
-
- /* Save file pointer */
- state->pass1_file = f;
-
- return(0);
-
-}
-
-static int vbr_getquant_2pass1(void *state)
-{
-
- return(2);
-
-}
-
-static int vbr_getintra_2pass1(void *state)
-{
-
- return(-1);
-
-}
-
-static int vbr_update_2pass1(void *sstate,
- int quant,
- int intra,
- int header_bytes,
- int total_bytes,
- int kblocks,
- int mblocks,
- int ublocks)
-
-
-{
-
- vbr_control_t *state = sstate;
-
- if(state->pass1_file == NULL)
- return(-1);
-
- /* Writes the resulting statistics */
- fprintf(state->pass1_file, "%d %d %d %d %d %d %d\n",
- quant,
- intra,
- header_bytes,
- total_bytes,
- kblocks,
- mblocks,
- ublocks);
-
- /* Update vbr control state */
- if(intra) state->nb_keyframes++;
- state->nb_frames++;
- state->cur_frame++;
-
- return(0);
-
-}
-
-static int vbr_finish_2pass1(void *sstate)
-{
-
- int c, i;
- vbr_control_t *state = sstate;
-
- if(state->pass1_file == NULL)
- return(-1);
-
- /* Goto to the file beginning */
- fseek(state->pass1_file, 0, SEEK_SET);
-
- /* Skip the version line and the empty line */
- c = i = 0;
- do {
- c = fgetc(state->pass1_file);
-
- if(c == EOF) return(-1);
- if(c == '\n') i++;
-
- }while(i < 2);
-
- /* Prepare to write to the stream */
- fseek( state->pass1_file, 0L, SEEK_CUR );
-
- /* Overwrite the frame field - safe as we have written extra spaces */
- fprintf(state->pass1_file, "# frames : %.10d\n", state->nb_frames);
-
- /* Overwrite the keyframe field */
- fprintf(state->pass1_file, "# keyframes : %.10d\n",
- state->nb_keyframes);
-
- /* Close the file */
- if(fclose(state->pass1_file) != 0)
- return(-1);
-
- return(0);
-
-}
-
-/******************************************************************************
- * 2 pass mode - 2nd pass functions (Need to be finished)
- *****************************************************************************/
-
-static int vbr_init_2pass2(void *sstate)
-{
-
- FILE *f;
- int c, n, pos_firstframe, credits_frames;
- long long credits1_bytes;
- long long credits2_bytes;
- long long desired;
- long long total_bytes;
- long long itotal_bytes;
- long long start_curved;
- long long end_curved;
- double total1;
- double total2;
-
- vbr_control_t *state = sstate;
-
- /* Check the filename */
- if(state->filename == NULL || state->filename[0] == '\0')
- return(-1);
-
- /* Initialize safe defaults for 2pass 2 */
- state->pass1_file = NULL;
- state->nb_frames = 0;
- state->nb_keyframes = 0;
-
- /* Open the 1st pass file */
- if((f = fopen(state->filename, "r")) == NULL)
- return(-1);
-
- state->pass1_file = f;
-
- /* Get the file version and check against current version */
- fscanf(state->pass1_file, "# ASCII XviD vbr stat file version %d\n", &n);
-
- if(n != VBR_VERSION) {
- fclose(state->pass1_file);
- state->pass1_file = NULL;
- return(-1);
- }
-
- /* Skip the blank commented line */
- c = n = 0;
- do {
-
- c = fgetc(state->pass1_file);
-
- if(c == EOF) {
- fclose(state->pass1_file);
- state->pass1_file = NULL;
- return(-1);
- }
-
- if(c == '\n') n++;
-
- }while(n < 1);
-
-
- /* Get the number of frames */
- fscanf(state->pass1_file, "# frames : %d\n", &state->nb_frames);
-
- /* Compute the desired size */
- state->desired_size = (long long)
- (((long long)state->nb_frames * (long long)state->desired_bitrate) /
- (state->fps * 8.0));
-
- /* Get the number of keyframes */
- fscanf(state->pass1_file, "# keyframes : %d\n", &state->nb_keyframes);
-
- /* Allocate memory space for the keyframe_location array */
- if((state->keyframe_locations
- = (int*)malloc((state->nb_keyframes+1)*sizeof(int))) == NULL) {
- fclose(state->pass1_file);
- state->pass1_file = NULL;
- return(-1);
- }
-
- /* Skip the blank commented line and the colum description */
- c = n = 0;
- do {
-
- c = fgetc(state->pass1_file);
-
- if(c == EOF) {
- fclose(state->pass1_file);
- state->pass1_file = NULL;
- return(-1);
- }
-
- if(c == '\n') n++;
-
- }while(n < 2);
-
- /* Save position for future use */
- pos_firstframe = ftell(state->pass1_file);
-
- /* Read and initialize some variables */
- credits1_bytes = credits2_bytes = 0;
- total_bytes = itotal_bytes = 0;
- start_curved = end_curved = 0;
- credits_frames = 0;
-
- for(state->cur_frame = c = 0; state->cur_frame<state->nb_frames; state->cur_frame++) {
-
- int quant, keyframe, frame_hbytes, frame_bytes;
- int kblocks, mblocks, ublocks;
-
- fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n",
- &quant, &keyframe, &frame_hbytes, &frame_bytes,
- &kblocks, &mblocks, &ublocks);
-
- /* Is the frame in the beginning credits */
- if(util_frametype(state) == FRAME_TYPE_STARTING_CREDITS) {
- credits1_bytes += frame_bytes;
- credits_frames++;
- continue;
- }
-
- /* Is the frame in the eding credits */
- if(util_frametype(state) == FRAME_TYPE_ENDING_CREDITS) {
- credits2_bytes += frame_bytes;
- credits_frames++;
- continue;
- }
-
- /* We only care about Keyframes when not in credits */
- if(keyframe) {
- itotal_bytes += frame_bytes + frame_bytes *
- state->keyframe_boost / 100;
- total_bytes += frame_bytes *
- state->keyframe_boost / 100;
- state->keyframe_locations[c++] = state->cur_frame;
- }
-
- total_bytes += frame_bytes;
-
- }
-
- /*
- * Last frame is treated like an I Frame so we can dispatch overflow
- * all other the last film segment
- */
- state->keyframe_locations[c] = state->cur_frame;
-
- desired = state->desired_size;
-
- switch(state->credits_mode) {
- case VBR_CREDITS_MODE_QUANT :
-
- state->movie_curve = (double)
- (total_bytes - credits1_bytes - credits2_bytes) /
- (desired - credits1_bytes - credits2_bytes);
-
- start_curved = credits1_bytes;
- end_curved = credits2_bytes;
-
- break;
- case VBR_CREDITS_MODE_SIZE:
-
- /* start curve = (start / start desired size) */
- state->credits_start_curve = (double)
- (credits1_bytes / state->credits_start_size);
-
- /* end curve = (end / end desired size) */
- state->credits_end_curve = (double)
- (credits2_bytes / state->credits_end_size);
-
- start_curved = (long long)
- (credits1_bytes / state->credits_start_curve);
-
- end_curved = (long long)
- (credits2_bytes / state->credits_end_curve);
-
- /* movie curve=(total-credits)/(desired_size-curved credits) */
- state->movie_curve = (double)
- (total_bytes - credits1_bytes - credits2_bytes) /
- (desired - start_curved - end_curved);
-
- break;
- case VBR_CREDITS_MODE_RATE:
- default:
-
- /* credits curve = (total/desired_size)*(100/credits_rate) */
- state->credits_start_curve = state->credits_end_curve =
- ((double)total_bytes / desired) *
- ((double)100 / state->credits_quant_ratio);
-
- start_curved =
- (long long)(credits1_bytes/state->credits_start_curve);
-
- end_curved =
- (long long)(credits2_bytes/state->credits_end_curve);
-
- state->movie_curve = (double)
- (total_bytes - credits1_bytes - credits2_bytes) /
- (desired - start_curved - end_curved);
-
- break;
- }
-
- /*
- * average frame size = (desired - curved credits - curved keyframes) /
- * (frames - credits frames - keyframes)
- */
- state->average_frame = (double)
- (desired - start_curved - end_curved -
- (itotal_bytes / state->movie_curve)) /
- (state->nb_frames - util_creditsframes(state) -
- state->nb_keyframes);
-
- /* Initialize alt curve parameters */
- if (state->use_alt_curve) {
-
- state->alt_curve_low =
- state->average_frame - state->average_frame *
- (double)(state->alt_curve_low_dist / 100.0);
-
- state->alt_curve_low_diff =
- state->average_frame - state->alt_curve_low;
-
- state->alt_curve_high =
- state->average_frame + state->average_frame *
- (double)(state->alt_curve_high_dist / 100.0);
-
- state->alt_curve_high_diff =
- state->alt_curve_high - state->average_frame;
-
- if (state->alt_curve_use_auto) {
-
- if (state->movie_curve > 1.0) {
-
- state->alt_curve_min_rel_qual =
- (int)(100.0 - (100.0 - 100.0 / state->movie_curve) *
- (double)state->alt_curve_auto_str / 100.0);
-
- if (state->alt_curve_min_rel_qual < 20)
- state->alt_curve_min_rel_qual = 20;
- }
- else {
- state->alt_curve_min_rel_qual = 100;
- }
-
- }
-
- state->alt_curve_mid_qual =
- (1.0 + (double)state->alt_curve_min_rel_qual / 100.0) / 2.0;
-
- state->alt_curve_qual_dev = 1.0 - state->alt_curve_mid_qual;
-
- if (state->alt_curve_low_dist > 100) {
-
- switch(state->alt_curve_type) {
- case VBR_ALT_CURVE_AGGRESIVE:
- /* Sine Curve (high aggressiveness) */
- state->alt_curve_qual_dev *=
- 2.0 /
- (1.0 + sin(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff)));
-
- state->alt_curve_mid_qual =
- 1.0 - state->alt_curve_qual_dev *
- sin(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff));
- break;
-
- default:
- case VBR_ALT_CURVE_LINEAR:
- /* Linear (medium aggressiveness) */
- state->alt_curve_qual_dev *=
- 2.0 /
- (1.0 + state->average_frame / state->alt_curve_low_diff);
-
- state->alt_curve_mid_qual =
- 1.0 - state->alt_curve_qual_dev *
- state->average_frame / state->alt_curve_low_diff;
-
- break;
-
- case VBR_ALT_CURVE_SOFT:
- /* Cosine Curve (low aggressiveness) */
- state->alt_curve_qual_dev *=
- 2.0 /
- (1.0 + (1.0 - cos(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff))));
-
- state->alt_curve_mid_qual =
- 1.0 - state->alt_curve_qual_dev *
- (1.0 - cos(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff)));
-
- break;
- }
- }
- }
-
- /* Go to the first non credits frame stats line into file */
- fseek(state->pass1_file, pos_firstframe, SEEK_SET);
-
- /* Perform prepass to compensate for over/undersizing */
- total1 = total2 = 0.0;
- for(state->cur_frame=0; state->cur_frame<state->nb_frames; state->cur_frame++) {
-
- int quant, keyframe, frame_hbytes, frame_bytes;
- int kblocks, mblocks, ublocks;
-
- fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n",
- &quant, &keyframe, &frame_hbytes, &frame_bytes,
- &kblocks, &mblocks, &ublocks);
-
- if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE)
- continue;
-
- if(!keyframe) {
-
- double dbytes = frame_bytes / state->movie_curve;
- total1 += dbytes;
-
- if (state->use_alt_curve) {
-
- if (dbytes > state->average_frame) {
-
- if (dbytes >= state->alt_curve_high) {
- total2 += dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev);
- }
- else {
-
- switch(state->alt_curve_type) {
- case VBR_ALT_CURVE_AGGRESIVE:
-
- total2 +=
- dbytes *
- (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff)));
- break;
- default:
- case VBR_ALT_CURVE_LINEAR:
-
- total2 +=
- dbytes *
- (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- (dbytes - state->average_frame) / state->alt_curve_high_diff);
- break;
- case VBR_ALT_CURVE_SOFT:
- total2 +=
- dbytes *
- (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff))));
- }
- }
- }
- else {
-
- if (dbytes <= state->alt_curve_low) {
- total2 += dbytes;
- }
- else {
-
- switch(state->alt_curve_type) {
- case VBR_ALT_CURVE_AGGRESIVE:
- total2 +=
- dbytes *
- (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff)));
- break;
- default:
- case VBR_ALT_CURVE_LINEAR:
- total2 +=
- dbytes *
- (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- (dbytes - state->average_frame) / state->alt_curve_low_diff);
- break;
- case VBR_ALT_CURVE_SOFT:
- total2 +=
- dbytes *
- (state->alt_curve_mid_qual + state->alt_curve_qual_dev *
- (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff))));
- }
- }
- }
- }
- else {
- if (dbytes > state->average_frame) {
- total2 +=
- ((double)dbytes +
- (state->average_frame - dbytes) *
- state->curve_compression_high / 100.0);
- }
- else {
- total2 +=
- ((double)dbytes +
- (state->average_frame - dbytes) *
- state->curve_compression_low / 100.0);
- }
- }
- }
- }
-
- state->curve_comp_scale = total1 / total2;
-
- if (state->use_alt_curve) {
-
- double curve_temp, dbytes;
- int newquant, percent;
- int oldquant = 1;
-
- if (state->alt_curve_use_auto_bonus_bias)
- state->alt_curve_bonus_bias = state->alt_curve_min_rel_qual;
-
- state->curve_bias_bonus =
- (total1 - total2) * (double)state->alt_curve_bonus_bias /
- (100.0 * (double)(state->nb_frames - util_creditsframes(state) - state->nb_keyframes));
- state->curve_comp_scale =
- ((total1 - total2) * (1.0 - (double)state->alt_curve_bonus_bias / 100.0) + total2) /
- total2;
-
-
- for (n=1; n <= (int)(state->alt_curve_high*2) + 1; n++) {
- dbytes = n;
- if (dbytes > state->average_frame)
- {
- if (dbytes >= state->alt_curve_high) {
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev);
- }
- else {
- switch(state->alt_curve_type) {
- case VBR_ALT_CURVE_AGGRESIVE:
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff)));
- break;
- default:
- case VBR_ALT_CURVE_LINEAR:
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- (dbytes - state->average_frame) / state->alt_curve_high_diff);
- break;
- case VBR_ALT_CURVE_SOFT:
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff))));
- }
- }
- }
- else {
- if (dbytes <= state->alt_curve_low) {
- curve_temp = dbytes;
- }
- else {
- switch(state->alt_curve_type) {
- case VBR_ALT_CURVE_AGGRESIVE:
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff)));
- break;
- default:
- case VBR_ALT_CURVE_LINEAR:
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- (dbytes - state->average_frame) / state->alt_curve_low_diff);
- break;
- case VBR_ALT_CURVE_SOFT:
- curve_temp = dbytes * (state->alt_curve_mid_qual + state->alt_curve_qual_dev *
- (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff))));
- }
- }
- }
-
- if (state->movie_curve > 1.0)
- dbytes *= state->movie_curve;
-
- newquant = (int)(dbytes * 2.0 / (curve_temp * state->curve_comp_scale + state->curve_bias_bonus));
- if (newquant > 1)
- {
- if (newquant != oldquant)
- {
- oldquant = newquant;
- percent = (int)((n - state->average_frame) * 100.0 / state->average_frame);
- }
-
- }
-
- }
-
- }
-
- state->overflow = 0;
- state->KFoverflow = 0;
- state->KFoverflow_partial = 0;
- state->KF_idx = 1;
-
- for (n=0 ; n < 32 ; n++) {
- state->quant_error[n] = 0.0;
- state->quant_count[n] = 0;
- }
-
- state->curve_comp_error = 0.0;
- state->last_quant = 0;
-
- /*
- * Above this frame size limit, normal vbr rules will not apply
- * This means :
- * 1 - Quant can de/increase more than -/+2 between 2 frames
- * 2 - Leads to artifacts because of 1
- */
- state->max_framesize = state->twopass_max_bitrate/state->fps;
-
- /* Get back to the beginning of frame statistics */
- fseek(state->pass1_file, pos_firstframe, SEEK_SET);
-
- /*
- * Small hack : We have to get next frame stats before the
- * getintra/quant calls
- * User clients update the data when they call vbrUpdate
- * we are just bypassing this because we don't have to update
- * the overflow and so on...
- */
- {
-
- /* Fake vars */
- int next_hbytes, next_kblocks, next_mblocks, next_ublocks;
-
- fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n",
- &state->pass1_quant, &state->pass1_intra, &next_hbytes,
- &state->pass1_bytes, &next_kblocks, &next_mblocks,
- &next_ublocks);
-
- }
-
- /* Initialize the frame counter */
- state->cur_frame = 0;
- state->last_keyframe = 0;
-
- return(0);
-
-}
-
-static int vbr_getquant_2pass2(void *sstate)
-{
-
- int quant;
- int intra;
- int bytes1, bytes2;
- int overflow;
- int capped_to_max_framesize = 0;
- int KFdistance, KF_min_size;
- vbr_control_t *state = sstate;
-
- bytes1 = state->pass1_bytes;
- overflow = state->overflow / 8;
- /* To shut up gcc warning */
- bytes2 = bytes1;
-
-
- if (state->pass1_intra)
- {
- overflow = 0;
- }
-
- if (util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) {
-
-
- switch (state->credits_mode) {
- case VBR_CREDITS_MODE_QUANT :
- if (state->credits_quant_i != state->credits_quant_p) {
- quant = state->pass1_intra ?
- state->credits_quant_i:
- state->credits_quant_p;
- }
- else {
- quant = state->credits_quant_p;
- }
-
- state->bytes1 = bytes1;
- state->bytes2 = bytes1;
- state->desired_bytes2 = bytes1;
- return(quant);
- default:
- case VBR_CREDITS_MODE_RATE :
- case VBR_CREDITS_MODE_SIZE :
- if(util_frametype(state) == FRAME_TYPE_STARTING_CREDITS)
- bytes2 = (int)(bytes1 / state->credits_start_curve);
- else
- bytes2 = (int)(bytes1 / state->credits_end_curve);
- break;
- }
- }
- else {
- /* Foxer: apply curve compression outside credits */
- double dbytes, curve_temp;
-
- bytes2 = bytes1;
-
- if (state->pass1_intra)
- dbytes = ((int)(bytes2 + bytes2 * state->keyframe_boost / 100)) /
- state->movie_curve;
- else
- dbytes = bytes2 / state->movie_curve;
-
- /* spread the compression error accross payback_delay frames */
- if (state->bitrate_payback_method == VBR_PAYBACK_BIAS) {
- bytes2 = (int)(state->curve_comp_error / state->bitrate_payback_delay);
- }
- else {
- bytes2 = (int)(state->curve_comp_error * dbytes /
- state->average_frame / state->bitrate_payback_delay);
-
- if (labs(bytes2) > fabs(state->curve_comp_error))
- bytes2 = (int)state->curve_comp_error;
- }
-
- state->curve_comp_error -= bytes2;
-
- if (state->use_alt_curve) {
-
- if (!state->pass1_intra) {
-
- if (dbytes > state->average_frame) {
- if (dbytes >= state->alt_curve_high)
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev);
- else {
- switch(state->alt_curve_type) {
- case VBR_ALT_CURVE_AGGRESIVE:
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff)));
- break;
- default:
- case VBR_ALT_CURVE_LINEAR:
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- (dbytes - state->average_frame) / state->alt_curve_high_diff);
- break;
- case VBR_ALT_CURVE_SOFT:
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff))));
- }
- }
- }
- else {
- if (dbytes <= state->alt_curve_low)
- curve_temp = dbytes;
- else {
- switch(state->alt_curve_type) {
- case VBR_ALT_CURVE_AGGRESIVE:
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff)));
- break;
- default:
- case VBR_ALT_CURVE_LINEAR:
- curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev *
- (dbytes - state->average_frame) / state->alt_curve_low_diff);
- break;
- case VBR_ALT_CURVE_SOFT:
- curve_temp = dbytes * (state->alt_curve_mid_qual + state->alt_curve_qual_dev *
- (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff))));
- }
- }
- }
-
- curve_temp = curve_temp * state->curve_comp_scale + state->curve_bias_bonus;
-
- bytes2 += ((int)curve_temp);
- state->curve_comp_error += curve_temp - ((int)curve_temp);
-
- }
- else {
- state->curve_comp_error += dbytes - ((int)dbytes);
- bytes2 += ((int)dbytes);
- }
- }
- else if ((state->curve_compression_high + state->curve_compression_low) &&
- !state->pass1_intra) {
-
- if (dbytes > state->average_frame) {
- curve_temp = state->curve_comp_scale *
- ((double)dbytes + (state->average_frame - dbytes) *
- state->curve_compression_high / 100.0);
- }
- else {
- curve_temp = state->curve_comp_scale *
- ((double)dbytes + (state->average_frame - dbytes) *
- state->curve_compression_low / 100.0);
- }
-
- bytes2 += ((int)curve_temp);
- state->curve_comp_error += curve_temp - ((int)curve_temp);
- }
- else {
- state->curve_comp_error += dbytes - ((int)dbytes);
- bytes2 += ((int)dbytes);
- }
-
- /* cap bytes2 to first pass size, lowers number of quant=1 frames */
- if (bytes2 > bytes1) {
- state->curve_comp_error += bytes2 - bytes1;
- bytes2 = bytes1;
- }
- else if (bytes2 < 1) {
- state->curve_comp_error += --bytes2;
- bytes2 = 1;
- }
- }
-
- state->desired_bytes2 = bytes2;
-
- /* Ugly dependance between getquant and getintra */
- intra = state->getintra(state);
-
- if(intra) {
-
- KFdistance = state->keyframe_locations[state->KF_idx] -
- state->keyframe_locations[state->KF_idx - 1];
-
- if (KFdistance < state->kftreshold) {
- KFdistance = KFdistance - state->min_key_interval;
-
- if (KFdistance >= 0) {
-
- KF_min_size = bytes2 * (100 - state->kfreduction) / 100;
- if (KF_min_size < 1)
- KF_min_size = 1;
-
- bytes2 = KF_min_size + (bytes2 - KF_min_size) * KFdistance /
- (state->kftreshold - state->min_key_interval);
-
- if (bytes2 < 1)
- bytes2 = 1;
- }
- }
- }
-
- /*
- * Foxer: scale overflow in relation to average size, so smaller frames don't get
- * too much/little bitrate
- */
- overflow = (int)((double)overflow * bytes2 / state->average_frame);
-
- /* Foxer: reign in overflow with huge frames */
- if (labs(overflow) > labs(state->overflow)) {
- overflow = state->overflow;
- }
-
- /* Foxer: make sure overflow doesn't run away */
- if(overflow > bytes2 * state->twopass_max_overflow_improvement / 100) {
- bytes2 += (overflow <= bytes2) ? bytes2 * state->twopass_max_overflow_improvement / 100 :
- overflow * state->twopass_max_overflow_improvement / 100;
- }
- else if(overflow < bytes2 * state->twopass_max_overflow_degradation / -100) {
- bytes2 += bytes2 * state->twopass_max_overflow_degradation / -100;
- }
- else {
- bytes2 += overflow;
- }
-
- if(bytes2 > state->max_framesize) {
- capped_to_max_framesize = 1;
- bytes2 = state->max_framesize;
- }
-
- if(bytes2 < 1) {
- bytes2 = 1;
- }
-
- state->bytes1 = bytes1;
- state->bytes2 = bytes2;
-
- /* very 'simple' quant<->filesize relationship */
- quant = state->pass1_quant * bytes1 / bytes2;
-
- if(quant < 1)
- quant = 1;
- else if(quant > 31)
- quant = 31;
- else if(!state->pass1_intra) {
-
- /* Foxer: aid desired quantizer precision by accumulating decision error */
- state->quant_error[quant] += ((double)(state->pass1_quant * bytes1) / bytes2) - quant;
-
- if (state->quant_error[quant] >= 1.0) {
- state->quant_error[quant] -= 1.0;
- quant++;
- }
- }
-
- /* we're done with credits */
- if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) {
- return(quant);
- }
-
- if(intra) {
-
- if (quant < state->min_iquant)
- quant = state->min_iquant;
- if (quant > state->max_iquant)
- quant = state->max_iquant;
- }
- else {
-
- if(quant > state->max_pquant)
- quant = state->max_pquant;
- if(quant < state->min_pquant)
- quant = state->min_pquant;
-
- /* subsequent frame quants can only be +- 2 */
- if(state->last_quant && capped_to_max_framesize == 0) {
- if (quant > state->last_quant + 2)
- quant = state->last_quant + 2;
- if (quant < state->last_quant - 2)
- quant = state->last_quant - 2;
- }
- }
-
- return(quant);
-
-}
-
-static int vbr_getintra_2pass2(void *sstate)
-{
-
- int intra;
- vbr_control_t *state = sstate;
-
-
- /* Get next intra state (fetched by update) */
- intra = state->pass1_intra;
-
- /* During credits, XviD will decide itself */
- if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) {
-
-
- switch(state->credits_mode) {
- default:
- case VBR_CREDITS_MODE_RATE :
- case VBR_CREDITS_MODE_SIZE :
- intra = -1;
- break;
- case VBR_CREDITS_MODE_QUANT :
- /* Except in this case */
- if (state->credits_quant_i == state->credits_quant_p)
- intra = -1;
- break;
- }
-
- }
-
- /* Force I Frame when max_key_interval is reached */
- if((state->cur_frame - state->last_keyframe) > state->max_key_interval)
- intra = 1;
-
- /*
- * Force P or B Frames for frames whose distance is less than the
- * requested minimum
- */
- if((state->cur_frame - state->last_keyframe) < state->min_key_interval)
- intra = 0;
-
-
- /* Return the given intra mode except for first frame */
- return((state->cur_frame==0)?1:intra);
-
-}
-
-static int vbr_update_2pass2(void *sstate,
- int quant,
- int intra,
- int header_bytes,
- int total_bytes,
- int kblocks,
- int mblocks,
- int ublocks)
-
-
-{
-
-
- int next_hbytes, next_kblocks, next_mblocks, next_ublocks;
- int tempdiv;
-
- vbr_control_t *state = sstate;
-
- /*
- * We do not depend on getintra/quant because we have the real results
- * from the xvid core
- */
-
- if (util_frametype(state) == FRAME_TYPE_NORMAL_MOVIE) {
-
- state->quant_count[quant]++;
-
- if (state->pass1_intra) {
-
- state->overflow += state->KFoverflow;
- state->KFoverflow = state->desired_bytes2 - total_bytes;
-
- tempdiv = (state->keyframe_locations[state->KF_idx] -
- state->keyframe_locations[state->KF_idx - 1]);
-
- /* redistribute correctly (by koepi) */
- if (tempdiv > 1) {
- /* non-consecutive keyframes */
- state->KFoverflow_partial = state->KFoverflow /
- (tempdiv - 1);
- }
- else {
- state->overflow += state->KFoverflow;
- state->KFoverflow = 0;
- state->KFoverflow_partial = 0;
- }
- state->KF_idx++;
-
- }
- else {
- state->overflow += state->desired_bytes2 - total_bytes +
- state->KFoverflow_partial;
- state->KFoverflow -= state->KFoverflow_partial;
- }
- }
- else {
-
- state->overflow += state->desired_bytes2 - total_bytes;
- state->overflow += state->KFoverflow;
- state->KFoverflow = 0;
- state->KFoverflow_partial = 0;
- }
-
- /* Save old quant */
- state->last_quant = quant;
-
- /* Update next frame data */
- fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n",
- &state->pass1_quant, &state->pass1_intra, &next_hbytes,
- &state->pass1_bytes, &next_kblocks, &next_mblocks,
- &next_ublocks);
-
- /* Save the last Keyframe pos */
- if(intra)
- state->last_keyframe = state->cur_frame;
-
- /* Ok next frame */
- state->cur_frame++;
-
- return(0);
-
-}
-
-static int vbr_finish_2pass2(void *sstate)
-{
-
- vbr_control_t *state = sstate;
-
- if(state->pass1_file == NULL)
- return(-1);
-
- /* Close the file */
- if(fclose(state->pass1_file) != 0)
- return(-1);
-
- /* Free the memory */
- if(state->keyframe_locations)
- free(state->keyframe_locations);
-
- return(0);
-
-}
-
-
-/******************************************************************************
- * Fixed quant mode - Most of the functions will be dummy functions
- *****************************************************************************/
-
-static int vbr_init_fixedquant(void *sstate)
-{
-
- vbr_control_t *state = sstate;
-
- if(state->fixed_quant < 1)
- state->fixed_quant = 1;
-
- if(state->fixed_quant > 31)
- state->fixed_quant = 31;
-
- state->cur_frame = 0;
-
- return(0);
-
-}
-
-static int vbr_getquant_fixedquant(void *sstate)
-{
-
- vbr_control_t *state = sstate;
-
- /* Credits' frame ? */
- if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) {
-
- int quant;
-
- switch(state->credits_mode) {
- case VBR_CREDITS_MODE_RATE:
- quant = state->fixed_quant * state->credits_quant_ratio;
- break;
- case VBR_CREDITS_MODE_QUANT:
- quant = state->credits_fixed_quant;
- break;
- default:
- quant = state->fixed_quant;
-
- }
-
- return(quant);
-
- }
-
- /* No credit frame - return fixed quant */
- return(state->fixed_quant);
-
-}
-
-static int vbr_getintra_fixedquant(void *state)
-{
-
- return(-1);
-
-}
diff --git a/core/XvidVbr.h b/core/XvidVbr.h
deleted file mode 100644
index ea9d3b703..000000000
--- a/core/XvidVbr.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/******************************************************************************
- *
- * XviD VBR Library
- *
- * Copyright (C) 2002 Edouard Gomez <[email protected]>
- *
- * The curve treatment algorithm is based on work done by Foxer <email?> and
- * Dirk Knop <[email protected]> for the XviD vfw dynamic library.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *****************************************************************************/
-
-#ifndef __XVID_VBR_H__
-#define __XVID_VBR_H__
-
-#define VBR_VERSION 0
-
-/******************************************************************************
- * Function types used in the vbr controler
- *****************************************************************************/
-
-typedef int (vbr_init_function)(void *state);
-typedef vbr_init_function *vbr_init_function_ptr;
-
-typedef int (vbr_get_quant_function)(void *state);
-typedef vbr_get_quant_function *vbr_get_quant_function_ptr;
-
-typedef int (vbr_get_intra_function)(void *state);
-typedef vbr_get_intra_function *vbr_get_intra_function_ptr;
-
-typedef int (vbr_update_function)(void *state,
- int quant,
- int intra,
- int header_bytes,
- int total_bytes,
- int kblocks,
- int mblocks,
- int ublocks);
-typedef vbr_update_function *vbr_update_function_ptr;
-
-typedef int (vbr_finish_function)(void *state);
-typedef vbr_finish_function *vbr_finish_function_ptr;
-
-/******************************************************************************
- * The VBR CONTROLER structure - the spin of the library
- *****************************************************************************/
-
-typedef struct _vbr_control_t
-{
-
- /* All modes - specifies what VBR algorithm has to be used */
- int mode;
-
- /* All modes - specifies what fps the movie uses */
- float fps;
-
- /* All modes */
- int debug;
-
- /*
- * For VBR_MODE_2PASS_1/2 - specifies from/to what file the vbr
- * controller has to write/read stats
- */
- char *filename;
-
- /* For VBR_MODE_2PASS_2 - Target size */
- int desired_bitrate;
-
- /* For VBR_MODE_2PASS_2 - Credits parameters */
- int credits_mode;
- int credits_start;
- int credits_start_begin;
- int credits_start_end;
- int credits_end;
- int credits_end_begin;
- int credits_end_end;
- int credits_quant_ratio;
- int credits_fixed_quant;
- int credits_quant_i;
- int credits_quant_p;
- int credits_start_size;
- int credits_end_size;
-
- /* For VBR_MODE_2PASS_2 - keyframe parameters */
- int keyframe_boost;
- int kftreshold;
- int kfreduction;
- int min_key_interval;
- int max_key_interval;
-
- /* For VBR_MODE_2PASS_2 - Normal curve */
- int curve_compression_high;
- int curve_compression_low;
-
- /* For VBR_MODE_2PASS_2 - Alternate curve parameters */
- int use_alt_curve;
- int alt_curve_type;
- int alt_curve_low_dist;
- int alt_curve_high_dist;
- int alt_curve_min_rel_qual;
- int alt_curve_use_auto;
- int alt_curve_auto_str;
- int alt_curve_use_auto_bonus_bias;
- int alt_curve_bonus_bias;
- int bitrate_payback_method;
- int bitrate_payback_delay;
- int max_iquant;
- int min_iquant;
- int max_pquant;
- int min_pquant;
- int twopass_max_bitrate;
- int twopass_max_overflow_improvement;
- int twopass_max_overflow_degradation;
-
- /*
- * For VBR_MODE_FIXED_QUANT - the quantizer that has to be used for all
- * frames
- */
- int fixed_quant;
-
- /* ----------- Internal data - Do not modify ----------- */
- void *debug_file;
- void *pass1_file;
-
- long long desired_size;
-
- int cur_frame;
- int nb_frames;
- int nb_keyframes;
-
- int *keyframe_locations;
- int last_keyframe;
-
- double credits_start_curve;
- double credits_end_curve;
- double movie_curve;
- double average_frame;
- double alt_curve_low;
- double alt_curve_low_diff;
- double alt_curve_high;
- double alt_curve_high_diff;
- double alt_curve_mid_qual;
- double alt_curve_qual_dev;
- double curve_bias_bonus;
- double curve_comp_scale;
- double curve_comp_error;
-
- int pass1_quant;
- int pass1_intra;
- int pass1_bytes;
-
- int bytes1;
- int bytes2;
- int desired_bytes2;
- int max_framesize;
- int last_quant;
- int quant_count[32];
- double quant_error[32];
-
- int overflow;
- int KFoverflow;
- int KFoverflow_partial;
- int KF_idx;
-
- int debug_quant_count[32];
-
- /* ----------- Internal data - do not modify ----------- */
- vbr_init_function_ptr init;
- vbr_get_quant_function_ptr getquant;
- vbr_get_intra_function_ptr getintra;
- vbr_update_function_ptr update;
- vbr_finish_function_ptr finish;
-
-}vbr_control_t;
-
-/******************************************************************************
- * Constants
- *****************************************************************************/
-
-/* Constants for the mode member */
-#define VBR_MODE_1PASS 0x01
-#define VBR_MODE_2PASS_1 0x02
-#define VBR_MODE_2PASS_2 0x04
-#define VBR_MODE_FIXED_QUANT 0x08
-
-/* Constants for the credits mode */
-#define VBR_CREDITS_MODE_RATE 0x01
-#define VBR_CREDITS_MODE_QUANT 0x02
-#define VBR_CREDITS_MODE_SIZE 0x04
-
-/* Alternate curve treatment types */
-#define VBR_ALT_CURVE_SOFT 0x01
-#define VBR_ALT_CURVE_LINEAR 0x02
-#define VBR_ALT_CURVE_AGGRESIVE 0x04
-
-/* Payback modes */
-#define VBR_PAYBACK_BIAS 0x01
-#define VBR_PAYBACK_PROPORTIONAL 0x02
-
-/******************************************************************************
- * VBR API
- *****************************************************************************/
-
-extern int vbrSetDefaults(vbr_control_t *state);
-extern int vbrInit(vbr_control_t *state);
-extern int vbrGetQuant(vbr_control_t *state);
-extern int vbrGetIntra(vbr_control_t *state);
-extern int vbrUpdate(vbr_control_t *state,
- int quant,
- int intra,
- int header_bytes,
- int total_bytes,
- int kblocks,
- int mblocks,
- int ublocks);
-extern int vbrFinish(vbr_control_t *state);
-
-#endif