summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2023-04-27 14:11:34 +0200
committerAnton Khirnov <anton@khirnov.net>2023-05-15 11:03:15 +0200
commit2b99c6bfd57d00e7f06cda09d60db9dbefaa117e (patch)
tree03c1567b72c55abf0529f30c3d36e9839870065d
parent09c686788e3be1f343ddf64be291e6df6946323f (diff)
downloadffmpeg-2b99c6bfd57d00e7f06cda09d60db9dbefaa117e.tar.gz
fftools/ffmpeg: move post-demux packet processing to ffmpeg_demux
That is a more appropriate place for this code and will allow hiding more of InputStream. The value of repeat_pict extracted from libavformat internal parser no longer needs to be trasmitted outside of the demuxing thread. Move readrate handling to the demuxer thread. This has to be done in the same commit, since it reads InputStream.dts,nb_packets, which are now set in the demuxer thread.
-rw-r--r--fftools/ffmpeg.c188
-rw-r--r--fftools/ffmpeg.h6
-rw-r--r--fftools/ffmpeg_demux.c268
3 files changed, 234 insertions, 228 deletions
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 2a39d767cd..ee92587798 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -1772,154 +1772,6 @@ static void decode_flush(InputFile *ifile)
}
}
-static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist,
- AVPacket *pkt)
-{
- const int fmt_is_discont = ifile->ctx->iformat->flags & AVFMT_TS_DISCONT;
- int disable_discontinuity_correction = copy_ts;
- int64_t pkt_dts = av_rescale_q_rnd(pkt->dts, pkt->time_base, AV_TIME_BASE_Q,
- AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
-
- if (copy_ts && ist->next_dts != AV_NOPTS_VALUE &&
- fmt_is_discont && ist->st->pts_wrap_bits < 60) {
- int64_t wrap_dts = av_rescale_q_rnd(pkt->dts + (1LL<<ist->st->pts_wrap_bits),
- pkt->time_base, AV_TIME_BASE_Q,
- AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
- if (FFABS(wrap_dts - ist->next_dts) < FFABS(pkt_dts - ist->next_dts)/10)
- disable_discontinuity_correction = 0;
- }
-
- if (ist->next_dts != AV_NOPTS_VALUE && !disable_discontinuity_correction) {
- int64_t delta = pkt_dts - ist->next_dts;
- if (fmt_is_discont) {
- if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE ||
- pkt_dts + AV_TIME_BASE/10 < ist->dts) {
- ifile->ts_offset_discont -= delta;
- av_log(NULL, AV_LOG_WARNING,
- "timestamp discontinuity for stream #%d:%d "
- "(id=%d, type=%s): %"PRId64", new offset= %"PRId64"\n",
- ist->file_index, ist->st->index, ist->st->id,
- av_get_media_type_string(ist->par->codec_type),
- delta, ifile->ts_offset_discont);
- pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base);
- if (pkt->pts != AV_NOPTS_VALUE)
- pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base);
- }
- } else {
- if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) {
- av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt->dts, ist->next_dts, pkt->stream_index);
- pkt->dts = AV_NOPTS_VALUE;
- }
- if (pkt->pts != AV_NOPTS_VALUE){
- int64_t pkt_pts = av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q);
- delta = pkt_pts - ist->next_dts;
- if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) {
- av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt->pts, ist->next_dts, pkt->stream_index);
- pkt->pts = AV_NOPTS_VALUE;
- }
- }
- }
- } else if (ist->next_dts == AV_NOPTS_VALUE && !copy_ts &&
- fmt_is_discont && ifile->last_ts != AV_NOPTS_VALUE) {
- int64_t delta = pkt_dts - ifile->last_ts;
- if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE) {
- ifile->ts_offset_discont -= delta;
- av_log(NULL, AV_LOG_DEBUG,
- "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n",
- delta, ifile->ts_offset_discont);
- pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base);
- if (pkt->pts != AV_NOPTS_VALUE)
- pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base);
- }
- }
-
- ifile->last_ts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q);
-}
-
-static void ts_discontinuity_process(InputFile *ifile, InputStream *ist,
- AVPacket *pkt)
-{
- int64_t offset = av_rescale_q(ifile->ts_offset_discont, AV_TIME_BASE_Q,
- pkt->time_base);
-
- // apply previously-detected timestamp-discontinuity offset
- // (to all streams, not just audio/video)
- if (pkt->dts != AV_NOPTS_VALUE)
- pkt->dts += offset;
- if (pkt->pts != AV_NOPTS_VALUE)
- pkt->pts += offset;
-
- // detect timestamp discontinuities for audio/video
- if ((ist->par->codec_type == AVMEDIA_TYPE_VIDEO ||
- ist->par->codec_type == AVMEDIA_TYPE_AUDIO) &&
- pkt->dts != AV_NOPTS_VALUE)
- ts_discontinuity_detect(ifile, ist, pkt);
-}
-
-static void ist_dts_update(InputStream *ist, AVPacket *pkt)
-{
- const AVCodecParameters *par = ist->par;
-
- if (!ist->saw_first_ts) {
- ist->first_dts =
- ist->dts = ist->st->avg_frame_rate.num ? - ist->par->video_delay * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
- if (pkt->pts != AV_NOPTS_VALUE) {
- ist->first_dts =
- ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q);
- }
- ist->saw_first_ts = 1;
- }
-
- if (ist->next_dts == AV_NOPTS_VALUE)
- ist->next_dts = ist->dts;
-
- if (pkt->dts != AV_NOPTS_VALUE)
- ist->next_dts = ist->dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q);
-
- ist->dts = ist->next_dts;
- switch (par->codec_type) {
- case AVMEDIA_TYPE_AUDIO:
- av_assert1(pkt->duration >= 0);
- if (par->sample_rate) {
- ist->next_dts += ((int64_t)AV_TIME_BASE * par->frame_size) /
- par->sample_rate;
- } else {
- ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q);
- }
- break;
- case AVMEDIA_TYPE_VIDEO:
- if (ist->framerate.num) {
- // TODO: Remove work-around for c99-to-c89 issue 7
- AVRational time_base_q = AV_TIME_BASE_Q;
- int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate));
- ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q);
- } else if (pkt->duration) {
- ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q);
- } else if (ist->par->framerate.num != 0) {
- int fields = (ist->codec_desc &&
- (ist->codec_desc->props & AV_CODEC_PROP_FIELDS)) ?
- ist->last_pkt_repeat_pict + 1 : 2;
- AVRational field_rate = av_mul_q(ist->par->framerate,
- (AVRational){ 2, 1 });
-
- ist->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q);
- }
- break;
- }
-
- av_assert0(!pkt->opaque_ref);
- if (ist->streamcopy_needed) {
- DemuxPktData *pd;
-
- pkt->opaque_ref = av_buffer_allocz(sizeof(*pd));
- if (!pkt->opaque_ref)
- report_and_exit(AVERROR(ENOMEM));
- pd = (DemuxPktData*)pkt->opaque_ref->data;
-
- pd->dts_est = ist->dts;
- }
-}
-
/*
* Return
* - 0 -- one packet was read and processed
@@ -1979,46 +1831,6 @@ static int process_input(int file_index)
ist = ifile->streams[pkt->stream_index];
- ist->data_size += pkt->size;
- ist->nb_packets++;
-
- /* add the stream-global side data to the first packet */
- if (ist->nb_packets == 1) {
- for (i = 0; i < ist->st->nb_side_data; i++) {
- AVPacketSideData *src_sd = &ist->st->side_data[i];
- uint8_t *dst_data;
-
- if (src_sd->type == AV_PKT_DATA_DISPLAYMATRIX)
- continue;
-
- if (av_packet_get_side_data(pkt, src_sd->type, NULL))
- continue;
-
- dst_data = av_packet_new_side_data(pkt, src_sd->type, src_sd->size);
- if (!dst_data)
- report_and_exit(AVERROR(ENOMEM));
-
- memcpy(dst_data, src_sd->data, src_sd->size);
- }
- }
-
- // detect and try to correct for timestamp discontinuities
- ts_discontinuity_process(ifile, ist, pkt);
-
- // update estimated/predicted dts
- ist_dts_update(ist, pkt);
-
- if (debug_ts) {
- av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s off:%s off_time:%s\n",
- ifile->index, pkt->stream_index,
- av_get_media_type_string(ist->par->codec_type),
- av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &pkt->time_base),
- av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &pkt->time_base),
- av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &pkt->time_base),
- av_ts2str(input_files[ist->file_index]->ts_offset),
- av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q));
- }
-
sub2video_heartbeat(ist, pkt->pts);
process_input_packet(ist, pkt, 0);
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 8a5d5b13c8..1900f3deb6 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -380,12 +380,6 @@ typedef struct InputStream {
int wrap_correction_done;
- // the value of AVCodecParserContext.repeat_pict from the AVStream parser
- // for the last packet returned from ifile_get_packet()
- // -1 if unknown
- // FIXME: this is a hack, the avstream parser should not be used
- int last_pkt_repeat_pict;
-
int64_t filter_in_rescale_delta_last;
// when forcing constant input framerate through -r,
diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c
index eda838f84c..2d0410808b 100644
--- a/fftools/ffmpeg_demux.c
+++ b/fftools/ffmpeg_demux.c
@@ -92,9 +92,6 @@ typedef struct Demuxer {
typedef struct DemuxMsg {
AVPacket *pkt;
int looping;
-
- // repeat_pict from the demuxer-internal parser
- int repeat_pict;
} DemuxMsg;
static DemuxStream *ds_from_ist(InputStream *ist)
@@ -188,13 +185,167 @@ static int seek_to_start(Demuxer *d)
return ret;
}
-static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict)
+static void ts_discontinuity_detect(InputFile *ifile, InputStream *ist,
+ AVPacket *pkt)
+{
+ const int fmt_is_discont = ifile->ctx->iformat->flags & AVFMT_TS_DISCONT;
+ int disable_discontinuity_correction = copy_ts;
+ int64_t pkt_dts = av_rescale_q_rnd(pkt->dts, pkt->time_base, AV_TIME_BASE_Q,
+ AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
+
+ if (copy_ts && ist->next_dts != AV_NOPTS_VALUE &&
+ fmt_is_discont && ist->st->pts_wrap_bits < 60) {
+ int64_t wrap_dts = av_rescale_q_rnd(pkt->dts + (1LL<<ist->st->pts_wrap_bits),
+ pkt->time_base, AV_TIME_BASE_Q,
+ AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX);
+ if (FFABS(wrap_dts - ist->next_dts) < FFABS(pkt_dts - ist->next_dts)/10)
+ disable_discontinuity_correction = 0;
+ }
+
+ if (ist->next_dts != AV_NOPTS_VALUE && !disable_discontinuity_correction) {
+ int64_t delta = pkt_dts - ist->next_dts;
+ if (fmt_is_discont) {
+ if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE ||
+ pkt_dts + AV_TIME_BASE/10 < ist->dts) {
+ ifile->ts_offset_discont -= delta;
+ av_log(NULL, AV_LOG_WARNING,
+ "timestamp discontinuity for stream #%d:%d "
+ "(id=%d, type=%s): %"PRId64", new offset= %"PRId64"\n",
+ ist->file_index, ist->st->index, ist->st->id,
+ av_get_media_type_string(ist->par->codec_type),
+ delta, ifile->ts_offset_discont);
+ pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base);
+ if (pkt->pts != AV_NOPTS_VALUE)
+ pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base);
+ }
+ } else {
+ if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) {
+ av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid dropping\n", pkt->dts, ist->next_dts, pkt->stream_index);
+ pkt->dts = AV_NOPTS_VALUE;
+ }
+ if (pkt->pts != AV_NOPTS_VALUE){
+ int64_t pkt_pts = av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q);
+ delta = pkt_pts - ist->next_dts;
+ if (FFABS(delta) > 1LL * dts_error_threshold * AV_TIME_BASE) {
+ av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid dropping st:%d\n", pkt->pts, ist->next_dts, pkt->stream_index);
+ pkt->pts = AV_NOPTS_VALUE;
+ }
+ }
+ }
+ } else if (ist->next_dts == AV_NOPTS_VALUE && !copy_ts &&
+ fmt_is_discont && ifile->last_ts != AV_NOPTS_VALUE) {
+ int64_t delta = pkt_dts - ifile->last_ts;
+ if (FFABS(delta) > 1LL * dts_delta_threshold * AV_TIME_BASE) {
+ ifile->ts_offset_discont -= delta;
+ av_log(NULL, AV_LOG_DEBUG,
+ "Inter stream timestamp discontinuity %"PRId64", new offset= %"PRId64"\n",
+ delta, ifile->ts_offset_discont);
+ pkt->dts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base);
+ if (pkt->pts != AV_NOPTS_VALUE)
+ pkt->pts -= av_rescale_q(delta, AV_TIME_BASE_Q, pkt->time_base);
+ }
+ }
+
+ ifile->last_ts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q);
+}
+
+static void ts_discontinuity_process(InputFile *ifile, InputStream *ist,
+ AVPacket *pkt)
+{
+ int64_t offset = av_rescale_q(ifile->ts_offset_discont, AV_TIME_BASE_Q,
+ pkt->time_base);
+
+ // apply previously-detected timestamp-discontinuity offset
+ // (to all streams, not just audio/video)
+ if (pkt->dts != AV_NOPTS_VALUE)
+ pkt->dts += offset;
+ if (pkt->pts != AV_NOPTS_VALUE)
+ pkt->pts += offset;
+
+ // detect timestamp discontinuities for audio/video
+ if ((ist->par->codec_type == AVMEDIA_TYPE_VIDEO ||
+ ist->par->codec_type == AVMEDIA_TYPE_AUDIO) &&
+ pkt->dts != AV_NOPTS_VALUE)
+ ts_discontinuity_detect(ifile, ist, pkt);
+}
+
+static int ist_dts_update(InputStream *ist, AVPacket *pkt)
+{
+ const AVCodecParameters *par = ist->par;
+
+ if (!ist->saw_first_ts) {
+ ist->first_dts =
+ ist->dts = ist->st->avg_frame_rate.num ? - ist->par->video_delay * AV_TIME_BASE / av_q2d(ist->st->avg_frame_rate) : 0;
+ if (pkt->pts != AV_NOPTS_VALUE) {
+ ist->first_dts =
+ ist->dts += av_rescale_q(pkt->pts, pkt->time_base, AV_TIME_BASE_Q);
+ }
+ ist->saw_first_ts = 1;
+ }
+
+ if (ist->next_dts == AV_NOPTS_VALUE)
+ ist->next_dts = ist->dts;
+
+ if (pkt->dts != AV_NOPTS_VALUE)
+ ist->next_dts = ist->dts = av_rescale_q(pkt->dts, pkt->time_base, AV_TIME_BASE_Q);
+
+ ist->dts = ist->next_dts;
+ switch (par->codec_type) {
+ case AVMEDIA_TYPE_AUDIO:
+ av_assert1(pkt->duration >= 0);
+ if (par->sample_rate) {
+ ist->next_dts += ((int64_t)AV_TIME_BASE * par->frame_size) /
+ par->sample_rate;
+ } else {
+ ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q);
+ }
+ break;
+ case AVMEDIA_TYPE_VIDEO:
+ if (ist->framerate.num) {
+ // TODO: Remove work-around for c99-to-c89 issue 7
+ AVRational time_base_q = AV_TIME_BASE_Q;
+ int64_t next_dts = av_rescale_q(ist->next_dts, time_base_q, av_inv_q(ist->framerate));
+ ist->next_dts = av_rescale_q(next_dts + 1, av_inv_q(ist->framerate), time_base_q);
+ } else if (pkt->duration) {
+ ist->next_dts += av_rescale_q(pkt->duration, pkt->time_base, AV_TIME_BASE_Q);
+ } else if (ist->par->framerate.num != 0) {
+ AVRational field_rate = av_mul_q(ist->par->framerate,
+ (AVRational){ 2, 1 });
+ int fields = 2;
+
+ if (ist->codec_desc &&
+ (ist->codec_desc->props & AV_CODEC_PROP_FIELDS) &&
+ av_stream_get_parser(ist->st))
+ fields = 1 + av_stream_get_parser(ist->st)->repeat_pict;
+
+ ist->next_dts += av_rescale_q(fields, av_inv_q(field_rate), AV_TIME_BASE_Q);
+ }
+ break;
+ }
+
+ av_assert0(!pkt->opaque_ref);
+ if (ist->streamcopy_needed) {
+ DemuxPktData *pd;
+
+ pkt->opaque_ref = av_buffer_allocz(sizeof(*pd));
+ if (!pkt->opaque_ref)
+ return AVERROR(ENOMEM);
+ pd = (DemuxPktData*)pkt->opaque_ref->data;
+
+ pd->dts_est = ist->dts;
+ }
+
+ return 0;
+}
+
+static int ts_fixup(Demuxer *d, AVPacket *pkt)
{
InputFile *ifile = &d->f;
InputStream *ist = ifile->streams[pkt->stream_index];
DemuxStream *ds = ds_from_ist(ist);
const int64_t start_time = ifile->start_time_effective;
int64_t duration;
+ int ret;
pkt->time_base = ist->st->time_base;
@@ -249,19 +400,27 @@ static void ts_fixup(Demuxer *d, AVPacket *pkt, int *repeat_pict)
if (pkt->dts != AV_NOPTS_VALUE)
pkt->dts += duration;
- *repeat_pict = -1;
- if (ist->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
- av_stream_get_parser(ist->st))
- *repeat_pict = av_stream_get_parser(ist->st)->repeat_pict;
-
SHOW_TS_DEBUG("demuxer+tsfixup");
+
+ // detect and try to correct for timestamp discontinuities
+ ts_discontinuity_process(ifile, ist, pkt);
+
+ // update estimated/predicted dts
+ ret = ist_dts_update(ist, pkt);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
// process an input packet into a message to send to the consumer thread
// src is always cleared by this function
static int input_packet_process(Demuxer *d, DemuxMsg *msg, AVPacket *src)
{
+ InputFile *f = &d->f;
+ InputStream *ist = f->streams[src->stream_index];
AVPacket *pkt;
+ int ret = 0;
pkt = av_packet_alloc();
if (!pkt) {
@@ -270,11 +429,72 @@ static int input_packet_process(Demuxer *d, DemuxMsg *msg, AVPacket *src)
}
av_packet_move_ref(pkt, src);
- ts_fixup(d, pkt, &msg->repeat_pict);
+ ret = ts_fixup(d, pkt);
+ if (ret < 0)
+ goto fail;
+
+ ist->data_size += pkt->size;
+ ist->nb_packets++;
+
+ /* add the stream-global side data to the first packet */
+ if (ist->nb_packets == 1) {
+ for (int i = 0; i < ist->st->nb_side_data; i++) {
+ AVPacketSideData *src_sd = &ist->st->side_data[i];
+ uint8_t *dst_data;
+
+ if (src_sd->type == AV_PKT_DATA_DISPLAYMATRIX)
+ continue;
+
+ if (av_packet_get_side_data(pkt, src_sd->type, NULL))
+ continue;
+
+ dst_data = av_packet_new_side_data(pkt, src_sd->type, src_sd->size);
+ if (!dst_data) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ memcpy(dst_data, src_sd->data, src_sd->size);
+ }
+ }
+
+ if (debug_ts) {
+ av_log(NULL, AV_LOG_INFO, "demuxer+ffmpeg -> ist_index:%d:%d type:%s pkt_pts:%s pkt_pts_time:%s pkt_dts:%s pkt_dts_time:%s duration:%s duration_time:%s off:%s off_time:%s\n",
+ f->index, pkt->stream_index,
+ av_get_media_type_string(ist->par->codec_type),
+ av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &pkt->time_base),
+ av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &pkt->time_base),
+ av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &pkt->time_base),
+ av_ts2str(input_files[ist->file_index]->ts_offset),
+ av_ts2timestr(input_files[ist->file_index]->ts_offset, &AV_TIME_BASE_Q));
+ }
msg->pkt = pkt;
+ pkt = NULL;
- return 0;
+fail:
+ av_packet_free(&pkt);
+
+ return ret;
+}
+
+static void readrate_sleep(Demuxer *d)
+{
+ InputFile *f = &d->f;
+ int64_t file_start = copy_ts * (
+ (f->start_time_effective != AV_NOPTS_VALUE ? f->start_time_effective * !start_at_zero : 0) +
+ (f->start_time != AV_NOPTS_VALUE ? f->start_time : 0)
+ );
+ int64_t burst_until = AV_TIME_BASE * d->readrate_initial_burst;
+ for (int i = 0; i < f->nb_streams; i++) {
+ InputStream *ist = f->streams[i];
+ int64_t stream_ts_offset, pts, now;
+ stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start);
+ pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE);
+ now = (av_gettime_relative() - ist->start) * f->readrate + stream_ts_offset;
+ if (pts - burst_until > now)
+ av_usleep(pts - burst_until - now);
+ }
}
static void thread_set_name(InputFile *f)
@@ -360,6 +580,9 @@ static void *input_thread(void *arg)
if (ret < 0)
break;
+ if (f->readrate)
+ readrate_sleep(d);
+
ret = av_thread_message_queue_send(d->in_thread_queue, &msg, flags);
if (flags && ret == AVERROR(EAGAIN)) {
flags = 0;
@@ -456,7 +679,6 @@ fail:
int ifile_get_packet(InputFile *f, AVPacket **pkt)
{
Demuxer *d = demuxer_from_ifile(f);
- InputStream *ist;
DemuxMsg msg;
int ret;
@@ -466,25 +688,6 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt)
return ret;
}
- if (f->readrate) {
- int i;
- int64_t file_start = copy_ts * (
- (f->start_time_effective != AV_NOPTS_VALUE ? f->start_time_effective * !start_at_zero : 0) +
- (f->start_time != AV_NOPTS_VALUE ? f->start_time : 0)
- );
- int64_t burst_until = AV_TIME_BASE * d->readrate_initial_burst;
- for (i = 0; i < f->nb_streams; i++) {
- InputStream *ist = f->streams[i];
- int64_t stream_ts_offset, pts, now;
- if (!ist->nb_packets) continue;
- stream_ts_offset = FFMAX(ist->first_dts != AV_NOPTS_VALUE ? ist->first_dts : 0, file_start);
- pts = av_rescale(ist->dts, 1000000, AV_TIME_BASE);
- now = (av_gettime_relative() - ist->start) * f->readrate + stream_ts_offset;
- if (pts - burst_until > now)
- return AVERROR(EAGAIN);
- }
- }
-
ret = av_thread_message_queue_recv(d->in_thread_queue, &msg,
d->non_blocking ?
AV_THREAD_MESSAGE_NONBLOCK : 0);
@@ -493,9 +696,6 @@ int ifile_get_packet(InputFile *f, AVPacket **pkt)
if (msg.looping)
return 1;
- ist = f->streams[msg.pkt->stream_index];
- ist->last_pkt_repeat_pict = msg.repeat_pict;
-
*pkt = msg.pkt;
return 0;
}