summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRodeo <[email protected]>2013-04-28 21:39:48 +0000
committerRodeo <[email protected]>2013-04-28 21:39:48 +0000
commitdbb20ebe94d7fe1e78d59261239354cff839c584 (patch)
treebbce64c0f316cf180c892081da7fb98e5a6039e0
parentab0a39397c7b3630ba141cc8175d5eb05ef79a7d (diff)
Refactor add_ffmpeg_audio.
Simplify, set bitrate to 0 - scan will then call decavcodecaBSInfo, decode some audio and set the other input parameters, including samples_per_frame. decavcodec and scan fixes by John Stebbins. Thanks! git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@5424 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r--libhb/decavcodec.c83
-rw-r--r--libhb/scan.c1
-rw-r--r--libhb/stream.c122
3 files changed, 116 insertions, 90 deletions
diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c
index fcbc2eaa5..7dcfce90e 100644
--- a/libhb/decavcodec.c
+++ b/libhb/decavcodec.c
@@ -185,12 +185,21 @@ static int decavcodecaInit( hb_work_object_t * w, hb_job_t * job )
pv->title = w->title;
pv->list = hb_list_init();
- codec = avcodec_find_decoder(w->codec_param);
+ codec = avcodec_find_decoder(w->codec_param);
pv->context = avcodec_alloc_context3(codec);
+
if (pv->title->opaque_priv != NULL)
{
AVFormatContext *ic = (AVFormatContext*)pv->title->opaque_priv;
avcodec_copy_context(pv->context, ic->streams[w->audio->id]->codec);
+ // libav's eac3 parser toggles the codec_id in the context as
+ // it reads eac3 data between AV_CODEC_ID_AC3 and AV_CODEC_ID_EAC3.
+ // It detects an AC3 sync pattern sometimes in ac3_sync() which
+ // causes it to eventually set avctx->codec_id to AV_CODEC_ID_AC3
+ // in ff_aac_ac3_parse(). Since we are parsing some data before
+ // we get here, the codec_id may have flipped. This will cause an
+ // error in hb_avcodec_open(). So flip it back!
+ pv->context->codec_id = w->codec_param;
}
else
{
@@ -415,8 +424,27 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
static char codec_name[64];
info->name = strncpy( codec_name, codec->name, sizeof(codec_name)-1 );
- AVCodecParserContext *parser = av_parser_init( codec->id );
- AVCodecContext *context = avcodec_alloc_context3(codec);
+ AVCodecContext *context = avcodec_alloc_context3(codec);
+ AVCodecParserContext *parser = NULL;
+
+ if (w->title->opaque_priv != NULL)
+ {
+ AVFormatContext *ic = (AVFormatContext*)w->title->opaque_priv;
+ avcodec_copy_context(context, ic->streams[w->audio->id]->codec);
+ // libav's eac3 parser toggles the codec_id in the context as
+ // it reads eac3 data between AV_CODEC_ID_AC3 and AV_CODEC_ID_EAC3.
+ // It detects an AC3 sync pattern sometimes in ac3_sync() which
+ // causes it to eventually set avctx->codec_id to AV_CODEC_ID_AC3
+ // in ff_aac_ac3_parse(). Since we are parsing some data before
+ // we get here, the codec_id may have flipped. This will cause an
+ // error in hb_avcodec_open(). So flip it back!
+ context->codec_id = w->codec_param;
+ }
+ else
+ {
+ parser = av_parser_init(codec->id);
+ }
+
hb_ff_set_sample_fmt( context, codec, AV_SAMPLE_FMT_FLT );
if ( hb_avcodec_open( context, codec, NULL, 0 ) )
{
@@ -437,20 +465,6 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
len = av_parser_parse2(parser, context, &pbuffer, &pbuffer_size,
buf->data + pos, buf->size - pos,
buf->s.start, buf->s.start, 0);
- if (context->codec_id == AV_CODEC_ID_TRUEHD &&
- context->channel_layout == AV_CH_LAYOUT_MONO)
- {
- // libavcodec can't decode TrueHD Mono (bug #356)
- // work around it by requesting Stereo before decoding
- truehd_mono = 1;
- context->request_channels = 2;
- context->request_channel_layout = AV_CH_LAYOUT_STEREO;
- }
- else
- {
- context->request_channels = 0;
- context->request_channel_layout = 0;
- }
}
else
{
@@ -458,6 +472,22 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
len = pbuffer_size = buf->size;
}
pos += len;
+
+ // libavcodec can't decode TrueHD Mono (bug #356)
+ // work around it by requesting Stereo before decoding
+ if (context->codec_id == AV_CODEC_ID_TRUEHD &&
+ context->channel_layout == AV_CH_LAYOUT_MONO)
+ {
+ truehd_mono = 1;
+ context->request_channels = 2;
+ context->request_channel_layout = AV_CH_LAYOUT_STEREO;
+ }
+ else
+ {
+ context->request_channels = 0;
+ context->request_channel_layout = 0;
+ }
+
if (pbuffer_size > 0)
{
int got_frame;
@@ -472,8 +502,24 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
{
info->rate_base = 1;
info->rate = context->sample_rate;
- info->bitrate = context->bit_rate;
info->samples_per_frame = frame.nb_samples;
+
+ int bps = av_get_bits_per_sample(context->codec_id);
+ if (bps > 0 && context->channels > 0)
+ {
+ info->bitrate = (bps *
+ context->channels *
+ context->sample_rate);
+ }
+ else if (context->bit_rate > 0)
+ {
+ info->bitrate = context->bit_rate;
+ }
+ else
+ {
+ info->bitrate = 1;
+ }
+
if (truehd_mono)
{
info->channel_layout = AV_CH_LAYOUT_MONO;
@@ -484,6 +530,7 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf,
hb_ff_layout_xlat(context->channel_layout,
context->channels);
}
+
ret = 1;
break;
}
diff --git a/libhb/scan.c b/libhb/scan.c
index 40dffa01e..c83326d4d 100644
--- a/libhb/scan.c
+++ b/libhb/scan.c
@@ -1000,6 +1000,7 @@ static void LookForAudio( hb_title_t * title, hb_buffer_t * b )
}
hb_work_info_t info;
+ w->title = title;
w->audio = audio;
w->codec_param = audio->config.in.codec_param;
b = hb_fifo_see( audio->priv.scan_cache );
diff --git a/libhb/stream.c b/libhb/stream.c
index 3bab6998c..994cb70de 100644
--- a/libhb/stream.c
+++ b/libhb/stream.c
@@ -5118,87 +5118,65 @@ static void ffmpeg_close( hb_stream_t *d )
static void add_ffmpeg_audio(hb_title_t *title, hb_stream_t *stream, int id)
{
- AVStream *st = stream->ffmpeg_ic->streams[id];
- AVCodecContext *codec = st->codec;
- AVDictionaryEntry *tag;
-
- // scan will ignore any audio without a bitrate. Since we've already typed the
- // audio in order to determine its codec we set up the audio parameters here.
- if (codec->bit_rate || codec->sample_rate)
- {
- hb_audio_t *audio = calloc(1, sizeof(*audio));
- audio->id = id;
+ AVStream *st = stream->ffmpeg_ic->streams[id];
+ AVCodecContext *codec = st->codec;
+ AVDictionaryEntry *tag = av_dict_get(st->metadata, "language", NULL, 0);
+
+ hb_audio_t *audio = calloc(1, sizeof(*audio));
+ audio->id = id;
+ audio->config.in.track = id;
+ audio->config.in.codec = HB_ACODEC_FFMPEG;
+ audio->config.in.codec_param = codec->codec_id;
+ // set the bitrate to 0; decavcodecaBSInfo will be called and fill the rest
+ audio->config.in.bitrate = 0;
+
+ // set the input codec and extradata for Passthru
+ switch (codec->codec_id)
+ {
+ case AV_CODEC_ID_AAC:
+ {
+ int len = MIN(codec->extradata_size, HB_CONFIG_MAX_SIZE);
+ memcpy(audio->priv.config.extradata.bytes, codec->extradata, len);
+ audio->priv.config.extradata.length = len;
+ audio->config.in.codec = HB_ACODEC_FFAAC;
+ } break;
+
+ case AV_CODEC_ID_AC3:
+ audio->config.in.codec = HB_ACODEC_AC3;
+ audio->config.in.codec_param = 0;
+ break;
- if (codec->codec_id == AV_CODEC_ID_AC3)
+ case AV_CODEC_ID_DTS:
{
- audio->config.in.codec = HB_ACODEC_AC3;
- }
- else
- {
- if (codec->codec_id == AV_CODEC_ID_DTS)
+ switch (codec->profile)
{
- if (codec->profile == FF_PROFILE_DTS_HD_MA ||
- codec->profile == FF_PROFILE_DTS_HD_HRA)
- {
- audio->config.in.codec = HB_ACODEC_DCA_HD;
- }
- else if (codec->profile == FF_PROFILE_DTS ||
- codec->profile == FF_PROFILE_DTS_ES ||
- codec->profile == FF_PROFILE_DTS_96_24)
- {
+ case FF_PROFILE_DTS:
+ case FF_PROFILE_DTS_ES:
+ case FF_PROFILE_DTS_96_24:
audio->config.in.codec = HB_ACODEC_DCA;
- }
- else
- {
- audio->config.in.codec = HB_ACODEC_FFMPEG;
- }
- }
- else if (codec->codec_id == AV_CODEC_ID_AAC)
- {
- int len = MIN(codec->extradata_size, HB_CONFIG_MAX_SIZE);
- memcpy(audio->priv.config.extradata.bytes, codec->extradata,
- len);
- audio->priv.config.extradata.length = len;
- audio->config.in.codec = HB_ACODEC_FFAAC;
- }
- else if (codec->codec_id == AV_CODEC_ID_MP3)
- {
- audio->config.in.codec = HB_ACODEC_MP3;
- }
- else
- {
- audio->config.in.codec = HB_ACODEC_FFMPEG;
- }
- audio->config.in.codec_param = codec->codec_id;
+ break;
- int bps = av_get_bits_per_sample(codec->codec_id);
- if (bps && codec->sample_rate && codec->channels)
- {
- audio->config.in.bitrate = (codec->channels *
- codec->sample_rate * bps);
- }
- else if (codec->bit_rate)
- {
- audio->config.in.bitrate = codec->bit_rate;
- }
- else
- {
- audio->config.in.bitrate = 1;
+ case FF_PROFILE_DTS_HD_MA:
+ case FF_PROFILE_DTS_HD_HRA:
+ audio->config.in.codec = HB_ACODEC_DCA_HD;
+ break;
+
+ default:
+ break;
}
- audio->config.in.samplerate = codec->sample_rate;
- audio->config.in.samples_per_frame = codec->frame_size;
- audio->config.in.channel_map = &hb_libav_chan_map;
- audio->config.in.channel_layout =
- hb_ff_layout_xlat(codec->channel_layout, codec->channels);
- }
+ } break;
- tag = av_dict_get(st->metadata, "language", NULL, 0);
- set_audio_description(stream, audio,
- lang_for_code2(tag ? tag->value : "und"));
+ case AV_CODEC_ID_MP3:
+ audio->config.in.codec = HB_ACODEC_MP3;
+ break;
- audio->config.in.track = id;
- hb_list_add(title->list_audio, audio);
+ default:
+ break;
}
+
+ set_audio_description(stream, audio,
+ lang_for_code2(tag != NULL ? tag->value : "und"));
+ hb_list_add(title->list_audio, audio);
}
/*