summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorSasi Inguva <isasi-at-google.com@ffmpeg.org>2017-12-18 15:31:16 -0800
committerMichael Niedermayer <michael@niedermayer.cc>2017-12-20 22:27:06 +0100
commit58a25aeb8e69532aae6ed1762fe7e0b260990010 (patch)
tree50704a36f02fb5b00ea703c4c209c77928cce029 /libavformat
parent05c1c79d3779ae53c50007c4812ec5195dc2c264 (diff)
lavf/mov.c: Guess video codec delay based on PTS while parsing MOV header.
Signed-off-by: Sasi Inguva <isasi@google.com> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/mov.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 28d60289aa..480e506370 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -3241,6 +3241,60 @@ static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, uns
return *ctts_count;
}
+#define MAX_REORDER_DELAY 16
+static void mov_estimate_video_delay(MOVContext *c, AVStream* st) {
+ MOVStreamContext *msc = st->priv_data;
+ int ind;
+ int ctts_ind = 0;
+ int ctts_sample = 0;
+ int64_t pts_buf[MAX_REORDER_DELAY + 1]; // Circular buffer to sort pts.
+ int buf_start = 0;
+ int buf_size = 0;
+ int j, r, num_swaps;
+
+ if (st->codecpar->video_delay <= 0 && msc->ctts_data &&
+ st->codecpar->codec_id == AV_CODEC_ID_H264) {
+ st->codecpar->video_delay = 0;
+ for(ind = 0; ind < st->nb_index_entries && ctts_ind < msc->ctts_count; ++ind) {
+ if (buf_size == (MAX_REORDER_DELAY + 1)) {
+ // If circular buffer is full, then move the first element forward.
+ buf_start = (buf_start + 1) % buf_size;
+ } else {
+ ++buf_size;
+ }
+
+ // Point j to the last elem of the buffer and insert the current pts there.
+ j = (buf_start + buf_size - 1) % buf_size;
+ pts_buf[j] = st->index_entries[ind].timestamp + msc->ctts_data[ctts_ind].duration;
+
+ // The timestamps that are already in the sorted buffer, and are greater than the
+ // current pts, are exactly the timestamps that need to be buffered to output PTS
+ // in correct sorted order.
+ // Hence the video delay (which is the buffer size used to sort DTS and output PTS),
+ // can be computed as the maximum no. of swaps any particular timestamp needs to
+ // go through, to keep this buffer in sorted order.
+ num_swaps = 0;
+ while (j != buf_start) {
+ r = (j - 1 + buf_size) % buf_size;
+ if (pts_buf[j] < pts_buf[r]) {
+ FFSWAP(int64_t, pts_buf[j], pts_buf[r]);
+ ++num_swaps;
+ }
+ j = r;
+ }
+ st->codecpar->video_delay = FFMAX(st->codecpar->video_delay, num_swaps);
+
+ ctts_sample++;
+ if (ctts_sample == msc->ctts_data[ctts_ind].count) {
+ ctts_ind++;
+ ctts_sample = 0;
+ }
+ }
+ av_log(c->fc, AV_LOG_DEBUG, "Setting codecpar->delay to %d for stream st: %d\n",
+ st->codecpar->video_delay, st->index);
+ }
+}
+
static void mov_current_sample_inc(MOVStreamContext *sc)
{
sc->current_sample++;
@@ -3897,6 +3951,8 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
// Fix index according to edit lists.
mov_fix_index(mov, st);
}
+
+ mov_estimate_video_delay(mov, st);
}
static int test_same_origin(const char *src, const char *ref) {