diff options
author | handbrake <[email protected]> | 2006-01-14 13:40:38 +0000 |
---|---|---|
committer | handbrake <[email protected]> | 2006-01-14 13:40:38 +0000 |
commit | 56bb6ce496b475944bb9577c7586e84be1cb831e (patch) | |
tree | 7720c135a160a34f22ce8f1f911f350e18207eaa /libhb/declpcm.c | |
parent | d35a2a23fe450c88925128b9db7c63a5f1ed395d (diff) |
HandBrake 0.7.0
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@16 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/declpcm.c')
-rw-r--r-- | libhb/declpcm.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/libhb/declpcm.c b/libhb/declpcm.c new file mode 100644 index 000000000..59163c366 --- /dev/null +++ b/libhb/declpcm.c @@ -0,0 +1,113 @@ +/* $Id: declpcm.c,v 1.8 2005/11/04 14:44:01 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "hb.h" + +struct hb_work_object_s +{ + HB_WORK_COMMON; + + hb_job_t * job; + hb_audio_t * audio; + + int64_t pts_last; +}; + +static int Work( hb_work_object_t * w, hb_buffer_t ** buf_in, + hb_buffer_t ** buf_out ) +{ + hb_buffer_t * in = *buf_in, * out; + int samplerate = 0; + int count; + uint8_t * samples_u8; + float * samples_fl32; + int i; + uint64_t duration; + + *buf_out = NULL; + + if( in->data[5] != 0x80 ) + { + hb_log( "no LPCM frame sync (%02x)", in->data[5] ); + return HB_WORK_OK; + } + + switch( ( in->data[4] >> 4 ) & 0x3 ) + { + case 0: + samplerate = 48000; + break; + case 1: + samplerate = 96000;//32000; /* FIXME vlc says it is 96000 */ + break; + case 2: + samplerate = 44100; + break; + case 3: + samplerate = 32000; + break; + } + + count = ( in->size - 6 ) / 2; + out = hb_buffer_init( count * sizeof( float ) ); + duration = count * 90000 / samplerate / 2; + if( w->pts_last > 0 && + in->start < w->pts_last + duration / 6 && + in->start > w->pts_last - duration / 6 ) + { + /* Workaround for DVDs where dates aren't exact */ + out->start = w->pts_last; + } + else + { + out->start = in->start; + } + out->stop = out->start + duration; + w->pts_last = out->stop; + + samples_u8 = in->data + 6; + samples_fl32 = (float *) out->data; + + /* Big endian int16 -> float conversion */ + for( i = 0; i < count; i++ ) + { +#ifdef WORDS_BIGENDIAN + samples_fl32[0] = *( (int16_t *) samples_u8 ); +#else + samples_fl32[0] = (int16_t) ( ( samples_u8[0] << 8 ) | samples_u8[1] ); +#endif + samples_u8 += 2; + samples_fl32 += 1; + } + + *buf_out = out; + + return HB_WORK_OK; +} + +static void Close( hb_work_object_t ** _w ) +{ + hb_work_object_t * w = *_w; + free( w->name ); + free( w ); + *_w = NULL; +} + +hb_work_object_t * hb_work_declpcm_init( hb_job_t * job, hb_audio_t * audio ) +{ + hb_work_object_t * w = calloc( sizeof( hb_work_object_t ), 1 ); + w->name = strdup( "LPCM decoder" ); + w->work = Work; + w->close = Close; + + w->job = job; + w->audio = audio; + + w->pts_last = -1; + + return w; +} + |