diff options
author | Rodeo <[email protected]> | 2013-04-28 21:39:48 +0000 |
---|---|---|
committer | Rodeo <[email protected]> | 2013-04-28 21:39:48 +0000 |
commit | dbb20ebe94d7fe1e78d59261239354cff839c584 (patch) | |
tree | bbce64c0f316cf180c892081da7fb98e5a6039e0 | |
parent | ab0a39397c7b3630ba141cc8175d5eb05ef79a7d (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.c | 83 | ||||
-rw-r--r-- | libhb/scan.c | 1 | ||||
-rw-r--r-- | libhb/stream.c | 122 |
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); } /* |