aboutsummaryrefslogtreecommitdiffstats
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
parent05c1c79d3779ae53c50007c4812ec5195dc2c264 (diff)
downloadffmpeg-58a25aeb8e69532aae6ed1762fe7e0b260990010.tar.gz
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>
-rw-r--r--libavformat/mov.c56
-rw-r--r--tests/fate/mov.mak7
-rw-r--r--tests/ref/fate/mov-guess-delay-13
-rw-r--r--tests/ref/fate/mov-guess-delay-23
-rw-r--r--tests/ref/fate/mov-guess-delay-33
5 files changed, 72 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) {
diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak
index 19b01304fb..907dfa0b69 100644
--- a/tests/fate/mov.mak
+++ b/tests/fate/mov.mak
@@ -13,6 +13,9 @@ FATE_MOV = fate-mov-3elist \
fate-mov-elst-ends-betn-b-and-i \
fate-mov-frag-overlap \
fate-mov-bbi-elst-starts-b \
+ fate-mov-guess-delay-1 \
+ fate-mov-guess-delay-2 \
+ fate-mov-guess-delay-3 \
FATE_MOV_FFPROBE = fate-mov-aac-2048-priming \
fate-mov-zombie \
@@ -82,3 +85,7 @@ fate-mov-spherical-mono: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries str
fate-mov-gpmf-remux: CMD = md5 -i $(TARGET_SAMPLES)/mov/fake-gp-media-with-real-gpmf.mp4 -map 0 -c copy -fflags +bitexact -f mp4
fate-mov-gpmf-remux: CMP = oneline
fate-mov-gpmf-remux: REF = 8f48e435ee1f6b7e173ea756141eabf3
+
+fate-mov-guess-delay-1: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=has_b_frames -select_streams v $(TARGET_SAMPLES)/h264/h264_3bf_nopyramid_nobsrestriction.mp4
+fate-mov-guess-delay-2: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=has_b_frames -select_streams v $(TARGET_SAMPLES)/h264/h264_3bf_pyramid_nobsrestriction.mp4
+fate-mov-guess-delay-3: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=has_b_frames -select_streams v $(TARGET_SAMPLES)/h264/h264_4bf_pyramid_nobsrestriction.mp4
diff --git a/tests/ref/fate/mov-guess-delay-1 b/tests/ref/fate/mov-guess-delay-1
new file mode 100644
index 0000000000..96cb67be0c
--- /dev/null
+++ b/tests/ref/fate/mov-guess-delay-1
@@ -0,0 +1,3 @@
+[STREAM]
+has_b_frames=1
+[/STREAM]
diff --git a/tests/ref/fate/mov-guess-delay-2 b/tests/ref/fate/mov-guess-delay-2
new file mode 100644
index 0000000000..248de1c3ea
--- /dev/null
+++ b/tests/ref/fate/mov-guess-delay-2
@@ -0,0 +1,3 @@
+[STREAM]
+has_b_frames=2
+[/STREAM]
diff --git a/tests/ref/fate/mov-guess-delay-3 b/tests/ref/fate/mov-guess-delay-3
new file mode 100644
index 0000000000..248de1c3ea
--- /dev/null
+++ b/tests/ref/fate/mov-guess-delay-3
@@ -0,0 +1,3 @@
+[STREAM]
+has_b_frames=2
+[/STREAM]