From: toots via ffmpeg-devel <ffmpeg-devel@ffmpeg.org> To: ffmpeg-devel@ffmpeg.org Cc: toots <code@ffmpeg.org> Subject: [FFmpeg-devel] [PATCH] Cleanup packet-level BOS/EOS logic. (PR #20640) Date: Wed, 01 Oct 2025 23:02:42 -0000 Message-ID: <175935976334.69.17346150839866119057@bf249f23a2c8> (raw) PR #20640 opened by toots URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20640 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20640.patch >From 3a9233d70c02a336a59d85bae753eadc09d86a53 Mon Sep 17 00:00:00 2001 From: Romain Beauxis <romain.beauxis@gmail.com> Date: Wed, 1 Oct 2025 18:01:13 -0500 Subject: [PATCH] Cleanup packet-level BOS/EOS logic. --- libavformat/oggdec.c | 6 ++-- libavformat/oggdec.h | 4 +-- libavformat/oggparsecelt.c | 2 +- libavformat/oggparsedirac.c | 4 +-- libavformat/oggparseflac.c | 6 ++-- libavformat/oggparseogm.c | 6 ++-- libavformat/oggparseopus.c | 36 +++------------------ libavformat/oggparseskeleton.c | 4 +-- libavformat/oggparsespeex.c | 6 ++-- libavformat/oggparsetheora.c | 6 ++-- libavformat/oggparsevorbis.c | 58 ++-------------------------------- libavformat/oggparsevp8.c | 6 ++-- 12 files changed, 33 insertions(+), 111 deletions(-) diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 9f3a92a5ea..2bd2ec1b65 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -567,7 +567,8 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, os->incomplete = 0; if (os->header) { - if ((ret = os->codec->header(s, idx)) < 0) { + int is_first = os->flags & OGG_FLAG_BOS && !os->nb_header; + if ((ret = os->codec->header(s, idx, is_first)) < 0) { av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret)); return ret; } @@ -605,7 +606,8 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, ret = 0; if (os->codec && os->codec->packet) { - if ((ret = os->codec->packet(s, idx)) < 0) { + int is_last_packet = os->flags & OGG_FLAG_EOS && os->page_end; + if ((ret = os->codec->packet(s, idx, is_last_packet)) < 0) { av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret)); return ret; } diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h index b051b651e3..76d1c0f0eb 100644 --- a/libavformat/oggdec.h +++ b/libavformat/oggdec.h @@ -37,7 +37,7 @@ struct ogg_codec { * 0 if the packet was not a header (was a data packet) * -1 if an error occurred or for unsupported stream */ - int (*header)(AVFormatContext *, int); + int (*header)(AVFormatContext *, int, int); /** * Attempt to process a packet as a data packet * @return < 0 (AVERROR) code or -1 on error @@ -45,7 +45,7 @@ struct ogg_codec { * == 1 if the packet was a header from a chained bitstream. * This will cause the packet to be skipped in calling code (ogg_packet() */ - int (*packet)(AVFormatContext *, int); + int (*packet)(AVFormatContext *, int, int); /** * Translate a granule into a timestamp. * Will set dts if non-null and known. diff --git a/libavformat/oggparsecelt.c b/libavformat/oggparsecelt.c index 626e1ab27d..683e075bf7 100644 --- a/libavformat/oggparsecelt.c +++ b/libavformat/oggparsecelt.c @@ -31,7 +31,7 @@ struct oggcelt_private { int extra_headers_left; }; -static int celt_header(AVFormatContext *s, int idx) +static int celt_header(AVFormatContext *s, int idx, int is_first) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; diff --git a/libavformat/oggparsedirac.c b/libavformat/oggparsedirac.c index c5bd43a757..62ded6e592 100644 --- a/libavformat/oggparsedirac.c +++ b/libavformat/oggparsedirac.c @@ -26,7 +26,7 @@ #include "internal.h" #include "oggdec.h" -static int dirac_header(AVFormatContext *s, int idx) +static int dirac_header(AVFormatContext *s, int idx, int is_first) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -84,7 +84,7 @@ static uint64_t dirac_gptopts(AVFormatContext *s, int idx, uint64_t granule, return pts; } -static int old_dirac_header(AVFormatContext *s, int idx) +static int old_dirac_header(AVFormatContext *s, int idx, int is_first) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c index e81e4021a1..ec68ebb6b8 100644 --- a/libavformat/oggparseflac.c +++ b/libavformat/oggparseflac.c @@ -31,7 +31,7 @@ #define OGG_FLAC_MAGIC_SIZE sizeof(OGG_FLAC_MAGIC)-1 static int -flac_header (AVFormatContext * s, int idx) +flac_header (AVFormatContext * s, int idx, int is_first) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -81,7 +81,7 @@ flac_header (AVFormatContext * s, int idx) } static int -flac_packet (AVFormatContext * s, int idx) +flac_packet (AVFormatContext * s, int idx, int is_last) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -109,7 +109,7 @@ flac_packet (AVFormatContext * s, int idx) } static int -old_flac_header (AVFormatContext * s, int idx) +old_flac_header (AVFormatContext * s, int idx, int is_first) { struct ogg *ogg = s->priv_data; AVStream *st = s->streams[idx]; diff --git a/libavformat/oggparseogm.c b/libavformat/oggparseogm.c index 1e794745ab..f66db82301 100644 --- a/libavformat/oggparseogm.c +++ b/libavformat/oggparseogm.c @@ -34,7 +34,7 @@ #include "riff.h" static int -ogm_header(AVFormatContext *s, int idx) +ogm_header(AVFormatContext *s, int idx, int is_first) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -128,7 +128,7 @@ ogm_header(AVFormatContext *s, int idx) } static int -ogm_dshow_header(AVFormatContext *s, int idx) +ogm_dshow_header(AVFormatContext *s, int idx, int is_first) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -169,7 +169,7 @@ ogm_dshow_header(AVFormatContext *s, int idx) } static int -ogm_packet(AVFormatContext *s, int idx) +ogm_packet(AVFormatContext *s, int idx, int is_last) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; diff --git a/libavformat/oggparseopus.c b/libavformat/oggparseopus.c index ae4ff22c53..af1f3e4ba6 100644 --- a/libavformat/oggparseopus.c +++ b/libavformat/oggparseopus.c @@ -81,7 +81,7 @@ static int parse_opus_header(AVFormatContext *avf, AVStream *st, struct ogg_stre return 1; } -static int opus_header(AVFormatContext *avf, int idx) +static int opus_header(AVFormatContext *avf, int idx, int is_first) { struct ogg *ogg = avf->priv_data; struct ogg_stream *os = &ogg->streams[idx]; @@ -95,7 +95,7 @@ static int opus_header(AVFormatContext *avf, int idx) return AVERROR(ENOMEM); } - if (os->flags & OGG_FLAG_BOS) + if (is_first) return parse_opus_header(avf, st, os, priv, packet, os->psize); if (priv->need_comments) { @@ -129,7 +129,7 @@ static int opus_duration(uint8_t *src, int size) return frame_size * nb_frames; } -static int opus_packet(AVFormatContext *avf, int idx) +static int opus_packet(AVFormatContext *avf, int idx, int is_last) { struct ogg *ogg = avf->priv_data; struct ogg_stream *os = &ogg->streams[idx]; @@ -163,34 +163,6 @@ static int opus_packet(AVFormatContext *avf, int idx) return 1; } - if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) { - int seg, d; - int duration; - uint8_t *last_pkt = os->buf + os->pstart; - uint8_t *next_pkt = last_pkt; - - duration = 0; - seg = os->segp; - d = opus_duration(last_pkt, os->psize); - if (d < 0) { - os->pflags |= AV_PKT_FLAG_CORRUPT; - return 0; - } - duration += d; - last_pkt = next_pkt = next_pkt + os->psize; - for (; seg < os->nsegs; seg++) { - next_pkt += os->segments[seg]; - if (os->segments[seg] < 255 && next_pkt != last_pkt) { - int d = opus_duration(last_pkt, next_pkt - last_pkt); - if (d > 0) - duration += d; - last_pkt = next_pkt; - } - } - os->lastpts = - os->lastdts = os->granule - duration; - } - if ((ret = opus_duration(packet, os->psize)) < 0) return ret; @@ -202,7 +174,7 @@ static int opus_packet(AVFormatContext *avf, int idx) } priv->cur_dts += os->pduration; - if ((os->flags & OGG_FLAG_EOS)) { + if (is_last) { int64_t skip = priv->cur_dts - os->granule + priv->pre_skip; skip = FFMIN(skip, os->pduration); if (skip > 0) { diff --git a/libavformat/oggparseskeleton.c b/libavformat/oggparseskeleton.c index 2016b16c95..1c54285aaa 100644 --- a/libavformat/oggparseskeleton.c +++ b/libavformat/oggparseskeleton.c @@ -23,7 +23,7 @@ #include "internal.h" #include "oggdec.h" -static int skeleton_header(AVFormatContext *s, int idx) +static int skeleton_header(AVFormatContext *s, int idx, int flags) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -36,7 +36,7 @@ static int skeleton_header(AVFormatContext *s, int idx) st->codecpar->codec_type = AVMEDIA_TYPE_DATA; - if ((os->flags & OGG_FLAG_EOS) && os->psize == 0) + if ((flags & OGG_FLAG_EOS) && os->psize == 0) return 1; if (os->psize < 8) diff --git a/libavformat/oggparsespeex.c b/libavformat/oggparsespeex.c index 0a4b32de15..d3eed6e728 100644 --- a/libavformat/oggparsespeex.c +++ b/libavformat/oggparsespeex.c @@ -36,7 +36,7 @@ struct speex_params { int seq; }; -static int speex_header(AVFormatContext *s, int idx) { +static int speex_header(AVFormatContext *s, int idx, int flags) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; struct speex_params *spxp = os->private; @@ -111,14 +111,14 @@ static int ogg_page_packets(struct ogg_stream *os) return packets; } -static int speex_packet(AVFormatContext *s, int idx) +static int speex_packet(AVFormatContext *s, int idx, int flags) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; struct speex_params *spxp = os->private; int packet_size = spxp->packet_size; - if (os->flags & OGG_FLAG_EOS && os->lastpts != AV_NOPTS_VALUE && + if (flags & OGG_FLAG_EOS && os->lastpts != AV_NOPTS_VALUE && os->granule > 0) { /* first packet of final page. we have to calculate the final packet duration here because it is the only place we know the next-to-last diff --git a/libavformat/oggparsetheora.c b/libavformat/oggparsetheora.c index 6cdd962759..43f5ef9fb3 100644 --- a/libavformat/oggparsetheora.c +++ b/libavformat/oggparsetheora.c @@ -35,7 +35,7 @@ typedef struct TheoraParams { unsigned version; } TheoraParams; -static int theora_header(AVFormatContext *s, int idx) +static int theora_header(AVFormatContext *s, int idx, int flags) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -168,7 +168,7 @@ static uint64_t theora_gptopts(AVFormatContext *ctx, int idx, uint64_t gp, return iframe + pframe; } -static int theora_packet(AVFormatContext *s, int idx) +static int theora_packet(AVFormatContext *s, int idx, int flags) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -179,7 +179,7 @@ static int theora_packet(AVFormatContext *s, int idx) the total duration to the page granule to find the encoder delay and set the first timestamp */ - if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) { + if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(flags & OGG_FLAG_EOS)) { int seg; int64_t pts; diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c index 7c4f7624f8..58b9f98669 100644 --- a/libavformat/oggparsevorbis.c +++ b/libavformat/oggparsevorbis.c @@ -368,7 +368,7 @@ static int vorbis_update_metadata(AVFormatContext *s, int idx) os->psize - 8); } -static int vorbis_header(AVFormatContext *s, int idx) +static int vorbis_header(AVFormatContext *s, int idx, int is_first) { struct ogg *ogg = s->priv_data; AVStream *st = s->streams[idx]; @@ -447,7 +447,7 @@ static int vorbis_header(AVFormatContext *s, int idx) return 1; } -static int vorbis_packet(AVFormatContext *s, int idx) +static int vorbis_packet(AVFormatContext *s, int idx, int is_last) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -460,58 +460,6 @@ static int vorbis_packet(AVFormatContext *s, int idx) if (!priv->vp) return AVERROR_INVALIDDATA; - /* first packet handling - * here we parse the duration of each packet in the first page and compare - * the total duration to the page granule to find the encoder delay and - * set the first timestamp */ - if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS) && (int64_t)os->granule>=0) { - int seg, d; - uint8_t *last_pkt = os->buf + os->pstart; - uint8_t *next_pkt = last_pkt; - - av_vorbis_parse_reset(priv->vp); - duration = 0; - seg = os->segp; - d = av_vorbis_parse_frame_flags(priv->vp, last_pkt, 1, &flags); - if (d < 0) { - os->pflags |= AV_PKT_FLAG_CORRUPT; - return 0; - } else if (flags & VORBIS_FLAG_COMMENT) { - vorbis_update_metadata(s, idx); - flags = 0; - } - duration += d; - last_pkt = next_pkt = next_pkt + os->psize; - for (; seg < os->nsegs; seg++) { - if (os->segments[seg] < 255) { - int d = av_vorbis_parse_frame_flags(priv->vp, last_pkt, 1, &flags); - if (d < 0) { - duration = os->granule; - break; - } else if (flags & VORBIS_FLAG_COMMENT) { - vorbis_update_metadata(s, idx); - flags = 0; - } - duration += d; - last_pkt = next_pkt + os->segments[seg]; - } - next_pkt += os->segments[seg]; - } - os->lastpts = - os->lastdts = os->granule - duration; - - if (!os->granule && duration) //hack to deal with broken files (Ticket3710) - os->lastpts = os->lastdts = AV_NOPTS_VALUE; - - if (s->streams[idx]->start_time == AV_NOPTS_VALUE) { - s->streams[idx]->start_time = FFMAX(os->lastpts, 0); - if (s->streams[idx]->duration != AV_NOPTS_VALUE) - s->streams[idx]->duration -= s->streams[idx]->start_time; - } - priv->final_pts = AV_NOPTS_VALUE; - av_vorbis_parse_reset(priv->vp); - } - /* parse packet duration */ if (os->psize > 0) { duration = av_vorbis_parse_frame_flags(priv->vp, os->buf + os->pstart, 1, &flags); @@ -569,7 +517,7 @@ static int vorbis_packet(AVFormatContext *s, int idx) * here we save the pts of the first packet in the final page, sum up all * packet durations in the final page except for the last one, and compare * to the page granule to find the duration of the final packet */ - if (os->flags & OGG_FLAG_EOS) { + if (is_last) { if (os->lastpts != AV_NOPTS_VALUE) { priv->final_pts = os->lastpts; priv->final_duration = 0; diff --git a/libavformat/oggparsevp8.c b/libavformat/oggparsevp8.c index 676b3a0f8e..679ef64d76 100644 --- a/libavformat/oggparsevp8.c +++ b/libavformat/oggparsevp8.c @@ -27,7 +27,7 @@ #define VP8_HEADER_SIZE 26 -static int vp8_header(AVFormatContext *s, int idx) +static int vp8_header(AVFormatContext *s, int idx, int flags) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; @@ -98,14 +98,14 @@ static uint64_t vp8_gptopts(AVFormatContext *s, int idx, return pts; } -static int vp8_packet(AVFormatContext *s, int idx) +static int vp8_packet(AVFormatContext *s, int idx, int flags) { struct ogg *ogg = s->priv_data; struct ogg_stream *os = ogg->streams + idx; uint8_t *p = os->buf + os->pstart; if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && - !(os->flags & OGG_FLAG_EOS)) { + !(flags & OGG_FLAG_EOS)) { int seg; int duration; uint8_t *last_pkt = p; -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
reply other threads:[~2025-10-01 23:03 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=175935976334.69.17346150839866119057@bf249f23a2c8 \ --to=ffmpeg-devel@ffmpeg.org \ --cc=code@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror http://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ http://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git