summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Stebbins <[email protected]>2017-02-14 16:25:40 -0700
committerJohn Stebbins <[email protected]>2017-02-14 16:27:26 -0700
commit5429a92c51682240acbbe7b150d314d993d7d3a0 (patch)
tree51b2b4ef27d3c3a97e76cf43c6a4b15c55ffac45
parentdf5601053a8857ad8e2b59d56e82bac7f44e96fb (diff)
mux: shift timestamps by largest encoder delay
This prevents libav from adding an mp4 edit list entry that causes a properly functioning player to drop the first couple of audio frames.
-rw-r--r--libhb/common.h1
-rw-r--r--libhb/encavcodec.c2
-rw-r--r--libhb/encavcodecaudio.c7
-rw-r--r--libhb/encx264.c4
-rw-r--r--libhb/encx265.c4
-rw-r--r--libhb/hbtypes.h2
-rw-r--r--libhb/internal.h8
-rw-r--r--libhb/muxavformat.c34
8 files changed, 49 insertions, 13 deletions
diff --git a/libhb/common.h b/libhb/common.h
index aa2f2ba3e..06a22c2a8 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -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 */
diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c
index 63c325a40..76fe3e7c7 100644
--- a/libhb/encavcodec.c
+++ b/libhb/encavcodec.c
@@ -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;
}
}
}
diff --git a/libhb/encavcodecaudio.c b/libhb/encavcodecaudio.c
index e376d4436..9f07f4a79 100644
--- a/libhb/encavcodecaudio.c
+++ b/libhb/encavcodecaudio.c
@@ -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)
diff --git a/libhb/encx264.c b/libhb/encx264.c
index 1fccd7d27..1d2fd997e 100644
--- a/libhb/encx264.c
+++ b/libhb/encx264.c
@@ -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. */
diff --git a/libhb/encx265.c b/libhb/encx265.c
index 0c5d4141a..90d786983 100644
--- a/libhb/encx265.c
+++ b/libhb/encx265.c
@@ -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)
diff --git a/libhb/hbtypes.h b/libhb/hbtypes.h
index 7c7d2c679..064ba7b6d 100644
--- a/libhb/hbtypes.h
+++ b/libhb/hbtypes.h
@@ -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;
diff --git a/libhb/internal.h b/libhb/internal.h
index 1a7094429..1e79447f8 100644
--- a/libhb/internal.h
+++ b/libhb/internal.h
@@ -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
diff --git a/libhb/muxavformat.c b/libhb/muxavformat.c
index e042a9d1c..5f15b7970 100644
--- a/libhb/muxavformat.c
+++ b/libhb/muxavformat.c
@@ -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)
{