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>
This commit is contained in:
Sasi Inguva 2017-12-18 15:31:16 -08:00 committed by Michael Niedermayer
parent 05c1c79d37
commit 58a25aeb8e
5 changed files with 72 additions and 0 deletions

View File

@ -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) {

View File

@ -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

View File

@ -0,0 +1,3 @@
[STREAM]
has_b_frames=1
[/STREAM]

View File

@ -0,0 +1,3 @@
[STREAM]
has_b_frames=2
[/STREAM]

View File

@ -0,0 +1,3 @@
[STREAM]
has_b_frames=2
[/STREAM]