]> granicus.if.org Git - handbrake/commitdiff
decavcodec: drop initial_padding audio samples
authorJohn Stebbins <jstebbins.hb@gmail.com>
Tue, 21 Feb 2017 17:51:33 +0000 (10:51 -0700)
committerJohn Stebbins <jstebbins.hb@gmail.com>
Tue, 21 Feb 2017 17:53:57 +0000 (10:53 -0700)
These are samples that were not in the original source and were added by
the encoder.  To get a faithful reproduction of the source, they must be
dropped.

libhb/common.h
libhb/decavcodec.c
libhb/stream.c

index 06a22c2a8504ab513f1df8a691ade466951d9988..4d7c548b343c5719b46b277d5f6fd3a4cf59bc3d 100644 (file)
@@ -770,6 +770,9 @@ struct hb_audio_config_s
         PRIVATE int matrix_encoding; /* Source matrix encoding mode, set by the audio decoder */
         PRIVATE uint64_t channel_layout; /* Source channel layout, set by the audio decoder */
         PRIVATE hb_chan_map_t * channel_map; /* Source channel map, set by the audio decoder */
+        PRIVATE int encoder_delay; /* Encoder delay in samples.
+                                    * These samples should be dropped
+                                    * when decoding */
     } in;
 
     struct
index 3788400e4292c9eea51438afb162c089059efc84..3515ba1674f6018a1409dc4445a756e4fd9b5dbe 100644 (file)
@@ -126,6 +126,7 @@ struct hb_work_private_s
 
     hb_audio_t           * audio;
     hb_audio_resample_t  * resample;
+    int                    drop_samples;
 
 #ifdef USE_QSV
     // QSV-specific settings
@@ -154,13 +155,14 @@ static int decavcodecaInit( hb_work_object_t * w, hb_job_t * job )
     hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
     w->private_data = pv;
 
-    pv->job       = job;
-    pv->audio     = w->audio;
-    pv->next_pts  = (int64_t)AV_NOPTS_VALUE;
+    pv->job          = job;
+    pv->audio        = w->audio;
+    pv->drop_samples = w->audio->config.in.encoder_delay;
+    pv->next_pts     = (int64_t)AV_NOPTS_VALUE;
     if (job)
-        pv->title = job->title;
+        pv->title    = job->title;
     else
-        pv->title = w->title;
+        pv->title    = w->title;
     hb_buffer_list_clear(&pv->list);
 
     codec       = avcodec_find_decoder(w->codec_param);
@@ -413,8 +415,10 @@ static int decavcodecaWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
     if (in->s.flags & HB_BUF_FLAG_EOF)
     {
         /* EOF on input stream - send it downstream & say that we're done */
-        *buf_out = in;
+        decodeAudio(pv, NULL);
+        hb_buffer_list_append(&pv->list, in);
         *buf_in = NULL;
+        *buf_out = hb_buffer_list_clear(&pv->list);
         return HB_WORK_DONE;
     }
 
@@ -1964,10 +1968,18 @@ static void decodeAudio(hb_work_private_t *pv, packet_info_t * packet_info)
     int              ret;
 
     av_init_packet(&avp);
-    avp.data = packet_info->data;
-    avp.size = packet_info->size;
-    avp.pts  = packet_info->pts;
-    avp.dts  = AV_NOPTS_VALUE;
+    if (packet_info != NULL)
+    {
+        avp.data = packet_info->data;
+        avp.size = packet_info->size;
+        avp.pts  = packet_info->pts;
+        avp.dts  = AV_NOPTS_VALUE;
+    }
+    else
+    {
+        avp.data = NULL;
+        avp.size = 0;
+    }
 
     ret = avcodec_send_packet(context, &avp);
     if (ret < 0 && ret != AVERROR_EOF)
@@ -2002,6 +2014,9 @@ static void decodeAudio(hb_work_private_t *pv, packet_info_t * packet_info)
         }
         pv->duration = (90000. * pv->frame->nb_samples / samplerate);
 
+        int64_t pts = pv->frame->pts;
+        double  duration = pv->duration;
+
         if (pv->audio->config.out.codec & HB_ACODEC_PASS_FLAG)
         {
             // Note that even though we are doing passthru, we had to decode
@@ -2050,13 +2065,37 @@ static void decodeAudio(hb_work_private_t *pv, packet_info_t * packet_info)
             }
             out = hb_audio_resample(pv->resample, pv->frame->extended_data,
                                     pv->frame->nb_samples);
+            if (out != NULL && pv->drop_samples > 0)
+            {
+                /* drop audio samples that are part of the encoder delay */
+                int channels = hb_mixdown_get_discrete_channel_count(
+                                                pv->audio->config.out.mixdown);
+                int sample_size = channels * sizeof(float);
+                int samples = out->size / sample_size;
+                if (samples <= pv->drop_samples)
+                {
+                    hb_buffer_close(&out);
+                    pv->drop_samples -= samples;
+                }
+                else
+                {
+                    int size = pv->drop_samples * sample_size;
+                    double drop_duration = pv->drop_samples * 90000L /
+                                           pv->audio->config.out.samplerate;
+                    memmove(out->data, out->data + size, out->size - size);
+                    out->size -= size;
+                    pts += drop_duration;
+                    duration -= drop_duration;
+                    pv->drop_samples = 0;
+                }
+            }
         }
 
         if (out != NULL)
         {
             out->s.scr_sequence = packet_info->scr_sequence;
-            out->s.start        = pv->frame->pts;
-            out->s.duration     = pv->duration;
+            out->s.start        = pts;
+            out->s.duration     = duration;
             if (out->s.start == AV_NOPTS_VALUE)
             {
                 out->s.start = pv->next_pts;
index b03a1530a3a72aadecbb4ae501fcec615ab5b62b..69af167b76854315a71cf1848340f11000560a5e 100644 (file)
@@ -5101,13 +5101,14 @@ static void add_ffmpeg_audio(hb_title_t *title, hb_stream_t *stream, int id)
     AVCodecParameters *codecpar = st->codecpar;
     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 = codecpar->codec_id;
+    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   = codecpar->codec_id;
     // set the bitrate to 0; decavcodecaBSInfo will be called and fill the rest
-    audio->config.in.bitrate     = 0;
+    audio->config.in.bitrate       = 0;
+    audio->config.in.encoder_delay = codecpar->initial_padding;
 
     // set the input codec and extradata for Passthru
     switch (codecpar->codec_id)