diff options
author | van <[email protected]> | 2009-11-26 10:08:55 +0000 |
---|---|---|
committer | van <[email protected]> | 2009-11-26 10:08:55 +0000 |
commit | 8dd32d1a370b061290ff26b4affbe28aa62ba66f (patch) | |
tree | ac5376d502c34a4828c9f1d905e11edde0af6e0b /libhb/decavcodec.c | |
parent | cafcbe5d543e28bbe23b56fd18fe8cbc8f1c19e8 (diff) |
Fix audio sync problem for AAC (or any other mpeg PS or TS audio decoded by decavcodec) with a sample rate other than 48KHz. This problem had already been fixed for decavcodecai (the 'internal' ffmpeg audio decoder that handles all input files but mpeg streams) so decavcodec was just changed to use the same logic.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@2985 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb/decavcodec.c')
-rw-r--r-- | libhb/decavcodec.c | 97 |
1 files changed, 31 insertions, 66 deletions
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index 9d1474b34..f8a06992f 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -110,6 +110,10 @@ struct hb_work_private_s struct SwsContext *sws_context; // if we have to rescale or convert color space }; +static void decodeAudio( hb_work_private_t *pv, uint8_t *data, int size ); +static hb_buffer_t *link_buf_list( hb_work_private_t *pv ); + + static int64_t heap_pop( pts_heap_t *heap ) { int64_t result; @@ -183,6 +187,7 @@ static int decavcodecInit( hb_work_object_t * w, hb_job_t * job ) w->private_data = pv; pv->job = job; + pv->list = hb_list_init(); int codec_id = w->codec_param; /*XXX*/ @@ -250,17 +255,12 @@ static int decavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in, hb_buffer_t ** buf_out ) { hb_work_private_t * pv = w->private_data; - hb_buffer_t * in = *buf_in, * buf, * last = NULL; - int pos, len, out_size, i, uncompressed_len; - short* bufaligned; - uint64_t cur; - unsigned char *parser_output_buffer; - int parser_output_buffer_len; + hb_buffer_t * in = *buf_in; - if ( (*buf_in)->size <= 0 ) + if ( in->size <= 0 ) { /* EOF on input stream - send it downstream & say that we're done */ - *buf_out = *buf_in; + *buf_out = in; *buf_in = NULL; return HB_WORK_DONE; } @@ -273,75 +273,40 @@ static int decavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in, return HB_WORK_OK; } - cur = ( in->start < 0 )? pv->pts_next : in->start; + // if the packet has a timestamp use it + if ( in->start != -1 ) + { + pv->pts_next = in->start; + } - bufaligned = av_malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE ); - pos = 0; - while( pos < in->size ) + int pos, len; + for ( pos = 0; pos < in->size; pos += len ) { + uint8_t *parser_output_buffer; + int parser_output_buffer_len; + int64_t cur = pv->pts_next; + len = av_parser_parse2( pv->parser, pv->context, &parser_output_buffer, &parser_output_buffer_len, in->data + pos, in->size - pos, cur, cur, AV_NOPTS_VALUE ); - out_size = 0; - uncompressed_len = 0; if (parser_output_buffer_len) { - AVPacket avp; - av_init_packet( &avp ); - avp.data = parser_output_buffer; - avp.size = parser_output_buffer_len; - - out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; - uncompressed_len = avcodec_decode_audio3( pv->context, bufaligned, &out_size, &avp ); - } - if( out_size ) - { - short * s16; - float * fl32; - - buf = hb_buffer_init( 2 * out_size ); - - int sample_size_in_bytes = 2; // Default to 2 bytes - switch (pv->context->sample_fmt) + // set the duration on every frame since the stream format can + // change (it shouldn't but there's no way to guarantee it). + // duration is a scaling factor to go from #bytes in the decoded + // frame to frame time (in 90KHz mpeg ticks). 'channels' converts + // total samples to per-channel samples. 'sample_rate' converts + // per-channel samples to seconds per sample and the 90000 + // is mpeg ticks per second. + if ( pv->context->sample_rate && pv->context->channels ) { - case SAMPLE_FMT_S16: - sample_size_in_bytes = 2; - break; - /* We should handle other formats here - but that needs additional format conversion work below */ - /* For now we'll just report the error and try to carry on */ - default: - hb_log("decavcodecWork - Unknown Sample Format from avcodec_decode_audio (%d) !", pv->context->sample_fmt); - break; - } - - buf->start = cur; - buf->stop = cur + 90000 * ( out_size / (sample_size_in_bytes * pv->context->channels) ) / - pv->context->sample_rate; - cur = buf->stop; - - s16 = bufaligned; - fl32 = (float *) buf->data; - for( i = 0; i < out_size / 2; i++ ) - { - fl32[i] = s16[i]; - } - - if( last ) - { - last = last->next = buf; - } - else - { - *buf_out = last = buf; + pv->duration = 90000. / + (double)( pv->context->sample_rate * pv->context->channels ); } + decodeAudio( pv, parser_output_buffer, parser_output_buffer_len ); } - - pos += len; } - - pv->pts_next = cur; - - av_free( bufaligned ); + *buf_out = link_buf_list( pv ); return HB_WORK_OK; } |