From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id BDA2446147 for ; Mon, 8 May 2023 09:18:46 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 53EA968C175; Mon, 8 May 2023 12:18:09 +0300 (EEST) Received: from mail0.khirnov.net (red.khirnov.net [176.97.15.12]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 64D2868C11E for ; Mon, 8 May 2023 12:18:00 +0300 (EEST) Received: from localhost (localhost [IPv6:::1]) by mail0.khirnov.net (Postfix) with ESMTP id 2EE9B2404F5 for ; Mon, 8 May 2023 11:18:00 +0200 (CEST) Received: from mail0.khirnov.net ([IPv6:::1]) by localhost (mail0.khirnov.net [IPv6:::1]) (amavisd-new, port 10024) with ESMTP id feJ6SY0PQqWz for ; Mon, 8 May 2023 11:17:58 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:2a00:c500:561:201::7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256 client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "libav.khirnov.net", Issuer "smtp.khirnov.net SMTP CA" (verified OK)) by mail0.khirnov.net (Postfix) with ESMTPS id 3806E240591 for ; Mon, 8 May 2023 11:17:57 +0200 (CEST) Received: from libav.khirnov.net (libav.khirnov.net [IPv6:::1]) by libav.khirnov.net (Postfix) with ESMTP id 0822D3A1267 for ; Mon, 8 May 2023 11:17:57 +0200 (CEST) From: Anton Khirnov To: ffmpeg-devel@ffmpeg.org Date: Mon, 8 May 2023 11:17:22 +0200 Message-Id: <20230508091738.20813-6-anton@khirnov.net> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230508091738.20813-1-anton@khirnov.net> References: <20230508091738.20813-1-anton@khirnov.net> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 06/22] fftools/ffmpeg: move post-demux packet processing to ffmpeg_demux X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: 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. --- fftools/ffmpeg.c | 188 ----------------------------- fftools/ffmpeg.h | 6 - fftools/ffmpeg_demux.c | 266 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 233 insertions(+), 227 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<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..9082de6a80 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<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,13 +429,74 @@ 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; + +fail: + av_packet_free(&pkt); return 0; } +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) { char name[16]; @@ -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; } -- 2.39.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".