summaryrefslogtreecommitdiffstats
path: root/core/Ac3Decoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/Ac3Decoder.cpp')
-rw-r--r--core/Ac3Decoder.cpp145
1 files changed, 145 insertions, 0 deletions
diff --git a/core/Ac3Decoder.cpp b/core/Ac3Decoder.cpp
new file mode 100644
index 000000000..12eed05df
--- /dev/null
+++ b/core/Ac3Decoder.cpp
@@ -0,0 +1,145 @@
+/* $Id: Ac3Decoder.cpp,v 1.12 2003/09/30 14:38:15 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://beos.titer.org/handbrake/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "Ac3Decoder.h"
+#include "Fifo.h"
+#include "Manager.h"
+
+extern "C" {
+#include <a52dec/a52.h>
+}
+
+HBAc3Decoder::HBAc3Decoder( HBManager * manager, HBAudio * audio )
+ : HBThread( "ac3decoder" )
+{
+ fManager = manager;
+ fAudio = audio;
+
+ /* Max size for a A52 frame is 3840 bytes */
+ fAc3Frame = new HBBuffer( 3840 );
+ fAc3Buffer = NULL;
+ fPosInBuffer = 0;
+ fPosition = 0;
+}
+
+HBAc3Decoder::~HBAc3Decoder()
+{
+ delete fAc3Frame;
+}
+
+void HBAc3Decoder::DoWork()
+{
+ /* Init liba52 */
+ a52_state_t * state = a52_init( 0 );
+ int inFlags = 0;
+ int outFlags = A52_STEREO;
+
+ /* Lame wants samples from -32768 to 32768 */
+ float sampleLevel = 32768;
+
+ int frameSize;
+ HBBuffer * rawBuffer;
+ sample_t * samples;
+
+ /* Main loop */
+ for( ;; )
+ {
+ while( fSuspend )
+ {
+ Snooze( 10000 );
+ }
+
+ fAc3Frame->fSize = 0;
+
+ /* Get a frame header (7 bytes) */
+ if( !( GetBytes( 7 ) ) )
+ {
+ break;
+ }
+
+ /* Get the size of the current frame */
+ frameSize = a52_syncinfo( fAc3Frame->fData, &inFlags,
+ &fAudio->fInSampleRate,
+ &fAudio->fInBitrate );
+
+ if( !frameSize )
+ {
+ Log( "HBAc3Decoder : a52_syncinfo failed" );
+ fManager->Error();
+ break;
+ }
+
+ /* Get the whole frame */
+ if( !( GetBytes( (uint32_t) frameSize ) ) )
+ {
+ break;
+ }
+
+ /* Feed liba52 */
+ a52_frame( state, fAc3Frame->fData, &outFlags, &sampleLevel, 0 );
+
+ /* 6 blocks per frame, 256 samples per block */
+ rawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) );
+ rawBuffer->fPosition = fPosition;
+ for( int i = 0; i < 6; i++ )
+ {
+ /* Decode a block */
+ a52_block( state );
+
+ /* Get a pointer to the raw data */
+ samples = a52_samples( state );
+
+ /* Copy left channel data */
+ memcpy( (float*) rawBuffer->fData + i * 256,
+ samples,
+ 256 * sizeof( float ) );
+
+ /* Copy right channel data */
+ memcpy( (float*) rawBuffer->fData + ( 6 + i ) * 256,
+ samples + 256,
+ 256 * sizeof( float ) );
+ }
+
+ if( !Push( fAudio->fRawFifo, rawBuffer ) )
+ {
+ break;
+ }
+ }
+}
+
+/* GetBytes() : pops buffers from the AC3 fifo until fAc3Frame
+ contains <size> bytes */
+bool HBAc3Decoder::GetBytes( uint32_t size )
+{
+ while( fAc3Frame->fSize < size )
+ {
+ if( !fAc3Buffer )
+ {
+ if( !( fAc3Buffer = Pop( fAudio->fAc3Fifo ) ) )
+ {
+ return false;
+ }
+ fPosInBuffer = 0;
+ fPosition = fAc3Buffer->fPosition;
+ }
+
+ int willCopy = MIN( size - fAc3Frame->fSize,
+ fAc3Buffer->fSize - fPosInBuffer );
+ memcpy( fAc3Frame->fData + fAc3Frame->fSize,
+ fAc3Buffer->fData + fPosInBuffer,
+ willCopy );
+ fAc3Frame->fSize += willCopy;
+ fPosInBuffer += willCopy;
+
+ if( fAc3Buffer->fSize == fPosInBuffer )
+ {
+ delete fAc3Buffer;
+ fAc3Buffer = NULL;
+ }
+ }
+
+ return true;
+}