diff options
-rw-r--r-- | contrib/ffmpeg/module.defs | 1 | ||||
-rw-r--r-- | libhb/decavcodec.c | 30 | ||||
-rw-r--r-- | libhb/muxavformat.c | 21 |
3 files changed, 51 insertions, 1 deletions
diff --git a/contrib/ffmpeg/module.defs b/contrib/ffmpeg/module.defs index 9956083f4..5c4a1a8e4 100644 --- a/contrib/ffmpeg/module.defs +++ b/contrib/ffmpeg/module.defs @@ -17,6 +17,7 @@ FFMPEG.CONFIGURE.extra = \ --enable-gpl \ --disable-doc \ --disable-bsfs \ + --enable-bsf=aac_adtstoasc \ --disable-avconv \ --disable-avplay \ --disable-avprobe \ diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index d7fe2244d..2029aa21d 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -606,6 +606,7 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf, { hb_work_private_t *pv = w->private_data; int ret = 0; + hb_audio_t *audio = w->audio; memset( info, 0, sizeof(*info) ); @@ -630,7 +631,7 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf, if (w->title && w->title->opaque_priv != NULL) { AVFormatContext *ic = (AVFormatContext*)w->title->opaque_priv; - avcodec_copy_context(context, ic->streams[w->audio->id]->codec); + avcodec_copy_context(context, ic->streams[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 @@ -778,6 +779,33 @@ static int decavcodecaBSInfo( hb_work_object_t *w, const hb_buffer_t *buf, info->mode = context->audio_service_type; } } + else if (context->codec_id == AV_CODEC_ID_AAC && + context->extradata_size == 0) + { + // Parse ADTS AAC streams for AudioSpecificConfig. + // This data is required in order to write + // proper headers in MP4 and MKV files. + AVBitStreamFilterContext* aac_adtstoasc; + aac_adtstoasc = av_bitstream_filter_init("aac_adtstoasc"); + if (aac_adtstoasc) + { + int ret, size; + uint8_t *data; + ret = av_bitstream_filter_filter(aac_adtstoasc, context, + NULL, &data, &size, avp.data, avp.size, 0); + if (ret >= 0 && + context->extradata_size > 0 && + audio->priv.config.extradata.length == 0) + { + int len; + len = MIN(context->extradata_size, HB_CONFIG_MAX_SIZE); + memcpy(audio->priv.config.extradata.bytes, + context->extradata, len); + audio->priv.config.extradata.length = len; + } + av_bitstream_filter_close(aac_adtstoasc); + } + } ret = 1; av_frame_free(&frame); diff --git a/libhb/muxavformat.c b/libhb/muxavformat.c index c5ebeb16a..9934c3551 100644 --- a/libhb/muxavformat.c +++ b/libhb/muxavformat.c @@ -32,6 +32,8 @@ struct hb_mux_data_s int64_t prev_chapter_tc; int16_t current_chapter; + + AVBitStreamFilterContext* bitstream_filter; }; struct hb_mux_object_s @@ -524,6 +526,15 @@ static int avformatInit( hb_mux_object_t * m ) memcpy(priv_data, audio->priv.config.extradata.bytes, audio->priv.config.extradata.length); + + // AAC from pass-through source may be ADTS. + // Therefore inserting "aac_adtstoasc" bitstream filter is + // preferred. + // The filter does nothing for non-ADTS bitstream. + if (audio->config.out.codec == HB_ACODEC_AAC_PASS) + { + track->bitstream_filter = av_bitstream_filter_init("aac_adtstoasc"); + } break; default: hb_error("muxavformat: Unknown audio codec: %x", @@ -1177,6 +1188,11 @@ static int avformatMux(hb_mux_object_t *m, hb_mux_data_t *track, hb_buffer_t *bu } track->duration = pts + pkt.duration; + if (track->bitstream_filter) + { + av_bitstream_filter_filter(track->bitstream_filter, track->st->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0); + } + pkt.stream_index = track->st->index; int ret = av_interleaved_write_frame(m->oc, &pkt); // Many avformat muxer functions do not check the error status @@ -1215,6 +1231,11 @@ static int avformatEnd(hb_mux_object_t *m) for (ii = 0; ii < m->ntracks; ii++) { avformatMux(m, m->tracks[ii], NULL); + + if (m->tracks[ii]->bitstream_filter) + { + av_bitstream_filter_close(m->tracks[ii]->bitstream_filter); + } } if (job->chapter_markers) |