diff options
Diffstat (limited to 'core/Mp3Enc.c')
-rw-r--r-- | core/Mp3Enc.c | 251 |
1 files changed, 49 insertions, 202 deletions
diff --git a/core/Mp3Enc.c b/core/Mp3Enc.c index bd62df4ae..c1aae34fe 100644 --- a/core/Mp3Enc.c +++ b/core/Mp3Enc.c @@ -1,4 +1,4 @@ -/* $Id: Mp3Enc.c,v 1.13 2004/01/21 17:59:33 titer Exp $ +/* $Id: Mp3Enc.c,v 1.23 2004/05/02 16:25:00 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. @@ -9,226 +9,110 @@ /* libmp3lame */ #include "lame/lame.h" -typedef struct HBMp3Enc +struct HBWork { HB_WORK_COMMON_MEMBERS HBHandle * handle; HBAudio * audio; lame_global_flags * globalFlags; - HBBuffer * rawBuffer; - int rawBufferPos; - float position; - int inputSamples; - int samplesGot; - float * left; - float * right; - HBBuffer * mp3Buffer; - - /* 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 = calloc( sizeof( HBMp3Enc ), 1 ) ) ) + HBWork * w; + if( !( w = calloc( sizeof( HBWork ), 1 ) ) ) { HBLog( "HBMp3EncInit: malloc() failed, gonna crash" ); return NULL; } - m->name = strdup( "Mp3Enc" ); - m->work = Mp3EncWork; + w->name = strdup( "Mp3Enc" ); + w->work = Mp3EncWork; - m->handle = handle; - m->audio = audio; + w->handle = handle; + w->audio = audio; - return (HBWork*) m; + return w; } -void HBMp3EncClose( HBWork ** _m ) +void HBMp3EncClose( HBWork ** _w ) { - 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 ); + HBWork * w = *_w; - 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; + if( w->globalFlags ) lame_close( w->globalFlags ); - 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 ); - - *_m = NULL; + free( w->name ); + free( w ); + *_w = NULL; } static int Mp3EncWork( HBWork * w ) { - HBMp3Enc * m = (HBMp3Enc*) w; - HBAudio * audio = m->audio; + HBAudio * audio = w->audio; HBBuffer * mp3Buffer; int ret; - int didSomething = 0; + float samples_f[1152 * 2]; + int16_t samples_s16[1152 * 2]; + float position; + int i; - if( !m->globalFlags ) + if( !w->globalFlags ) { - int i; - - /* Get a first buffer so we know that audio->inSampleRate is - correct */ - if( ( m->rawBuffer = HBFifoPop( audio->rawFifo ) ) ) + if( !HBFifoSize( audio->resampleFifo ) ) { - didSomething = 1; + return 0; } - else - { - return didSomething; - } - m->rawBufferPos = 0; - m->position = m->rawBuffer->position; - - /* The idea is to have exactly one mp3 frame (i.e. 1152 samples) by - output buffer. As we are resampling from inSampleRate to - outSampleRate, we will give ( 1152 * inSampleRate ) / - ( 2 * outSampleRate ) samples to libmp3lame so we are sure we - will never get more than 1 frame at a time */ - audio->outSampleRate = 44100; - m->inputSamples = 1152 * audio->inSampleRate / - audio->outSampleRate / 2; - - HBLog( "HBMp3Enc: opening lame (%d->%d Hz, %d kbps)", - audio->inSampleRate, audio->outSampleRate, - audio->outBitrate ); - m->globalFlags = lame_init(); - lame_set_in_samplerate( m->globalFlags, audio->inSampleRate ); - lame_set_out_samplerate( m->globalFlags, audio->outSampleRate ); - lame_set_brate( m->globalFlags, audio->outBitrate ); - if( lame_init_params( m->globalFlags ) == -1 ) - { - HBLog( "HBMp3Enc: lame_init_params() failed" ); - HBErrorOccured( m->handle, HB_ERROR_MP3_INIT ); - return didSomething; - } + HBLog( "HBMp3Enc: opening lame (%d kbps)", audio->outBitrate ); - m->left = malloc( m->inputSamples * sizeof( float ) ); - m->right = malloc( m->inputSamples * sizeof( float ) ); + w->globalFlags = lame_init(); + lame_set_brate( w->globalFlags, audio->outBitrate ); - if( !m->left || !m->right ) - { - HBLog( "HBMp3Enc: malloc() failed, gonna crash" ); - } + /* No resampling there - it's been done before */ + lame_set_in_samplerate( w->globalFlags, audio->outSampleRate ); + lame_set_out_samplerate( w->globalFlags, audio->outSampleRate ); - for( i = 0; i < m->inputSamples; i++ ) + if( lame_init_params( w->globalFlags ) == -1 ) { - m->left[i] = 0.0; - m->right[i] = 0.0; + HBLog( "HBMp3Enc: lame_init_params() failed" ); + HBErrorOccured( w->handle, HB_ERROR_MP3_INIT ); + return 0; } } - /* Push encoded buffer */ - if( m->mp3Buffer ) + if( HBFifoIsHalfFull( audio->outFifo ) ) { - if( HBFifoPush( audio->outFifo, &m->mp3Buffer ) ) - { - didSomething = 1; - } - else - { - return didSomething; - } + return 0; } - /* A/V synchro fix in case audio doesn't start at the same time - than video */ - if( audio->delay > 0 ) + if( !HBFifoGetBytes( audio->resampleFifo, (uint8_t*) samples_f, + 1152 * 2 * sizeof( float ), &position ) ) { - /* Audio starts later - insert some silence */ - int length = m->inputSamples * 1000 / audio->inSampleRate; - - if( audio->delay > length ) - { - HBLog( "HBMp3Enc: adding %d ms of silence", length ); - m->samplesGot = m->inputSamples; - audio->delay -= length; - } - else - { - audio->delay = 0; - } + return 0; } - else if( audio->delay < 0 ) - { - /* Audio starts sooner - trash some */ - int length = m->inputSamples * 1000 / audio->inSampleRate; - if( - audio->delay > length ) - { - if( GetSamples( m ) ) - { - didSomething = 1; - HBLog( "HBMp3Enc: trashing %d ms", length ); - m->samplesGot = 0; - audio->delay += length; - return didSomething; - } - else - { - return didSomething; - } - } - else - { - audio->delay = 0; - } - } - - /* Get new samples */ - if( GetSamples( m ) ) + /* float -> s16 */ + for( i = 0; i < 1152 * 2; i++ ) { - didSomething = 1; + samples_s16[i] = samples_f[i]; } - else - { - return didSomething; - } - - m->samplesGot = 0; mp3Buffer = HBBufferInit( LAME_MAXMP3BUFFER ); - ret = lame_encode_buffer_float( m->globalFlags, m->left, - m->right, m->inputSamples, - mp3Buffer->data, - mp3Buffer->size ); - /* Stats */ - m->samples += m->inputSamples; + ret = lame_encode_buffer_interleaved( w->globalFlags, + samples_s16, 1152, mp3Buffer->data, LAME_MAXMP3BUFFER ); if( ret < 0 ) { /* Error */ HBLog( "HBMp3Enc: lame_encode_buffer_float() failed (%d)", ret ); - HBErrorOccured( m->handle, HB_ERROR_MP3_ENCODE ); + HBErrorOccured( w->handle, HB_ERROR_MP3_ENCODE ); HBBufferClose( &mp3Buffer ); } else if( ret == 0 ) @@ -241,51 +125,14 @@ static int Mp3EncWork( HBWork * w ) /* Encoding was successful */ mp3Buffer->size = ret; mp3Buffer->keyFrame = 1; - mp3Buffer->position = m->position; - m->mp3Buffer = mp3Buffer; + mp3Buffer->position = position; - /* Stats */ - m->bytes += ret; - } - - return didSomething; -} - -static int GetSamples( HBMp3Enc * m ) -{ - while( m->samplesGot < m->inputSamples ) - { - int i; - - if( !m->rawBuffer ) - { - if( !( m->rawBuffer = HBFifoPop( m->audio->rawFifo ) ) ) - { - return 0; - } - - m->rawBufferPos = 0; - m->position = m->rawBuffer->position; - } - - i = MIN( m->inputSamples - m->samplesGot, - m->rawBuffer->samples - m->rawBufferPos ); - - memcpy( m->left + m->samplesGot, - m->rawBuffer->left + m->rawBufferPos, - i * sizeof( float ) ); - memcpy( m->right + m->samplesGot, - m->rawBuffer->right + m->rawBufferPos, - i * sizeof( float ) ); - - m->samplesGot += i; - m->rawBufferPos += i; - - if( m->rawBufferPos == m->rawBuffer->samples ) + if( !HBFifoPush( audio->outFifo, &mp3Buffer ) ) { - HBBufferClose( &m->rawBuffer ); + HBLog( "HBMp3Enc: HBFifoPush failed" ); } } return 1; } + |