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