* [FFmpeg-devel] [PATCH v2 1/2] Parse ogg/flac header again after processing a new chained ogg bitstream. @ 2025-01-29 14:40 Romain Beauxis 2025-01-29 14:40 ` [FFmpeg-devel] [PATCH v1 2/2] Add stream dump test with test for ogg/flac Romain Beauxis 2025-01-29 16:40 ` [FFmpeg-devel] [PATCH v2 1/2] Parse ogg/flac header again after processing a new chained ogg bitstream Marvin Scholz 0 siblings, 2 replies; 6+ messages in thread From: Romain Beauxis @ 2025-01-29 14:40 UTC (permalink / raw) To: ffmpeg-devel; +Cc: Romain Beauxis This patch makes sure that ogg/flac headers are parsed again when encountering a new logic stream inside a chained ogg bistream[1]. This patches makes it possible to retrieve metadata in chained ogg/flac bitstreams. It is particularly important because ogg/flac is one of the only (if not the only one) lossless container supported over HTTP/icecast. The patch has been tested with various ogg/flac encoders and appears to work fine with ffmpeg. Changes since last version: * Make sure to clear the stream's metadata before parsing again. 1: https://xiph.org/ogg/doc/oggstream.html --- libavformat/oggdec.c | 7 +++++-- libavformat/oggparseflac.c | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 5339fdd32c..d986e19817 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -239,8 +239,11 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic, os->start_trimming = 0; os->end_trimming = 0; - /* Chained files have extradata as a new packet */ - if (codec == &ff_opus_codec) + /* Parse opus and flac header on new chained bitstream. + * For opus, header contains required extradata as new packet + * For both formats, this makes it possible to read chained metadata. */ + if (codec == &ff_opus_codec || + codec == &ff_flac_codec) os->header = -1; return i; diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c index f25ed9cc15..932907fa1a 100644 --- a/libavformat/oggparseflac.c +++ b/libavformat/oggparseflac.c @@ -72,6 +72,8 @@ flac_header (AVFormatContext * s, int idx) avpriv_set_pts_info(st, 64, 1, samplerate); } else if (mdt == FLAC_METADATA_TYPE_VORBIS_COMMENT) { + /* New metadata packet; release old data. */ + av_dict_free(&st->metadata); ff_vorbis_stream_comment(s, st, os->buf + os->pstart + 4, os->psize - 4); } -- 2.39.5 (Apple Git-154) _______________________________________________ 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". ^ permalink raw reply [flat|nested] 6+ messages in thread
* [FFmpeg-devel] [PATCH v1 2/2] Add stream dump test with test for ogg/flac. 2025-01-29 14:40 [FFmpeg-devel] [PATCH v2 1/2] Parse ogg/flac header again after processing a new chained ogg bitstream Romain Beauxis @ 2025-01-29 14:40 ` Romain Beauxis 2025-01-29 16:05 ` Romain Beauxis 2025-01-29 16:40 ` [FFmpeg-devel] [PATCH v2 1/2] Parse ogg/flac header again after processing a new chained ogg bitstream Marvin Scholz 1 sibling, 1 reply; 6+ messages in thread From: Romain Beauxis @ 2025-01-29 14:40 UTC (permalink / raw) To: ffmpeg-devel; +Cc: Romain Beauxis This patch adds a fate test for ogg/flac chained streams. First, a new api-dump-stream-meta-test utility is introduced then it is used to dump the metadata of a ogg/flac chained sample. Sample is available here: https://www.dropbox.com/scl/fo/fxt2edwkyj2mjc9qubku5/AICHxJyxMMAK8MIJqWLcvk4?rlkey=mlt12lsu741ejukz0p5qtn9rq&dl=0 Sample is very short so the dump output is: Stream ID: 0, PTS: 0, DTS: 0, metadata: encoder=Lavc61.19.100 flac:title=First Stream Stream ID: 0, PTS: 4608, DTS: 4608, metadata: encoder=Lavc61.19.100 flac:title=First Stream Stream ID: 0, PTS: 0, DTS: 0, metadata: encoder=Lavc61.19.100 flac:title=Second Stream Stream ID: 0, PTS: 4608, DTS: 4608, metadata: encoder=Lavc61.19.100 flac:title=Second Stream --- tests/Makefile | 2 + tests/api/Makefile | 2 +- tests/api/api-dump-stream-meta-test.c | 88 +++++++++++++++++++++++++++ tests/fate/api.mak | 5 ++ tests/fate/ogg-flac.mak | 11 ++++ 5 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 tests/api/api-dump-stream-meta-test.c create mode 100644 tests/fate/ogg-flac.mak diff --git a/tests/Makefile b/tests/Makefile index f9f5fc07f3..66e5189e6d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -219,6 +219,7 @@ include $(SRC_PATH)/tests/fate/mpeg4.mak include $(SRC_PATH)/tests/fate/mpegps.mak include $(SRC_PATH)/tests/fate/mpegts.mak include $(SRC_PATH)/tests/fate/mxf.mak +include $(SRC_PATH)/tests/fate/ogg-flac.mak include $(SRC_PATH)/tests/fate/oma.mak include $(SRC_PATH)/tests/fate/opus.mak include $(SRC_PATH)/tests/fate/pcm.mak @@ -277,6 +278,7 @@ $(FATE_FFPROBE) $(FATE_FFMPEG_FFPROBE) $(FATE_SAMPLES_FFPROBE) $(FATE_SAMPLES_FF $(FATE_SAMPLES_FASTSTART): tools/qt-faststart$(EXESUF) $(FATE_SAMPLES_DUMP_DATA) $(FATE_SAMPLES_DUMP_DATA-yes): tools/venc_data_dump$(EXESUF) $(FATE_SAMPLES_SCALE_SLICE): tools/scale_slice_test$(EXESUF) +$(FATE_SAMPLES_DUMP_STREAM_META): tests/api/api-dump-stream-meta-test$(EXESUF) ifdef SAMPLES FATE += $(FATE_EXTERN) diff --git a/tests/api/Makefile b/tests/api/Makefile index c96e636756..a2cb06a729 100644 --- a/tests/api/Makefile +++ b/tests/api/Makefile @@ -1,7 +1,7 @@ APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264 APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice -APITESTPROGS-yes += api-seek +APITESTPROGS-yes += api-seek api-dump-stream-meta APITESTPROGS-$(call DEMDEC, H263, H263) += api-band APITESTPROGS-$(HAVE_THREADS) += api-threadmessage APITESTPROGS += $(APITESTPROGS-yes) diff --git a/tests/api/api-dump-stream-meta-test.c b/tests/api/api-dump-stream-meta-test.c new file mode 100644 index 0000000000..d750e0aecb --- /dev/null +++ b/tests/api/api-dump-stream-meta-test.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2025 Romain Beauxis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * Dump stream metadata + */ + +#include "libavformat/avformat.h" + +static int dump_stream_meta(const char *input_filename) +{ + AVPacket *pkt = NULL; + AVFormatContext *fmt_ctx = NULL; + int result; + char *metadata; + + result = avformat_open_input(&fmt_ctx, input_filename, NULL, NULL); + if (result < 0) { + av_log(NULL, AV_LOG_ERROR, "Can't open file\n"); + return result; + } + + result = avformat_find_stream_info(fmt_ctx, NULL); + if (result < 0) { + av_log(NULL, AV_LOG_ERROR, "Can't get stream info\n"); + goto end; + } + + pkt = av_packet_alloc(); + if (!pkt) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate packet\n"); + result = AVERROR(ENOMEM); + goto end; + } + + for (;;) { + result = av_read_frame(fmt_ctx, pkt); + if (result) + goto end; + + result = av_dict_get_string( + fmt_ctx->streams[pkt->stream_index]->metadata, &metadata, '=', ':'); + if (result < 0) + goto end; + + printf("Stream ID: %d, PTS: %lld, DTS: %lld, metadata: %s\n", + pkt->stream_index, pkt->pts, pkt->dts, metadata); + av_free(metadata); + av_packet_unref(pkt); + } + +end: + av_packet_free(&pkt); + avformat_close_input(&fmt_ctx); + return result; +} + +int main(int argc, char **argv) +{ + if (argc < 2) { + av_log(NULL, AV_LOG_ERROR, "Incorrect input\n"); + return 1; + } + + if (dump_stream_meta(argv[1]) != AVERROR_EOF) + return 1; + + return 0; +} diff --git a/tests/fate/api.mak b/tests/fate/api.mak index d2868e57ac..a9872a5589 100644 --- a/tests/fate/api.mak +++ b/tests/fate/api.mak @@ -1,3 +1,8 @@ +FATE_API_LIBAVFORMAT-$(call ENCDEC, FLAC, FLAC) += api-dump-stream-meta +fate-api-ogg-flac-meta: $(APITESTSDIR)/api-dump-stream-meta-test$(EXESUF) +fate-api-ogg-flac-meta: CMD = run $(APITESTSDIR)/api-flac-test$(EXESUF) +fate-api-ogg-flac-meta: CMP = null + FATE_API_LIBAVCODEC-$(call ENCDEC, FLAC, FLAC) += fate-api-flac fate-api-flac: $(APITESTSDIR)/api-flac-test$(EXESUF) fate-api-flac: CMD = run $(APITESTSDIR)/api-flac-test$(EXESUF) diff --git a/tests/fate/ogg-flac.mak b/tests/fate/ogg-flac.mak new file mode 100644 index 0000000000..22e2030534 --- /dev/null +++ b/tests/fate/ogg-flac.mak @@ -0,0 +1,11 @@ +FATE_OGG_FLAC += fate-ogg-flac-chained-meta +fate-ogg-flac-chained-meta: REF = $(SAMPLES)/ogg-flac/chained-meta.txt +fate-ogg-flac-chained-meta: CMD = $(APITESTSDIR)/api-dump-stream-meta-test$(EXESUF) $(TARGET_SAMPLES)/ogg-flac/chained-meta.ogg + +FATE_OGG_FLAC-$(call DEMDEC, OGG, FLAC) += $(FATE_OGG_FLAC) + +FATE_SAMPLES_DUMP_STREAM_META += $(FATE_OGG_FLAC-yes) + +FATE_EXTERN += $(FATE_OGG_FLAC-yes) + +fate-ogg-flac: $(FATE_OGG_FLAC-yes) -- 2.39.5 (Apple Git-154) _______________________________________________ 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". ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [FFmpeg-devel] [PATCH v1 2/2] Add stream dump test with test for ogg/flac. 2025-01-29 14:40 ` [FFmpeg-devel] [PATCH v1 2/2] Add stream dump test with test for ogg/flac Romain Beauxis @ 2025-01-29 16:05 ` Romain Beauxis 0 siblings, 0 replies; 6+ messages in thread From: Romain Beauxis @ 2025-01-29 16:05 UTC (permalink / raw) To: ffmpeg-devel Le mer. 29 janv. 2025 à 15:43, Romain Beauxis <romain.beauxis@gmail.com> a écrit : > > This patch adds a fate test for ogg/flac chained streams. > > First, a new api-dump-stream-meta-test utility is introduced then it is > used to dump the metadata of a ogg/flac chained sample. > > Sample is available here: https://www.dropbox.com/scl/fo/fxt2edwkyj2mjc9qubku5/AICHxJyxMMAK8MIJqWLcvk4?rlkey=mlt12lsu741ejukz0p5qtn9rq&dl=0 > > Sample is very short so the dump output is: > > Stream ID: 0, PTS: 0, DTS: 0, metadata: encoder=Lavc61.19.100 flac:title=First Stream > Stream ID: 0, PTS: 4608, DTS: 4608, metadata: encoder=Lavc61.19.100 flac:title=First Stream > Stream ID: 0, PTS: 0, DTS: 0, metadata: encoder=Lavc61.19.100 flac:title=Second Stream > Stream ID: 0, PTS: 4608, DTS: 4608, metadata: encoder=Lavc61.19.100 flac:title=Second Stream I forgot to add the output of the stream meta dump prior to the changes: Stream ID: 0, PTS: 0, DTS: 0, metadata: encoder=Lavc61.19.100 flac:title=First Stream Stream ID: 0, PTS: 4608, DTS: 4608, metadata: encoder=Lavc61.19.100 flac:title=First Stream Stream ID: 0, PTS: 0, DTS: 0, metadata: encoder=Lavc61.19.100 flac:title=First Stream Stream ID: 0, PTS: 0, DTS: 0, metadata: encoder=Lavc61.19.100 flac:title=First Stream Stream ID: 0, PTS: 0, DTS: 0, metadata: encoder=Lavc61.19.100 flac:title=First Stream Stream ID: 0, PTS: 4608, DTS: 4608, metadata: encoder=Lavc61.19.100 flac:title=First Stream The extra two packets are the header packets. The PTS/DTS discontinuity is already present, the decoder seems to have no problem with them. I'd be happy to do a follow-up to tentatively adjust PTS/DTS if that'd make sense/is possible. Le mer. 29 janv. 2025 à 15:43, Romain Beauxis <romain.beauxis@gmail.com> a écrit : > This patch adds a fate test for ogg/flac chained streams. > > First, a new api-dump-stream-meta-test utility is introduced then it is > used to dump the metadata of a ogg/flac chained sample. > > Sample is available here: > https://www.dropbox.com/scl/fo/fxt2edwkyj2mjc9qubku5/AICHxJyxMMAK8MIJqWLcvk4?rlkey=mlt12lsu741ejukz0p5qtn9rq&dl=0 > > Sample is very short so the dump output is: > > Stream ID: 0, PTS: 0, DTS: 0, metadata: encoder=Lavc61.19.100 > flac:title=First Stream > Stream ID: 0, PTS: 4608, DTS: 4608, metadata: encoder=Lavc61.19.100 > flac:title=First Stream > Stream ID: 0, PTS: 0, DTS: 0, metadata: encoder=Lavc61.19.100 > flac:title=Second Stream > Stream ID: 0, PTS: 4608, DTS: 4608, metadata: encoder=Lavc61.19.100 > flac:title=Second Stream > > --- > tests/Makefile | 2 + > tests/api/Makefile | 2 +- > tests/api/api-dump-stream-meta-test.c | 88 +++++++++++++++++++++++++++ > tests/fate/api.mak | 5 ++ > tests/fate/ogg-flac.mak | 11 ++++ > 5 files changed, 107 insertions(+), 1 deletion(-) > create mode 100644 tests/api/api-dump-stream-meta-test.c > create mode 100644 tests/fate/ogg-flac.mak > > diff --git a/tests/Makefile b/tests/Makefile > index f9f5fc07f3..66e5189e6d 100644 > --- a/tests/Makefile > +++ b/tests/Makefile > @@ -219,6 +219,7 @@ include $(SRC_PATH)/tests/fate/mpeg4.mak > include $(SRC_PATH)/tests/fate/mpegps.mak > include $(SRC_PATH)/tests/fate/mpegts.mak > include $(SRC_PATH)/tests/fate/mxf.mak > +include $(SRC_PATH)/tests/fate/ogg-flac.mak > include $(SRC_PATH)/tests/fate/oma.mak > include $(SRC_PATH)/tests/fate/opus.mak > include $(SRC_PATH)/tests/fate/pcm.mak > @@ -277,6 +278,7 @@ $(FATE_FFPROBE) $(FATE_FFMPEG_FFPROBE) > $(FATE_SAMPLES_FFPROBE) $(FATE_SAMPLES_FF > $(FATE_SAMPLES_FASTSTART): tools/qt-faststart$(EXESUF) > $(FATE_SAMPLES_DUMP_DATA) $(FATE_SAMPLES_DUMP_DATA-yes): > tools/venc_data_dump$(EXESUF) > $(FATE_SAMPLES_SCALE_SLICE): tools/scale_slice_test$(EXESUF) > +$(FATE_SAMPLES_DUMP_STREAM_META): > tests/api/api-dump-stream-meta-test$(EXESUF) > > ifdef SAMPLES > FATE += $(FATE_EXTERN) > diff --git a/tests/api/Makefile b/tests/api/Makefile > index c96e636756..a2cb06a729 100644 > --- a/tests/api/Makefile > +++ b/tests/api/Makefile > @@ -1,7 +1,7 @@ > APITESTPROGS-$(call ENCDEC, FLAC, FLAC) += api-flac > APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264 > APITESTPROGS-$(call DEMDEC, H264, H264) += api-h264-slice > -APITESTPROGS-yes += api-seek > +APITESTPROGS-yes += api-seek api-dump-stream-meta > APITESTPROGS-$(call DEMDEC, H263, H263) += api-band > APITESTPROGS-$(HAVE_THREADS) += api-threadmessage > APITESTPROGS += $(APITESTPROGS-yes) > diff --git a/tests/api/api-dump-stream-meta-test.c > b/tests/api/api-dump-stream-meta-test.c > new file mode 100644 > index 0000000000..d750e0aecb > --- /dev/null > +++ b/tests/api/api-dump-stream-meta-test.c > @@ -0,0 +1,88 @@ > +/* > + * Copyright (c) 2025 Romain Beauxis > + * > + * Permission is hereby granted, free of charge, to any person obtaining > a copy > + * of this software and associated documentation files (the "Software"), > to deal > + * in the Software without restriction, including without limitation the > rights > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or > sell > + * copies of the Software, and to permit persons to whom the Software is > + * furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be > included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, > EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF > MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR > OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, > ARISING FROM, > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS > IN > + * THE SOFTWARE. > + */ > + > +/** > + * Dump stream metadata > + */ > + > +#include "libavformat/avformat.h" > + > +static int dump_stream_meta(const char *input_filename) > +{ > + AVPacket *pkt = NULL; > + AVFormatContext *fmt_ctx = NULL; > + int result; > + char *metadata; > + > + result = avformat_open_input(&fmt_ctx, input_filename, NULL, NULL); > + if (result < 0) { > + av_log(NULL, AV_LOG_ERROR, "Can't open file\n"); > + return result; > + } > + > + result = avformat_find_stream_info(fmt_ctx, NULL); > + if (result < 0) { > + av_log(NULL, AV_LOG_ERROR, "Can't get stream info\n"); > + goto end; > + } > + > + pkt = av_packet_alloc(); > + if (!pkt) { > + av_log(NULL, AV_LOG_ERROR, "Cannot allocate packet\n"); > + result = AVERROR(ENOMEM); > + goto end; > + } > + > + for (;;) { > + result = av_read_frame(fmt_ctx, pkt); > + if (result) > + goto end; > + > + result = av_dict_get_string( > + fmt_ctx->streams[pkt->stream_index]->metadata, &metadata, > '=', ':'); > + if (result < 0) > + goto end; > + > + printf("Stream ID: %d, PTS: %lld, DTS: %lld, metadata: %s\n", > + pkt->stream_index, pkt->pts, pkt->dts, metadata); > + av_free(metadata); > + av_packet_unref(pkt); > + } > + > +end: > + av_packet_free(&pkt); > + avformat_close_input(&fmt_ctx); > + return result; > +} > + > +int main(int argc, char **argv) > +{ > + if (argc < 2) { > + av_log(NULL, AV_LOG_ERROR, "Incorrect input\n"); > + return 1; > + } > + > + if (dump_stream_meta(argv[1]) != AVERROR_EOF) > + return 1; > + > + return 0; > +} > diff --git a/tests/fate/api.mak b/tests/fate/api.mak > index d2868e57ac..a9872a5589 100644 > --- a/tests/fate/api.mak > +++ b/tests/fate/api.mak > @@ -1,3 +1,8 @@ > +FATE_API_LIBAVFORMAT-$(call ENCDEC, FLAC, FLAC) += api-dump-stream-meta > +fate-api-ogg-flac-meta: $(APITESTSDIR)/api-dump-stream-meta-test$(EXESUF) > +fate-api-ogg-flac-meta: CMD = run $(APITESTSDIR)/api-flac-test$(EXESUF) > +fate-api-ogg-flac-meta: CMP = null > + > FATE_API_LIBAVCODEC-$(call ENCDEC, FLAC, FLAC) += fate-api-flac > fate-api-flac: $(APITESTSDIR)/api-flac-test$(EXESUF) > fate-api-flac: CMD = run $(APITESTSDIR)/api-flac-test$(EXESUF) > diff --git a/tests/fate/ogg-flac.mak b/tests/fate/ogg-flac.mak > new file mode 100644 > index 0000000000..22e2030534 > --- /dev/null > +++ b/tests/fate/ogg-flac.mak > @@ -0,0 +1,11 @@ > +FATE_OGG_FLAC += fate-ogg-flac-chained-meta > +fate-ogg-flac-chained-meta: REF = $(SAMPLES)/ogg-flac/chained-meta.txt > +fate-ogg-flac-chained-meta: CMD = > $(APITESTSDIR)/api-dump-stream-meta-test$(EXESUF) > $(TARGET_SAMPLES)/ogg-flac/chained-meta.ogg > + > +FATE_OGG_FLAC-$(call DEMDEC, OGG, FLAC) += $(FATE_OGG_FLAC) > + > +FATE_SAMPLES_DUMP_STREAM_META += $(FATE_OGG_FLAC-yes) > + > +FATE_EXTERN += $(FATE_OGG_FLAC-yes) > + > +fate-ogg-flac: $(FATE_OGG_FLAC-yes) > -- > 2.39.5 (Apple Git-154) > > _______________________________________________ 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". ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [FFmpeg-devel] [PATCH v2 1/2] Parse ogg/flac header again after processing a new chained ogg bitstream. 2025-01-29 14:40 [FFmpeg-devel] [PATCH v2 1/2] Parse ogg/flac header again after processing a new chained ogg bitstream Romain Beauxis 2025-01-29 14:40 ` [FFmpeg-devel] [PATCH v1 2/2] Add stream dump test with test for ogg/flac Romain Beauxis @ 2025-01-29 16:40 ` Marvin Scholz 2025-01-30 7:08 ` Romain Beauxis 1 sibling, 1 reply; 6+ messages in thread From: Marvin Scholz @ 2025-01-29 16:40 UTC (permalink / raw) To: FFmpeg development discussions and patches On 29 Jan 2025, at 15:40, Romain Beauxis wrote: > This patch makes sure that ogg/flac headers are parsed again when > encountering a new logic stream inside a chained ogg bistream[1]. > > This patches makes it possible to retrieve metadata in chained ogg/flac > bitstreams. It is particularly important because ogg/flac is one of the > only (if not the only one) lossless container supported over HTTP/icecast. > > The patch has been tested with various ogg/flac encoders and appears to > work fine with ffmpeg. > > Changes since last version: > * Make sure to clear the stream's metadata before parsing again. > > 1: https://xiph.org/ogg/doc/oggstream.html > Hi, thanks a lot for trying to solve this, see remarks inline below: > --- > libavformat/oggdec.c | 7 +++++-- > libavformat/oggparseflac.c | 2 ++ > 2 files changed, 7 insertions(+), 2 deletions(-) > > diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c > index 5339fdd32c..d986e19817 100644 > --- a/libavformat/oggdec.c > +++ b/libavformat/oggdec.c > @@ -239,8 +239,11 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic, > os->start_trimming = 0; > os->end_trimming = 0; > > - /* Chained files have extradata as a new packet */ > - if (codec == &ff_opus_codec) > + /* Parse opus and flac header on new chained bitstream. > + * For opus, header contains required extradata as new packet > + * For both formats, this makes it possible to read chained metadata. */ > + if (codec == &ff_opus_codec || > + codec == &ff_flac_codec) > os->header = -1; > > return i; > diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c > index f25ed9cc15..932907fa1a 100644 > --- a/libavformat/oggparseflac.c > +++ b/libavformat/oggparseflac.c > @@ -72,6 +72,8 @@ flac_header (AVFormatContext * s, int idx) > > avpriv_set_pts_info(st, 64, 1, samplerate); > } else if (mdt == FLAC_METADATA_TYPE_VORBIS_COMMENT) { > + /* New metadata packet; release old data. */ > + av_dict_free(&st->metadata); I do not think it’s fine to change this mid-demuxing, as the caller has no way to know this changed „behind its back“ so may still hold on to the old pointer and run into invalid memory access. I checked with James and he suggested that maybe propagating the new metadata with AVPacket’s side_data might be a better approach, similar to AV_PKT_DATA_NEW_EXTRADATA. > ff_vorbis_stream_comment(s, st, os->buf + os->pstart + 4, os->psize - 4); > } > > -- > 2.39.5 (Apple Git-154) > > _______________________________________________ > 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". _______________________________________________ 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". ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [FFmpeg-devel] [PATCH v2 1/2] Parse ogg/flac header again after processing a new chained ogg bitstream. 2025-01-29 16:40 ` [FFmpeg-devel] [PATCH v2 1/2] Parse ogg/flac header again after processing a new chained ogg bitstream Marvin Scholz @ 2025-01-30 7:08 ` Romain Beauxis 2025-02-04 10:57 ` Romain Beauxis 0 siblings, 1 reply; 6+ messages in thread From: Romain Beauxis @ 2025-01-30 7:08 UTC (permalink / raw) To: FFmpeg development discussions and patches Le mer. 29 janv. 2025 à 17:40, Marvin Scholz <epirat07@gmail.com> a écrit : > > > > On 29 Jan 2025, at 15:40, Romain Beauxis wrote: > > > This patch makes sure that ogg/flac headers are parsed again when > > encountering a new logic stream inside a chained ogg bistream[1]. > > > > This patches makes it possible to retrieve metadata in chained ogg/flac > > bitstreams. It is particularly important because ogg/flac is one of the > > only (if not the only one) lossless container supported over HTTP/icecast. > > > > The patch has been tested with various ogg/flac encoders and appears to > > work fine with ffmpeg. > > > > Changes since last version: > > * Make sure to clear the stream's metadata before parsing again. > > > > 1: https://xiph.org/ogg/doc/oggstream.html > > > > Hi, thanks a lot for trying to solve this, see remarks inline below: > > > --- > > libavformat/oggdec.c | 7 +++++-- > > libavformat/oggparseflac.c | 2 ++ > > 2 files changed, 7 insertions(+), 2 deletions(-) > > > > diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c > > index 5339fdd32c..d986e19817 100644 > > --- a/libavformat/oggdec.c > > +++ b/libavformat/oggdec.c > > @@ -239,8 +239,11 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic, > > os->start_trimming = 0; > > os->end_trimming = 0; > > > > - /* Chained files have extradata as a new packet */ > > - if (codec == &ff_opus_codec) > > + /* Parse opus and flac header on new chained bitstream. > > + * For opus, header contains required extradata as new packet > > + * For both formats, this makes it possible to read chained metadata. */ > > + if (codec == &ff_opus_codec || > > + codec == &ff_flac_codec) > > os->header = -1; > > > > return i; > > diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c > > index f25ed9cc15..932907fa1a 100644 > > --- a/libavformat/oggparseflac.c > > +++ b/libavformat/oggparseflac.c > > @@ -72,6 +72,8 @@ flac_header (AVFormatContext * s, int idx) > > > > avpriv_set_pts_info(st, 64, 1, samplerate); > > } else if (mdt == FLAC_METADATA_TYPE_VORBIS_COMMENT) { > > + /* New metadata packet; release old data. */ > > + av_dict_free(&st->metadata); > > I do not think it’s fine to change this mid-demuxing, as the caller > has no way to know this changed „behind its back“ so may still hold > on to the old pointer and run into invalid memory access. > > I checked with James and he suggested that maybe propagating the new > metadata with AVPacket’s side_data might be a better approach, similar > to AV_PKT_DATA_NEW_EXTRADATA. Thank you for the review! Do you mean the st->metadata dictionary? The nature of `av_dict` is to be an ever-changing pointer; each time a value is changed, the underlying pointer is changed so I think keeping a long-term pointer on it is a programming error. It's also worth noting that this is the same method used currently by the vorbis decoder. That being said, updating the AVStream is not natural and requires the user to constantly check on it. It would be more natural to have: * The headers packets flow out of the demuxer as it is now so anyone operating at this level can see them and act accordingly. * Have the decoded frame carry the new metadata, which is a more natural place for it. I'll look into this. Hopefully this is a better approach and also one that could be generalized to all ogg-encapsulated formats.. -- Romain _______________________________________________ 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". ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [FFmpeg-devel] [PATCH v2 1/2] Parse ogg/flac header again after processing a new chained ogg bitstream. 2025-01-30 7:08 ` Romain Beauxis @ 2025-02-04 10:57 ` Romain Beauxis 0 siblings, 0 replies; 6+ messages in thread From: Romain Beauxis @ 2025-02-04 10:57 UTC (permalink / raw) To: FFmpeg development discussions and patches, Marvin Scholz Le jeu. 30 janv. 2025 à 08:08, Romain Beauxis <romain.beauxis@gmail.com> a écrit : > > > > > Le mer. 29 janv. 2025 à 17:40, Marvin Scholz <epirat07@gmail.com> a écrit : > > > > > > > > On 29 Jan 2025, at 15:40, Romain Beauxis wrote: > > > > > This patch makes sure that ogg/flac headers are parsed again when > > > encountering a new logic stream inside a chained ogg bistream[1]. > > > > > > This patches makes it possible to retrieve metadata in chained ogg/flac > > > bitstreams. It is particularly important because ogg/flac is one of the > > > only (if not the only one) lossless container supported over HTTP/icecast. > > > > > > The patch has been tested with various ogg/flac encoders and appears to > > > work fine with ffmpeg. > > > > > > Changes since last version: > > > * Make sure to clear the stream's metadata before parsing again. > > > > > > 1: https://xiph.org/ogg/doc/oggstream.html > > > > > > > Hi, thanks a lot for trying to solve this, see remarks inline below: > > > > > --- > > > libavformat/oggdec.c | 7 +++++-- > > > libavformat/oggparseflac.c | 2 ++ > > > 2 files changed, 7 insertions(+), 2 deletions(-) > > > > > > diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c > > > index 5339fdd32c..d986e19817 100644 > > > --- a/libavformat/oggdec.c > > > +++ b/libavformat/oggdec.c > > > @@ -239,8 +239,11 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic, > > > os->start_trimming = 0; > > > os->end_trimming = 0; > > > > > > - /* Chained files have extradata as a new packet */ > > > - if (codec == &ff_opus_codec) > > > + /* Parse opus and flac header on new chained bitstream. > > > + * For opus, header contains required extradata as new packet > > > + * For both formats, this makes it possible to read chained metadata. */ > > > + if (codec == &ff_opus_codec || > > > + codec == &ff_flac_codec) > > > os->header = -1; > > > > > > return i; > > > diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c > > > index f25ed9cc15..932907fa1a 100644 > > > --- a/libavformat/oggparseflac.c > > > +++ b/libavformat/oggparseflac.c > > > @@ -72,6 +72,8 @@ flac_header (AVFormatContext * s, int idx) > > > > > > avpriv_set_pts_info(st, 64, 1, samplerate); > > > } else if (mdt == FLAC_METADATA_TYPE_VORBIS_COMMENT) { > > > + /* New metadata packet; release old data. */ > > > + av_dict_free(&st->metadata); > > > > I do not think it’s fine to change this mid-demuxing, as the caller > > has no way to know this changed „behind its back“ so may still hold > > on to the old pointer and run into invalid memory access. > > > > I checked with James and he suggested that maybe propagating the new > > metadata with AVPacket’s side_data might be a better approach, similar > > to AV_PKT_DATA_NEW_EXTRADATA. > > Thank you for the review! > > Do you mean the st->metadata dictionary? > > The nature of `av_dict` is to be an ever-changing pointer; each time a value is changed, the underlying pointer is changed so I think keeping a long-term pointer on it is a programming error. > > It's also worth noting that this is the same method used currently by the vorbis decoder. > > That being said, updating the AVStream is not natural and requires the user to constantly check on it. > > It would be more natural to have: > * The headers packets flow out of the demuxer as it is now so anyone operating at this level can see them and act accordingly. > * Have the decoded frame carry the new metadata, which is a more natural place for it. > > I'll look into this. Hopefully this is a better approach and also one that could be generalized to all ogg-encapsulated formats.. I'm sending another version of the patch. It pushes the metadata decoding to the codec decoding. This makes sense from separation of concern perspective: packets keep seeing the full encoded data and decoded frames see the decoded metadata. However, this adds a dependency on libavformat to libavcodec. I also looked at moving the vorbis comment parsing to libavutil but there's a lot of metadata definitions and utils that at located in libavformat at the moment so perhaps it makes sense this way. -- Romain _______________________________________________ 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". ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2025-02-04 10:58 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2025-01-29 14:40 [FFmpeg-devel] [PATCH v2 1/2] Parse ogg/flac header again after processing a new chained ogg bitstream Romain Beauxis 2025-01-29 14:40 ` [FFmpeg-devel] [PATCH v1 2/2] Add stream dump test with test for ogg/flac Romain Beauxis 2025-01-29 16:05 ` Romain Beauxis 2025-01-29 16:40 ` [FFmpeg-devel] [PATCH v2 1/2] Parse ogg/flac header again after processing a new chained ogg bitstream Marvin Scholz 2025-01-30 7:08 ` Romain Beauxis 2025-02-04 10:57 ` Romain Beauxis
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 https://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/ https://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