diff options
author | handbrake <[email protected]> | 2006-01-14 13:05:49 +0000 |
---|---|---|
committer | handbrake <[email protected]> | 2006-01-14 13:05:49 +0000 |
commit | 5824c4979fbc54ae3d3015c07cbf6fa4aea7516d (patch) | |
tree | 49ba3bbe1f8d8166fa4f7f964055d4011d2deca0 /core/Ac3Dec.c | |
parent | f013e3544c0bdf17348d617a467af0e4fde0f545 (diff) |
HandBrake 0.5
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@7 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'core/Ac3Dec.c')
-rw-r--r-- | core/Ac3Dec.c | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/core/Ac3Dec.c b/core/Ac3Dec.c new file mode 100644 index 000000000..d5430d49e --- /dev/null +++ b/core/Ac3Dec.c @@ -0,0 +1,219 @@ +/* $Id: Ac3Dec.c,v 1.4 2003/11/04 20:16:44 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "Ac3Dec.h" +#include "Fifo.h" +#include "Work.h" + +#include <a52dec/a52.h> + +/* Local prototypes */ +static int Ac3DecWork( HBWork * ); +static int GetBytes( HBAc3Dec *, int ); + +struct HBAc3Dec +{ + HB_WORK_COMMON_MEMBERS + + HBHandle * handle; + HBAudio * audio; + + /* liba52 stuff */ + a52_state_t * state; + int inFlags; + int outFlags; + float sampleLevel; + + /* Buffers */ + uint8_t ac3Frame[3840]; /* Max size of a A52 frame */ + int ac3FrameSize; /* In bytes */ + HBBuffer * ac3Buffer; + int ac3BufferPos; /* In bytes */ + int nextFrameSize; /* In bytes */ + float position; + HBBuffer * rawBuffer; +}; + +HBAc3Dec * HBAc3DecInit( HBHandle * handle, HBAudio * audio ) +{ + HBAc3Dec * a; + if( !( a = malloc( sizeof( HBAc3Dec ) ) ) ) + { + HBLog( "HBAc3DecInit: malloc() failed, gonna crash" ); + return NULL; + } + + a->name = strdup( "Ac3Dec" ); + a->work = Ac3DecWork; + + a->handle = handle; + a->audio = audio; + + /* Init liba52 */ + a->state = a52_init( 0 ); + a->inFlags = 0; + + /* Let it do the downmixing */ + a->outFlags = A52_STEREO; + + /* Lame wants samples from -32768 to 32768 */ + a->sampleLevel = 32768.0; + + a->ac3FrameSize = 0; + a->ac3Buffer = NULL; + a->ac3BufferPos = 0; + a->nextFrameSize = 0; + a->position = 0.0; + a->rawBuffer = NULL; + + return a; +} + +void HBAc3DecClose( HBAc3Dec ** _a ) +{ + HBAc3Dec * a = *_a; + + if( a->ac3Buffer ) HBBufferClose( &a->ac3Buffer ); + if( a->rawBuffer ) HBBufferClose( &a->rawBuffer ); + a52_free( a->state ); + free( a->name ); + free( a ); + + *_a = NULL; +} + +static int Ac3DecWork( HBWork * w ) +{ + HBAc3Dec * a = (HBAc3Dec*) w; + HBAudio * audio = a->audio; + + int didSomething = 0; + + /* Push decoded buffer */ + if( a->rawBuffer ) + { + if( HBFifoPush( audio->rawFifo, &a->rawBuffer ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + } + + /* Get a frame header (7 bytes) */ + if( a->ac3FrameSize < 7 ) + { + if( GetBytes( a, 7 ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + + a->nextFrameSize = a52_syncinfo( a->ac3Frame, &a->inFlags, + &audio->inSampleRate, + &audio->inBitrate ); + + if( !a->nextFrameSize ) + { + HBLog( "HBAc3Dec: a52_syncinfo() failed" ); + HBErrorOccured( a->handle, HB_ERROR_A52_SYNC ); + return didSomething; + } + } + + /* Get the whole frame */ + if( a->ac3FrameSize >= 7 ) + { + sample_t * samples; + HBBuffer * rawBuffer; + int i; + + if( GetBytes( a, a->nextFrameSize ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + + /* Feed liba52 */ + a52_frame( a->state, a->ac3Frame, &a->outFlags, + &a->sampleLevel, 0 ); + a->ac3FrameSize = 0; + + /* 6 blocks per frame, 256 samples per block, 2 channels */ + rawBuffer = HBBufferInit( 12 * 256 * sizeof( float ) ); + rawBuffer->position = a->position; + + for( i = 0; i < 6; i++ ) + { + /* Decode a block */ + a52_block( a->state ); + + /* Get a pointer to the raw data */ + samples = a52_samples( a->state ); + + /* Copy left channel data */ + memcpy( rawBuffer->data + i * 256 * sizeof( float ), + samples, + 256 * sizeof( float ) ); + + /* Copy right channel data */ + memcpy( rawBuffer->data + ( 6 + i ) * 256 * sizeof( float ), + samples + 256, + 256 * sizeof( float ) ); + } + + a->rawBuffer = rawBuffer; + } + + return didSomething; +} + +static int GetBytes( HBAc3Dec * a, int size ) +{ + int i; + + while( a->ac3FrameSize < size ) + { + if( !a->ac3Buffer ) + { + if( !( a->ac3Buffer = HBFifoPop( a->audio->ac3Fifo ) ) ) + { + return 0; + } + a->ac3BufferPos = 0; + a->position = a->ac3Buffer->position; + + if( a->ac3Buffer->last ) + { + HBDone( a->handle ); + } + } + + i = MIN( size - a->ac3FrameSize, + a->ac3Buffer->size - a->ac3BufferPos ); + memcpy( a->ac3Frame + a->ac3FrameSize, + a->ac3Buffer->data + a->ac3BufferPos, + i ); + a->ac3FrameSize += i; + a->ac3BufferPos += i; + + if( a->ac3BufferPos == a->ac3Buffer->size ) + { + HBBufferClose( &a->ac3Buffer ); + } + } + + return 1; +} + |