@@ -347,8 +347,6 @@ typedef struct InputStream {
AVRational framerate_guessed;
- int64_t nb_samples; /* number of samples in the last decoded audio frame before looping */
-
AVDictionary *decoder_opts;
AVRational framerate; /* framerate forced with -r */
#if FFMPEG_OPT_TOP
@@ -391,11 +389,6 @@ typedef struct InputStream {
uint64_t decode_errors;
} InputStream;
-typedef struct LastFrameDuration {
- int stream_idx;
- int64_t duration;
-} LastFrameDuration;
-
typedef struct InputFile {
const AVClass *class;
@@ -427,9 +420,9 @@ typedef struct InputFile {
int accurate_seek;
/* when looping the input file, this queue is used by decoders to report
- * the last frame duration back to the demuxer thread */
- AVThreadMessageQueue *audio_duration_queue;
- int audio_duration_queue_size;
+ * the last frame timestamp back to the demuxer thread */
+ AVThreadMessageQueue *audio_ts_queue;
+ int audio_ts_queue_size;
} InputFile;
enum forced_keyframes_const {
@@ -632,7 +632,6 @@ static int packet_decode(InputStream *ist, AVPacket *pkt, AVFrame *frame)
if (dec->codec_type == AVMEDIA_TYPE_AUDIO) {
ist->samples_decoded += frame->nb_samples;
- ist->nb_samples = frame->nb_samples;
audio_ts_process(ist, ist->decoder, frame);
} else {
@@ -724,14 +723,9 @@ static void *decoder_thread(void *arg)
/* report last frame duration to the demuxer thread */
if (ist->dec->type == AVMEDIA_TYPE_AUDIO) {
- LastFrameDuration dur;
-
- dur.stream_idx = ist->index;
- dur.duration = av_rescale_q(ist->nb_samples,
- (AVRational){ 1, ist->dec_ctx->sample_rate},
- ist->st->time_base);
-
- av_thread_message_queue_send(ifile->audio_duration_queue, &dur, 0);
+ Timestamp ts = { .ts = d->last_frame_pts + d->last_frame_duration_est,
+ .tb = d->last_frame_tb };
+ av_thread_message_queue_send(ifile->audio_ts_queue, &ts, 0);
}
avcodec_flush_buffers(ist->dec_ctx);
@@ -760,8 +754,8 @@ finish:
// make sure the demuxer does not get stuck waiting for audio durations
// that will never arrive
- if (ifile->audio_duration_queue && ist->dec->type == AVMEDIA_TYPE_AUDIO)
- av_thread_message_queue_set_err_recv(ifile->audio_duration_queue, AVERROR_EOF);
+ if (ifile->audio_ts_queue && ist->dec->type == AVMEDIA_TYPE_AUDIO)
+ av_thread_message_queue_set_err_recv(ifile->audio_ts_queue, AVERROR_EOF);
dec_thread_uninit(&dt);
@@ -74,9 +74,6 @@ typedef struct DemuxStream {
///< dts of the last packet read for this stream (in AV_TIME_BASE units)
int64_t dts;
- int64_t min_pts; /* pts with the smallest value in a current stream */
- int64_t max_pts; /* pts with the higher value in a current stream */
-
/* number of packets successfully read for this stream */
uint64_t nb_packets;
// combined size of all the packets read
@@ -99,11 +96,11 @@ typedef struct Demuxer {
/* number of times input stream should be looped */
int loop;
- /* actual duration of the longest stream in a file at the moment when
- * looping happens */
- int64_t duration;
- /* time base of the duration */
- AVRational time_base;
+ /* duration of the looped segment of the input file */
+ Timestamp duration;
+ /* pts with the smallest/largest values ever seen */
+ Timestamp min_pts;
+ Timestamp max_pts;
/* number of streams that the user was warned of */
int nb_streams_warn;
@@ -156,23 +153,6 @@ static void report_new_stream(Demuxer *d, const AVPacket *pkt)
d->nb_streams_warn = pkt->stream_index + 1;
}
-static void ifile_duration_update(Demuxer *d, DemuxStream *ds,
- int64_t last_duration)
-{
- /* the total duration of the stream, max_pts - min_pts is
- * the duration of the stream without the last frame */
- if (ds->max_pts > ds->min_pts &&
- ds->max_pts - (uint64_t)ds->min_pts < INT64_MAX - last_duration)
- last_duration += ds->max_pts - ds->min_pts;
-
- if (!d->duration ||
- av_compare_ts(d->duration, d->time_base,
- last_duration, ds->ist.st->time_base) < 0) {
- d->duration = last_duration;
- d->time_base = ds->ist.st->time_base;
- }
-}
-
static int seek_to_start(Demuxer *d)
{
InputFile *ifile = &d->f;
@@ -183,41 +163,28 @@ static int seek_to_start(Demuxer *d)
if (ret < 0)
return ret;
- if (ifile->audio_duration_queue_size) {
- /* duration is the length of the last frame in a stream
- * when audio stream is present we don't care about
- * last video frame length because it's not defined exactly */
- int got_durations = 0;
+ if (ifile->audio_ts_queue_size) {
+ int got_ts = 0;
- while (got_durations < ifile->audio_duration_queue_size) {
- DemuxStream *ds;
- LastFrameDuration dur;
- ret = av_thread_message_queue_recv(ifile->audio_duration_queue, &dur, 0);
+ while (got_ts < ifile->audio_ts_queue_size) {
+ Timestamp ts;
+ ret = av_thread_message_queue_recv(ifile->audio_ts_queue, &ts, 0);
if (ret < 0)
return ret;
- got_durations++;
+ got_ts++;
- ds = ds_from_ist(ifile->streams[dur.stream_idx]);
- ifile_duration_update(d, ds, dur.duration);
- }
- } else {
- for (int i = 0; i < ifile->nb_streams; i++) {
- int64_t duration = 0;
- InputStream *ist = ifile->streams[i];
- DemuxStream *ds = ds_from_ist(ist);
-
- if (ist->framerate.num) {
- duration = av_rescale_q(1, av_inv_q(ist->framerate), ist->st->time_base);
- } else if (ist->st->avg_frame_rate.num) {
- duration = av_rescale_q(1, av_inv_q(ist->st->avg_frame_rate), ist->st->time_base);
- } else {
- duration = 1;
- }
-
- ifile_duration_update(d, ds, duration);
+ if (d->max_pts.ts == AV_NOPTS_VALUE ||
+ av_compare_ts(d->max_pts.ts, d->max_pts.tb, ts.ts, ts.tb) < 0)
+ d->max_pts = ts;
}
}
+ if (d->max_pts.ts != AV_NOPTS_VALUE) {
+ int64_t min_pts = d->min_pts.ts == AV_NOPTS_VALUE ? 0 : d->min_pts.ts;
+ d->duration.ts = d->max_pts.ts - av_rescale_q(min_pts, d->min_pts.tb, d->max_pts.tb);
+ }
+ d->duration.tb = d->max_pts.tb;
+
if (d->loop > 0)
d->loop--;
@@ -434,11 +401,27 @@ static int ts_fixup(Demuxer *d, AVPacket *pkt)
if (pkt->dts != AV_NOPTS_VALUE)
pkt->dts *= ds->ts_scale;
- duration = av_rescale_q(d->duration, d->time_base, pkt->time_base);
+ duration = av_rescale_q(d->duration.ts, d->duration.tb, pkt->time_base);
if (pkt->pts != AV_NOPTS_VALUE) {
+ // audio decoders take precedence for estimating total file duration
+ int64_t pkt_duration = ifile->audio_ts_queue_size ? 0 : pkt->duration;
+
pkt->pts += duration;
- ds->max_pts = FFMAX(pkt->pts, ds->max_pts);
- ds->min_pts = FFMIN(pkt->pts, ds->min_pts);
+
+ // update max/min pts that will be used to compute total file duration
+ // when using -stream_loop
+ if (d->max_pts.ts == AV_NOPTS_VALUE ||
+ av_compare_ts(d->max_pts.ts, d->max_pts.tb,
+ pkt->pts + pkt_duration, pkt->time_base) < 0) {
+ d->max_pts = (Timestamp){ .ts = pkt->pts + pkt_duration,
+ .tb = pkt->time_base };
+ }
+ if (d->min_pts.ts == AV_NOPTS_VALUE ||
+ av_compare_ts(d->min_pts.ts, d->min_pts.tb,
+ pkt->pts, pkt->time_base) > 0) {
+ d->min_pts = (Timestamp){ .ts = pkt->pts,
+ .tb = pkt->time_base };
+ }
}
if (pkt->dts != AV_NOPTS_VALUE)
@@ -669,7 +652,7 @@ static void thread_stop(Demuxer *d)
pthread_join(d->thread, NULL);
av_thread_message_queue_free(&d->in_thread_queue);
- av_thread_message_queue_free(&f->audio_duration_queue);
+ av_thread_message_queue_free(&f->audio_ts_queue);
}
static int thread_start(Demuxer *d)
@@ -699,11 +682,11 @@ static int thread_start(Demuxer *d)
}
if (nb_audio_dec) {
- ret = av_thread_message_queue_alloc(&f->audio_duration_queue,
- nb_audio_dec, sizeof(LastFrameDuration));
+ ret = av_thread_message_queue_alloc(&f->audio_ts_queue,
+ nb_audio_dec, sizeof(Timestamp));
if (ret < 0)
goto fail;
- f->audio_duration_queue_size = nb_audio_dec;
+ f->audio_ts_queue_size = nb_audio_dec;
}
}
@@ -1053,13 +1036,9 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st)
ist->discard = 1;
st->discard = AVDISCARD_ALL;
- ist->nb_samples = 0;
ds->first_dts = AV_NOPTS_VALUE;
ds->next_dts = AV_NOPTS_VALUE;
- ds->min_pts = INT64_MAX;
- ds->max_pts = INT64_MIN;
-
ds->ts_scale = 1.0;
MATCH_PER_STREAM_OPT(ts_scale, dbl, ds->ts_scale, ic, st);
@@ -1591,10 +1570,12 @@ int ifile_open(const OptionsContext *o, const char *filename)
f->ts_offset = o->input_ts_offset - (copy_ts ? (start_at_zero && ic->start_time != AV_NOPTS_VALUE ? ic->start_time : 0) : timestamp);
f->accurate_seek = o->accurate_seek;
d->loop = o->loop;
- d->duration = 0;
- d->time_base = (AVRational){ 1, 1 };
d->nb_streams_warn = ic->nb_streams;
+ d->duration = (Timestamp){ .ts = 0, .tb = (AVRational){ 1, 1 } };
+ d->min_pts = (Timestamp){ .ts = AV_NOPTS_VALUE, .tb = (AVRational){ 1, 1 } };
+ d->max_pts = (Timestamp){ .ts = AV_NOPTS_VALUE, .tb = (AVRational){ 1, 1 } };
+
f->format_nots = !!(ic->iformat->flags & AVFMT_NOTIMESTAMPS);
f->readrate = o->readrate ? o->readrate : 0.0;
@@ -23,9 +23,15 @@
#include "libavutil/common.h"
#include "libavutil/frame.h"
+#include "libavutil/rational.h"
#include "libavcodec/packet.h"
+typedef struct Timestamp {
+ int64_t ts;
+ AVRational tb;
+} Timestamp;
+
/**
* Merge two return codes - return one of the error codes if at least one of
* them was negative, 0 otherwise.
@@ -44,108 +44,108 @@
1, 22488, 22488, 1024, 8192, 0x00000000
1, 23496, 23496, 1024, 8192, 0x00000000
0, 12, 12, 1, 1378560, 0x9c598000
-1, 25488, 25488, 1024, 8192, 0x00000000
+1, 25536, 25536, 1024, 8192, 0x00000000
0, 13, 13, 1, 1378560, 0xbaf121ba
-1, 26512, 26512, 1024, 8192, 0x00000000
-1, 27528, 27528, 1024, 8192, 0x00000000
+1, 26560, 26560, 1024, 8192, 0x00000000
+1, 27576, 27576, 1024, 8192, 0x00000000
0, 14, 14, 1, 1378560, 0xbaf121ba
-1, 28552, 28552, 1024, 8192, 0x00000000
-1, 29576, 29576, 1024, 8192, 0x00000000
+1, 28600, 28600, 1024, 8192, 0x00000000
+1, 29624, 29624, 1024, 8192, 0x00000000
0, 15, 15, 1, 1378560, 0x6579d31a
-1, 30600, 30600, 1024, 8192, 0x00000000
-1, 31608, 31608, 1024, 8192, 0x00000000
+1, 30648, 30648, 1024, 8192, 0x00000000
+1, 31656, 31656, 1024, 8192, 0x00000000
0, 16, 16, 1, 1378560, 0xca1deba8
-1, 32688, 32688, 1024, 8192, 0x00000000
-1, 33712, 33712, 1024, 8192, 0x00000000
+1, 32736, 32736, 1024, 8192, 0x00000000
+1, 33760, 33760, 1024, 8192, 0x00000000
0, 17, 17, 1, 1378560, 0xd4eed467
-1, 34728, 34728, 1024, 8192, 0x00000000
-1, 35736, 35736, 1024, 8192, 0x00000000
+1, 34776, 34776, 1024, 8192, 0x00000000
+1, 35784, 35784, 1024, 8192, 0x00000000
0, 18, 18, 1, 1378560, 0xd6e1d5b7
-1, 36760, 36760, 1024, 8192, 0x00000000
-1, 37784, 37784, 1024, 8192, 0x00000000
+1, 36808, 36808, 1024, 8192, 0x00000000
+1, 37832, 37832, 1024, 8192, 0x00000000
0, 19, 19, 1, 1378560, 0x0b574d39
-1, 38808, 38808, 1024, 8192, 0x00000000
-1, 39816, 39816, 1024, 8192, 0x00000000
+1, 38856, 38856, 1024, 8192, 0x00000000
+1, 39864, 39864, 1024, 8192, 0x00000000
0, 20, 20, 1, 1378560, 0x1bdd4d61
-1, 40840, 40840, 1024, 8192, 0x00000000
-1, 41864, 41864, 1024, 8192, 0x00000000
+1, 40888, 40888, 1024, 8192, 0x00000000
+1, 41912, 41912, 1024, 8192, 0x00000000
0, 21, 21, 1, 1378560, 0x3b28f549
-1, 42888, 42888, 1024, 8192, 0x00000000
-1, 43896, 43896, 1024, 8192, 0x00000000
+1, 42936, 42936, 1024, 8192, 0x00000000
+1, 43944, 43944, 1024, 8192, 0x00000000
0, 22, 22, 1, 1378560, 0x45b2f57b
-1, 44920, 44920, 1024, 8192, 0x00000000
-1, 45944, 45944, 1024, 8192, 0x00000000
+1, 44968, 44968, 1024, 8192, 0x00000000
+1, 45992, 45992, 1024, 8192, 0x00000000
0, 23, 23, 1, 1378560, 0x8955570e
-1, 46968, 46968, 1024, 8192, 0x00000000
-1, 47976, 47976, 1024, 8192, 0x00000000
+1, 47016, 47016, 1024, 8192, 0x00000000
+1, 48024, 48024, 1024, 8192, 0x00000000
0, 24, 24, 1, 1378560, 0x9c598000
-1, 49968, 49968, 1024, 8192, 0x00000000
0, 25, 25, 1, 1378560, 0xbaf121ba
-1, 50992, 50992, 1024, 8192, 0x00000000
-1, 52008, 52008, 1024, 8192, 0x00000000
+1, 50064, 50064, 1024, 8192, 0x00000000
+1, 51088, 51088, 1024, 8192, 0x00000000
0, 26, 26, 1, 1378560, 0xbaf121ba
-1, 53032, 53032, 1024, 8192, 0x00000000
+1, 52104, 52104, 1024, 8192, 0x00000000
+1, 53128, 53128, 1024, 8192, 0x00000000
0, 27, 27, 1, 1378560, 0x6579d31a
-1, 54056, 54056, 1024, 8192, 0x00000000
-1, 55080, 55080, 1024, 8192, 0x00000000
+1, 54152, 54152, 1024, 8192, 0x00000000
+1, 55176, 55176, 1024, 8192, 0x00000000
0, 28, 28, 1, 1378560, 0xca1deba8
-1, 56088, 56088, 1024, 8192, 0x00000000
-1, 57168, 57168, 1024, 8192, 0x00000000
+1, 56184, 56184, 1024, 8192, 0x00000000
+1, 57264, 57264, 1024, 8192, 0x00000000
0, 29, 29, 1, 1378560, 0xd4eed467
-1, 58192, 58192, 1024, 8192, 0x00000000
-1, 59208, 59208, 1024, 8192, 0x00000000
+1, 58288, 58288, 1024, 8192, 0x00000000
+1, 59304, 59304, 1024, 8192, 0x00000000
0, 30, 30, 1, 1378560, 0xd6e1d5b7
-1, 60216, 60216, 1024, 8192, 0x00000000
-1, 61240, 61240, 1024, 8192, 0x00000000
+1, 60312, 60312, 1024, 8192, 0x00000000
+1, 61336, 61336, 1024, 8192, 0x00000000
0, 31, 31, 1, 1378560, 0x0b574d39
-1, 62264, 62264, 1024, 8192, 0x00000000
-1, 63288, 63288, 1024, 8192, 0x00000000
+1, 62360, 62360, 1024, 8192, 0x00000000
+1, 63384, 63384, 1024, 8192, 0x00000000
0, 32, 32, 1, 1378560, 0x1bdd4d61
-1, 64296, 64296, 1024, 8192, 0x00000000
-1, 65320, 65320, 1024, 8192, 0x00000000
+1, 64392, 64392, 1024, 8192, 0x00000000
+1, 65416, 65416, 1024, 8192, 0x00000000
0, 33, 33, 1, 1378560, 0x3b28f549
-1, 66344, 66344, 1024, 8192, 0x00000000
-1, 67368, 67368, 1024, 8192, 0x00000000
+1, 66440, 66440, 1024, 8192, 0x00000000
+1, 67464, 67464, 1024, 8192, 0x00000000
0, 34, 34, 1, 1378560, 0x45b2f57b
-1, 68376, 68376, 1024, 8192, 0x00000000
-1, 69400, 69400, 1024, 8192, 0x00000000
+1, 68472, 68472, 1024, 8192, 0x00000000
+1, 69496, 69496, 1024, 8192, 0x00000000
0, 35, 35, 1, 1378560, 0x8955570e
-1, 70424, 70424, 1024, 8192, 0x00000000
-1, 71448, 71448, 1024, 8192, 0x00000000
-0, 36, 36, 1, 1378560, 0x9c598000
-1, 72456, 72456, 1024, 8192, 0x00000000
-0, 37, 37, 1, 1378560, 0xbaf121ba
-1, 74448, 74448, 1024, 8192, 0x00000000
-1, 75472, 75472, 1024, 8192, 0x00000000
+1, 70520, 70520, 1024, 8192, 0x00000000
+1, 71544, 71544, 1024, 8192, 0x00000000
+1, 72552, 72552, 1024, 8192, 0x00000000
+0, 37, 37, 1, 1378560, 0x9c598000
+1, 74592, 74592, 1024, 8192, 0x00000000
+1, 75616, 75616, 1024, 8192, 0x00000000
0, 38, 38, 1, 1378560, 0xbaf121ba
-1, 76488, 76488, 1024, 8192, 0x00000000
-1, 77512, 77512, 1024, 8192, 0x00000000
-0, 39, 39, 1, 1378560, 0x6579d31a
-1, 78536, 78536, 1024, 8192, 0x00000000
-1, 79560, 79560, 1024, 8192, 0x00000000
-0, 40, 40, 1, 1378560, 0xca1deba8
-1, 80568, 80568, 1024, 8192, 0x00000000
-1, 81648, 81648, 1024, 8192, 0x00000000
-0, 41, 41, 1, 1378560, 0xd4eed467
-1, 82672, 82672, 1024, 8192, 0x00000000
-1, 83688, 83688, 1024, 8192, 0x00000000
-0, 42, 42, 1, 1378560, 0xd6e1d5b7
-1, 84696, 84696, 1024, 8192, 0x00000000
-1, 85720, 85720, 1024, 8192, 0x00000000
-0, 43, 43, 1, 1378560, 0x0b574d39
-1, 86744, 86744, 1024, 8192, 0x00000000
-1, 87768, 87768, 1024, 8192, 0x00000000
-0, 44, 44, 1, 1378560, 0x1bdd4d61
-1, 88776, 88776, 1024, 8192, 0x00000000
-1, 89800, 89800, 1024, 8192, 0x00000000
-0, 45, 45, 1, 1378560, 0x3b28f549
-1, 90824, 90824, 1024, 8192, 0x00000000
-1, 91848, 91848, 1024, 8192, 0x00000000
-0, 46, 46, 1, 1378560, 0x45b2f57b
-1, 92856, 92856, 1024, 8192, 0x00000000
-1, 93880, 93880, 1024, 8192, 0x00000000
-0, 47, 47, 1, 1378560, 0x8955570e
-1, 94904, 94904, 1024, 8192, 0x00000000
-1, 95928, 95928, 1024, 8192, 0x00000000
-1, 96936, 96936, 1024, 8192, 0x00000000
+1, 76632, 76632, 1024, 8192, 0x00000000
+1, 77656, 77656, 1024, 8192, 0x00000000
+0, 39, 39, 1, 1378560, 0xbaf121ba
+1, 78680, 78680, 1024, 8192, 0x00000000
+1, 79704, 79704, 1024, 8192, 0x00000000
+0, 40, 40, 1, 1378560, 0x6579d31a
+1, 80712, 80712, 1024, 8192, 0x00000000
+1, 81792, 81792, 1024, 8192, 0x00000000
+0, 41, 41, 1, 1378560, 0xca1deba8
+1, 82816, 82816, 1024, 8192, 0x00000000
+1, 83832, 83832, 1024, 8192, 0x00000000
+0, 42, 42, 1, 1378560, 0xd4eed467
+1, 84840, 84840, 1024, 8192, 0x00000000
+1, 85864, 85864, 1024, 8192, 0x00000000
+0, 43, 43, 1, 1378560, 0xd6e1d5b7
+1, 86888, 86888, 1024, 8192, 0x00000000
+1, 87912, 87912, 1024, 8192, 0x00000000
+0, 44, 44, 1, 1378560, 0x0b574d39
+1, 88920, 88920, 1024, 8192, 0x00000000
+1, 89944, 89944, 1024, 8192, 0x00000000
+0, 45, 45, 1, 1378560, 0x1bdd4d61
+1, 90968, 90968, 1024, 8192, 0x00000000
+1, 91992, 91992, 1024, 8192, 0x00000000
+0, 46, 46, 1, 1378560, 0x3b28f549
+1, 93000, 93000, 1024, 8192, 0x00000000
+1, 94024, 94024, 1024, 8192, 0x00000000
+0, 47, 47, 1, 1378560, 0x45b2f57b
+1, 95048, 95048, 1024, 8192, 0x00000000
+1, 96072, 96072, 1024, 8192, 0x00000000
+0, 48, 48, 1, 1378560, 0x8955570e
+1, 97080, 97080, 1024, 8192, 0x00000000
0, 49, 49, 1, 1378560, 0x9c598000