summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjstebbins <[email protected]>2010-04-02 23:58:24 +0000
committerjstebbins <[email protected]>2010-04-02 23:58:24 +0000
commit7397025b5095f6154f69b5529a79791d5588d935 (patch)
tree0ab6e53e6f7a6bf3b55eddb8143827dcd0765713
parentfc299fb336fa32722f04e529e987c27d67dddb26 (diff)
fix audio detection problem during scan of ffmpeg audio sources
audio frames can be larger than their container packet sizes, but during scan, we only feed one container packet to the decoder, then reset the decoder and try the next packet. so the audio is never detected. as buffers are tested, they are added to a cache. the entire cache is passed to the decoder to scan for info. the cache is limited to 4KB. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3195 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r--libhb/common.h1
-rw-r--r--libhb/decavcodec.c69
-rw-r--r--libhb/fifo.c17
-rw-r--r--libhb/internal.h1
-rw-r--r--libhb/scan.c48
5 files changed, 99 insertions, 37 deletions
diff --git a/libhb/common.h b/libhb/common.h
index cf1dc02d8..69c6ddea0 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -436,6 +436,7 @@ struct hb_audio_s
hb_esconfig_t config;
hb_mux_data_t * mux_data;
+ hb_fifo_t * scan_cache;
} priv;
};
#endif
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index e083d517e..9f3196a85 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -389,44 +389,53 @@ static int decavcodecBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
uint8_t *buffer = av_malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE );
int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
unsigned char *pbuffer;
- int pos = 0, pbuffer_size;
+ int pos, pbuffer_size;
- while ( pos < buf->size )
+ while ( buf && !ret )
{
- int len;
-
- if (parser != NULL )
- {
- len = av_parser_parse2( parser, context, &pbuffer, &pbuffer_size,
- buf->data + pos, buf->size - pos,
- buf->start, buf->start, AV_NOPTS_VALUE );
- }
- else
+ pos = 0;
+ while ( pos < buf->size )
{
- pbuffer = buf->data;
- len = pbuffer_size = buf->size;
- }
- pos += len;
- if ( pbuffer_size > 0 )
- {
- AVPacket avp;
- av_init_packet( &avp );
- avp.data = pbuffer;
- avp.size = pbuffer_size;
+ int len;
- len = avcodec_decode_audio3( context, (int16_t*)buffer, &out_size, &avp );
- if ( len > 0 && context->sample_rate > 0 )
+ if (parser != NULL )
{
- info->bitrate = context->bit_rate;
- info->rate = context->sample_rate;
- info->rate_base = 1;
- info->channel_layout =
- hb_ff_layout_xlat(context->channel_layout, context->channels);
- ret = 1;
- break;
+ len = av_parser_parse2( parser, context, &pbuffer,
+ &pbuffer_size, buf->data + pos,
+ buf->size - pos, buf->start,
+ buf->start, AV_NOPTS_VALUE );
+ }
+ else
+ {
+ pbuffer = buf->data;
+ len = pbuffer_size = buf->size;
+ }
+ pos += len;
+ if ( pbuffer_size > 0 )
+ {
+ AVPacket avp;
+ av_init_packet( &avp );
+ avp.data = pbuffer;
+ avp.size = pbuffer_size;
+
+ len = avcodec_decode_audio3( context, (int16_t*)buffer,
+ &out_size, &avp );
+ if ( len > 0 && context->sample_rate > 0 )
+ {
+ info->bitrate = context->bit_rate;
+ info->rate = context->sample_rate;
+ info->rate_base = 1;
+ info->channel_layout =
+ hb_ff_layout_xlat(context->channel_layout,
+ context->channels);
+ ret = 1;
+ break;
+ }
}
}
+ buf = buf->next;
}
+
av_free( buffer );
if ( parser != NULL )
av_parser_close( parser );
diff --git a/libhb/fifo.c b/libhb/fifo.c
index c72b4e10b..3aeeea273 100644
--- a/libhb/fifo.c
+++ b/libhb/fifo.c
@@ -235,6 +235,23 @@ hb_fifo_t * hb_fifo_init( int capacity, int thresh )
return f;
}
+int hb_fifo_size_bytes( hb_fifo_t * f )
+{
+ int ret = 0;
+ hb_buffer_t * link;
+
+ hb_lock( f->lock );
+ link = f->first;
+ while ( link )
+ {
+ ret += link->size;
+ link = link->next;
+ }
+ hb_unlock( f->lock );
+
+ return ret;
+}
+
int hb_fifo_size( hb_fifo_t * f )
{
int ret;
diff --git a/libhb/internal.h b/libhb/internal.h
index 59753022e..7672c7311 100644
--- a/libhb/internal.h
+++ b/libhb/internal.h
@@ -87,6 +87,7 @@ void hb_buffer_copy_settings( hb_buffer_t * dst,
hb_fifo_t * hb_fifo_init( int capacity, int thresh );
int hb_fifo_size( hb_fifo_t * );
+int hb_fifo_size_bytes( hb_fifo_t * );
int hb_fifo_is_full( hb_fifo_t * );
float hb_fifo_percent_full( hb_fifo_t * f );
hb_buffer_t * hb_fifo_get( hb_fifo_t * );
diff --git a/libhb/scan.c b/libhb/scan.c
index e14e6712b..1ae5de007 100644
--- a/libhb/scan.c
+++ b/libhb/scan.c
@@ -30,7 +30,7 @@ typedef struct
static void ScanFunc( void * );
static int DecodePreviews( hb_scan_t *, hb_title_t * title );
-static void LookForAudio( hb_title_t * title, hb_buffer_t * b );
+static int LookForAudio( hb_title_t * title, hb_buffer_t * b );
static int AllAudioOK( hb_title_t * title );
static const char *aspect_to_string( double aspect )
@@ -163,6 +163,11 @@ static void ScanFunc( void * _data )
free( audio );
continue;
}
+ if ( audio->priv.scan_cache )
+ {
+ hb_fifo_flush( audio->priv.scan_cache );
+ hb_fifo_close( &audio->priv.scan_cache );
+ }
j++;
}
@@ -513,9 +518,11 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title )
vid_buf = NULL;
}
}
- else if( ! AllAudioOK( title ) )
+ else
{
- LookForAudio( title, buf_es );
+ if( ! AllAudioOK( title ) )
+ if ( !LookForAudio( title, buf_es ) )
+ buf_es = NULL;
}
if ( buf_es )
hb_buffer_close( &buf_es );
@@ -698,6 +705,15 @@ static int DecodePreviews( hb_scan_t * data, hb_title_t * title )
++npreviews;
skip_preview:
+ /* Make sure we found audio rates and bitrates */
+ for( j = 0; j < hb_list_count( title->list_audio ); j++ )
+ {
+ hb_audio_t * audio = hb_list_item( title->list_audio, j );
+ if ( audio->priv.scan_cache )
+ {
+ hb_fifo_flush( audio->priv.scan_cache );
+ }
+ }
if ( vid_buf )
hb_buffer_close( &vid_buf );
}
@@ -809,7 +825,7 @@ skip_preview:
* aren't (e.g., some European DVD Teletext streams use the same IDs as US ATSC
* AC-3 audio).
*/
-static void LookForAudio( hb_title_t * title, hb_buffer_t * b )
+static int LookForAudio( hb_title_t * title, hb_buffer_t * b )
{
int i;
@@ -830,9 +846,20 @@ static void LookForAudio( hb_title_t * title, hb_buffer_t * b )
if( !audio || audio->config.in.bitrate != 0 )
{
/* not found or already done */
- return;
+ return 1;
}
+ if ( audio->priv.scan_cache == NULL )
+ audio->priv.scan_cache = hb_fifo_init( 16, 16 );
+
+ if ( hb_fifo_size_bytes( audio->priv.scan_cache ) >= 4096 )
+ {
+ hb_buffer_t * tmp;
+ tmp = hb_fifo_get( audio->priv.scan_cache );
+ hb_buffer_close( &tmp );
+ }
+ hb_fifo_push( audio->priv.scan_cache, b );
+
hb_work_object_t *w = hb_codec_decoder( audio->config.in.codec );
if ( w == NULL || w->bsinfo == NULL )
@@ -845,6 +872,7 @@ static void LookForAudio( hb_title_t * title, hb_buffer_t * b )
hb_work_info_t info;
w->audio = audio;
w->codec_param = audio->config.in.codec_param;
+ b = hb_fifo_see( audio->priv.scan_cache );
int ret = w->bsinfo( w, b, &info );
if ( ret < 0 )
{
@@ -856,8 +884,11 @@ static void LookForAudio( hb_title_t * title, hb_buffer_t * b )
if ( !info.bitrate )
{
/* didn't find any info */
- return;
+ return 0;
}
+ hb_fifo_flush( audio->priv.scan_cache );
+ hb_fifo_close( &audio->priv.scan_cache );
+
audio->config.in.samplerate = info.rate;
audio->config.in.bitrate = info.bitrate;
audio->config.in.channel_layout = info.channel_layout;
@@ -886,7 +917,7 @@ static void LookForAudio( hb_title_t * title, hb_buffer_t * b )
audio->config.lang.description );
free( w );
- return;
+ return 1;
// We get here if there's no hope of finding info on an audio bitstream,
// either because we don't have a decoder (or a decoder with a bitstream
@@ -898,7 +929,10 @@ static void LookForAudio( hb_title_t * title, hb_buffer_t * b )
if ( w )
free( w );
+ hb_fifo_flush( audio->priv.scan_cache );
+ hb_fifo_close( &audio->priv.scan_cache );
hb_list_rem( title->list_audio, audio );
+ return -1;
}
/*