]> granicus.if.org Git - handbrake/commitdiff
mux: shift timestamps by largest encoder delay
authorJohn Stebbins <jstebbins.hb@gmail.com>
Tue, 14 Feb 2017 23:25:40 +0000 (16:25 -0700)
committerJohn Stebbins <jstebbins.hb@gmail.com>
Tue, 14 Feb 2017 23:27:26 +0000 (16:27 -0700)
This prevents libav from adding an mp4 edit list entry that causes a
properly functioning player to drop the first couple of audio frames.

libhb/common.h
libhb/encavcodec.c
libhb/encavcodecaudio.c
libhb/encx264.c
libhb/encx265.c
libhb/hbtypes.h
libhb/internal.h
libhb/muxavformat.c

index aa2f2ba3e9bc8691936968ff671d73d17ade3c82..06a22c2a8504ab513f1df8a691ade466951d9988 100644 (file)
@@ -749,7 +749,6 @@ struct hb_audio_config_s
         int      normalize_mix_level; /* mix level normalization (boolean) */
         int      dither_method; /* dither algorithm */
         char *   name; /* Output track name */
-        int      delay;
     } out;
 
     /* Input */
index 63c325a40515aece43a3c73c3b43ed6034483a83..76fe3e7c7bbf6de5c29af07de98ab60a0c05c850 100644 (file)
@@ -444,7 +444,7 @@ static void compute_dts_offset( hb_work_private_t * pv, hb_buffer_t * buf )
         if ( ( pv->frameno_in ) == pv->job->areBframes )
         {
             pv->dts_delay = buf->s.start;
-            pv->job->config.h264.init_delay = pv->dts_delay;
+            pv->job->config.init_delay = pv->dts_delay;
         }
     }
 }
index e376d4436629d02d0cf97c00c4df6893cd87d7ed..9f07f4a795c86c7effcc091ca94b746d899767ad 100644 (file)
@@ -200,6 +200,9 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
         hb_error("encavcodecaInit: hb_avcodec_open() failed");
         return 1;
     }
+    w->config->init_delay = av_rescale_q(context->delay, context->time_base,
+                                         (AVRational){1, 90000});
+
     // avcodec_open populates the opts dictionary with the
     // things it didn't recognize.
     AVDictionaryEntry *t = NULL;
@@ -268,9 +271,6 @@ static int encavcodecaInit(hb_work_object_t *w, hb_job_t *job)
         w->config->extradata.length = context->extradata_size;
     }
 
-    audio->config.out.delay = av_rescale_q(context->delay, context->time_base,
-                                           (AVRational){1, 90000});
-
     return 0;
 }
 
@@ -426,7 +426,6 @@ static void Encode(hb_work_object_t *w, hb_buffer_list_t *list)
                                           audio->config.out.samplerate));
         frame.pts = av_rescale(frame.pts, pv->context->sample_rate, 90000);
 
-
         // Encode
         ret = avcodec_send_frame(pv->context, &frame);
         if (ret < 0)
