libhb: Fix AAC passthru from TS files
authorjstebbins <jstebbins.hb@gmail.com>
Wed, 4 Feb 2015 00:23:12 +0000 (00:23 +0000)
committerjstebbins <jstebbins.hb@gmail.com>
Wed, 4 Feb 2015 00:23:12 +0000 (00:23 +0000)
Apply aac_adtstoasc bitstream filter while muxing AAC stream and extract
AudioSpecificConfig during scan.

Patch submitted by Taihei Momma

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6867 b64f7644-9d1e-0410-96f1-a4d463321fa5

contrib/ffmpeg/module.defs
libhb/decavcodec.c
libhb/muxavformat.c

index 2bcd41d983040358715917f084d08524b73c27b5..49dd3e1eb9def340af8a2134612d7b291979b36a 100644 (file)
@@ -17,6 +17,7 @@ FFMPEG.CONFIGURE.extra = \
     --enable-gpl \
     --disable-doc \
     --disable-bsfs \
+    --enable-bsf=aac_adtstoasc \
     --disable-avconv \
     --disable-avplay \
     --disable-avprobe \
index 9c48a7bf9977af02d44146e04cb51448c22d5539..fef5dd89df1c347f4ab6febbc8df12794f7f63aa 100644 (file)
@@ -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);
index bf28ae6aaa3c4d9f309a1700f17a00049c42f015..266a3ae453b83c40643b835bc8d037b02d47edf4 100644 (file)
@@ -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
@@ -515,6 +517,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",
@@ -1173,6 +1184,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
@@ -1211,6 +1227,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)