index 1fccd7d27256d16ba59bfeba163783c016af4369..1d2fd997e9c2095ea314b9baa385a9db93fb3b40 100644 (file)
@@ -654,9 +654,9 @@ static hb_buffer_t *nal_encode( hb_work_object_t *w, x264_picture_t *pic_out,
     buf->s.start        = pic_out->i_pts;
     buf->s.stop         = buf->s.start + buf->s.duration;
     buf->s.renderOffset = pic_out->i_dts;
-    if ( !w->config->h264.init_delay && pic_out->i_dts < 0 )
+    if ( !w->config->init_delay && pic_out->i_dts < 0 )
     {
-        w->config->h264.init_delay = -pic_out->i_dts;
+        w->config->init_delay = -pic_out->i_dts;
     }
 
     /* Determine what type of frame we have. */
index 0c5d4141a977314d1ffc1b1c938eeb9e88bc3379..90d786983beebd67a6cf003f7ee76d43bc7c0504 100644 (file)
@@ -414,9 +414,9 @@ static hb_buffer_t* nal_encode(hb_work_object_t *w,
     buf->s.stop         = pic_out->pts + buf->s.duration;
     buf->s.start        = pic_out->pts;
     buf->s.renderOffset = pic_out->dts;
-    if (w->config->h264.init_delay == 0 && pic_out->dts < 0)
+    if (w->config->init_delay == 0 && pic_out->dts < 0)
     {
-        w->config->h264.init_delay -= pic_out->dts;
+        w->config->init_delay -= pic_out->dts;
     }
 
     switch (pic_out->sliceType)
index 7c7d2c679c65ae19d763ad9c7d69afca7dacc1bc..064ba7b6df812d8f2c5d893550c168019cd70128 100644 (file)
@@ -34,7 +34,7 @@ typedef struct hb_attachment_s hb_attachment_t;
 typedef struct hb_metadata_s hb_metadata_t;
 typedef struct hb_coverart_s hb_coverart_t;
 typedef struct hb_state_s hb_state_t;
-typedef union  hb_esconfig_u     hb_esconfig_t;
+typedef struct hb_esconfig_s     hb_esconfig_t;
 typedef struct hb_work_private_s hb_work_private_t;
 typedef struct hb_work_object_s  hb_work_object_t;
 typedef struct hb_filter_private_s hb_filter_private_t;
index 1a709442934ddb0c01acfdb1be65a6cc780001f9..1e79447f80c23809b575c332c89622628d6293ed 100644 (file)
@@ -373,8 +373,12 @@ void hb_stream_set_need_keyframe( hb_stream_t *stream, int need_keyframe );
  * Work objects
  **********************************************************************/
 #define HB_CONFIG_MAX_SIZE (2*8192)
-union hb_esconfig_u
+struct hb_esconfig_s
 {
+    int init_delay;
+
+    union
+    {
 
     struct
     {
@@ -388,7 +392,6 @@ union hb_esconfig_u
            int       sps_length;
            uint8_t  pps[HB_CONFIG_MAX_SIZE];
            int       pps_length;
-        int      init_delay;
        } h264;
 
     struct
@@ -413,6 +416,7 @@ union hb_esconfig_u
         uint8_t headers[3][HB_CONFIG_MAX_SIZE];
         char *language;
     } vorbis;
+    };
 };
 
 enum
index e042a9d1c876f98431a52b33f1c7a0375bf5b244..5f15b7970d95f724c922e91405019861cbef0d2e 100644 (file)
@@ -44,6 +44,7 @@ struct hb_mux_object_s
 
     AVFormatContext   * oc;
     AVRational          time_base;
+    int64_t             delay;
 
     int                 ntracks;
     hb_mux_data_t    ** tracks;
@@ -107,6 +108,25 @@ static char* lookup_lang_code(int mux, char *iso639_2)
     return out;
 }
 
+static int64_t compute_delay(hb_job_t * job)
+{
+    int64_t delay = 0;
+
+    if (job->config.init_delay > delay)
+        delay = job->config.init_delay;
+
+    int ii, count;
+    count = hb_list_count(job->list_audio);
+    for (ii = 0; ii < count; ii++)
+    {
+        hb_audio_t * audio = hb_list_item(job->list_audio, ii);
+        if (audio->priv.config.init_delay > delay)
+            delay = audio->priv.config.init_delay;
+    }
+
+    return delay;
+}
+
 /**********************************************************************
  * avformatInit
  **********************************************************************
@@ -130,6 +150,7 @@ static int avformatInit( hb_mux_object_t * m )
     uint8_t         need_fonts = 0;
     char *lang;
 
+    m->delay = AV_NOPTS_VALUE;
 
     max_tracks = 1 + hb_list_count( job->list_audio ) +
                      hb_list_count( job->list_subtitle );
@@ -1064,6 +1085,10 @@ static int avformatMux(hb_mux_object_t *m, hb_mux_data_t *track, hb_buffer_t *bu
     hb_job_t * job     = m->job;
     uint8_t  * sub_out = NULL;
 
+    if (m->delay == AV_NOPTS_VALUE)
+    {
+        m->delay = compute_delay(m->job);
+    }
     if (track->type == MUX_TYPE_VIDEO && (job->mux & HB_MUX_MASK_MP4))
     {
         // compute dts duration for MP4 files
@@ -1098,6 +1123,15 @@ static int avformatMux(hb_mux_object_t *m, hb_mux_data_t *track, hb_buffer_t *bu
         return 0;
     }
 
+    buf->s.start += m->delay;
+    if (buf->s.renderOffset != AV_NOPTS_VALUE)
+    {
+        buf->s.renderOffset += m->delay;
+    }
+    if (buf->s.stop != AV_NOPTS_VALUE)
+    {
+        buf->s.stop += m->delay;
+    }
     if (track->type == MUX_TYPE_VIDEO && (job->mux & HB_MUX_MASK_MKV) &&
         buf->s.renderOffset < 0)
     {