Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH v2 0/3] Properly decode ogg metadata in ogg/flac chained bitstreams
@ 2025-02-04 11:15 Romain Beauxis
  2025-02-04 11:15 ` [FFmpeg-devel] [PATCH v2 1/3] libavformat/oggdec: Allow first parameter in ff_vorbis_comment to be a generic AVClass struct Romain Beauxis
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Romain Beauxis @ 2025-02-04 11:15 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: epirat07, Romain Beauxis

This is a series of 3 patches to allow proper decoding of ogg metadata
in chained ogg/flac streams.

ogg/flac streams are pretty important because there are perhaps the only
combination of lossless audio codec and open-source container that
allows for proper transmittion of lossless audio data accross systems
such as Icecast, browser media tags and more.

In the context of long-running audio streams, the ogg bitstream specs[1]
have historically been very badly implemented. For each new track and
each new metadata, the specs require the logical bitstream to come to a
full EOF and then start with a full new logical stream.

These specs have often been confused with a gobal EOF by most
implementations.

Furtunately, FFmpeg is a little better at that in that it is capable to
parsing chained logical ogg bitstreams and properly output either
encoded ogg packets or decoded audio.

Chained bitstreams with more than one underlying type of content
(audio+video, etc) is not yet supported though this is a much less needed
feature.

The purpose of these changes is to also allow proper decoding of
metadata associated with subsequent streams in chained ogg/flac
bitstream.

This is done by simply intercepting ogg packets with comments in the
flac decoded, parsing the comment block and retaining it to be attached
with the next decoded audio frame.

Along with the changes is a new FATE test validating the implementation.

This solution keeps a proper separation of concerns: ogg packets are
sill output by the demuxer (as shown in the test) but consumer of decoded
data see decoded metadata in the decoded frames.

Only drawback is that this adds a dependency on libavformat to
libavcodec.

I have looked at moving the vorbis metadata parsing to libavutil but a
lot of definitions and utilities related to metadata are in fact located
in libavformat so perhaps this makes sense.

Follow-up work not addressed in this series of patch:
* Ensure valid PTS in decoded frames of subsequent streams?
* Generalize this approach to other chained ogg codec.

Thanks,
-- Romain

Romain Beauxis (3):
  libavformat/oggdec: Allow first parameter in ff_vorbis_comment to be a
    generic AVClass struct
  libavcodec/flacdec: parse vorbis metadata from ogg packets, add them
    to the next decoded frame.
  Add stream dump test with test for ogg/flac.

 libavcodec/flacdec.c                  |  12 +-
 libavformat/oggdec.h                  |   5 +-
 libavformat/oggparsevorbis.c          |   4 +-
 tests/Makefile                        |   2 +
 tests/api/Makefile                    |   2 +-
 tests/api/api-dump-stream-meta-test.c | 169 ++++++++++++++++++++++++++
 tests/fate/api.mak                    |   5 +
 tests/fate/ogg-flac.mak               |  11 ++
 8 files changed, 205 insertions(+), 5 deletions(-)
 create mode 100644 tests/api/api-dump-stream-meta-test.c
 create mode 100644 tests/fate/ogg-flac.mak

-- 
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] 5+ messages in thread

* [FFmpeg-devel] [PATCH v2 1/3] libavformat/oggdec: Allow first parameter in ff_vorbis_comment to be a generic AVClass struct
  2025-02-04 11:15 [FFmpeg-devel] [PATCH v2 0/3] Properly decode ogg metadata in ogg/flac chained bitstreams Romain Beauxis
@ 2025-02-04 11:15 ` Romain Beauxis
  2025-02-04 11:15 ` [FFmpeg-devel] [PATCH v2 2/3] libavcodec/flacdec: parse vorbis metadata from ogg packets, add them to the next decoded frame Romain Beauxis
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Romain Beauxis @ 2025-02-04 11:15 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: epirat07, Romain Beauxis

Firt argument in these function is only used to pass to av_log. This
makes it possible to re-use them with any type of AVClass struct.

---
 libavformat/oggdec.h         | 5 ++++-
 libavformat/oggparsevorbis.c | 4 ++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/libavformat/oggdec.h b/libavformat/oggdec.h
index 43df23f4cb..6177254fd2 100644
--- a/libavformat/oggdec.h
+++ b/libavformat/oggdec.h
@@ -136,8 +136,11 @@ extern const struct ogg_codec ff_vp8_codec;
  *        so it needs to be writable. Furthermore it must be padded
  *        by a single byte (not counted in size).
  *        All changes will have been reverted upon return.
+ *
+ * @param avcl A pointer to an arbitrary struct of which the first field is a
+ *        pointer to an AVClass struct.
  */
-int ff_vorbis_comment(AVFormatContext *ms, AVDictionary **m,
+int ff_vorbis_comment(void *avcl, AVDictionary **m,
                       const uint8_t *buf, int size, int parse_picture);
 
 /**
diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
index 9f50ab9ffc..62eb8bbf70 100644
--- a/libavformat/oggparsevorbis.c
+++ b/libavformat/oggparsevorbis.c
@@ -88,7 +88,7 @@ int ff_vorbis_stream_comment(AVFormatContext *as, AVStream *st,
  * and reverts its changes before return. The input buffer needs to have
  * at least one byte of padding.
  */
-static int vorbis_parse_single_comment(AVFormatContext *as, AVDictionary **m,
+static int vorbis_parse_single_comment(void *as, AVDictionary **m,
                                        const uint8_t *buf, uint32_t size,
                                        int *updates, int parse_picture)
 {
@@ -146,7 +146,7 @@ end:
     return 0;
 }
 
-int ff_vorbis_comment(AVFormatContext *as, AVDictionary **m,
+int ff_vorbis_comment(void *as, AVDictionary **m,
                       const uint8_t *buf, int size,
                       int parse_picture)
 {
-- 
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] 5+ messages in thread

* [FFmpeg-devel] [PATCH v2 2/3] libavcodec/flacdec: parse vorbis metadata from ogg packets, add them to the next decoded frame.
  2025-02-04 11:15 [FFmpeg-devel] [PATCH v2 0/3] Properly decode ogg metadata in ogg/flac chained bitstreams Romain Beauxis
  2025-02-04 11:15 ` [FFmpeg-devel] [PATCH v2 1/3] libavformat/oggdec: Allow first parameter in ff_vorbis_comment to be a generic AVClass struct Romain Beauxis
@ 2025-02-04 11:15 ` Romain Beauxis
  2025-02-04 11:15 ` [FFmpeg-devel] [PATCH v2 3/3] Add stream dump test with test for ogg/flac Romain Beauxis
  2025-02-04 12:19 ` [FFmpeg-devel] [PATCH v2 0/3] Properly decode ogg metadata in ogg/flac chained bitstreams Romain Beauxis
  3 siblings, 0 replies; 5+ messages in thread
From: Romain Beauxis @ 2025-02-04 11:15 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: epirat07, Romain Beauxis

This is the main patch. Parse ogg comments in ogg packets with comment,
keep them in pending_metadata and copy them to the next decoded audio
frame.

---
 libavcodec/flacdec.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/libavcodec/flacdec.c b/libavcodec/flacdec.c
index ad921a1bd1..03a68cdfef 100644
--- a/libavcodec/flacdec.c
+++ b/libavcodec/flacdec.c
@@ -37,6 +37,7 @@
 #include "libavutil/crc.h"
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
+#include "libavformat/oggdec.h"
 #include "avcodec.h"
 #include "codec_internal.h"
 #include "get_bits.h"
@@ -68,6 +69,8 @@ typedef struct FLACContext {
     unsigned int decoded_buffer_size_33bps;
     int buggy_lpc;                          ///< use workaround for old lavc encoded files
 
+    AVDictionary *pending_metadata;
+
     FLACDSPContext dsp;
 } FLACContext;
 
@@ -728,7 +731,8 @@ static int flac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
     }
 
     if (buf_size > 0 && (*buf & 0x7F) == FLAC_METADATA_TYPE_VORBIS_COMMENT) {
-        av_log(s->avctx, AV_LOG_DEBUG, "skipping vorbis comment\n");
+        av_dict_free(&s->pending_metadata);
+        ff_vorbis_comment(avctx, &s->pending_metadata, buf + 4, buf_size - 4, 1);
         return buf_size;
     }
 
@@ -788,6 +792,11 @@ static int flac_decode_frame(AVCodecContext *avctx, AVFrame *frame,
                buf_size - bytes_read, buf_size);
     }
 
+    if (s->pending_metadata) {
+        av_dict_copy(&frame->metadata, s->pending_metadata, AV_DICT_APPEND);
+        av_dict_free(&s->pending_metadata);
+    }
+
     *got_frame_ptr = 1;
 
     return bytes_read;
@@ -799,6 +808,7 @@ static av_cold int flac_decode_close(AVCodecContext *avctx)
 
     av_freep(&s->decoded_buffer);
     av_freep(&s->decoded_buffer_33bps);
+    av_dict_free(&s->pending_metadata);
 
     return 0;
 }
-- 
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] 5+ messages in thread

* [FFmpeg-devel] [PATCH v2 3/3] Add stream dump test with test for ogg/flac.
  2025-02-04 11:15 [FFmpeg-devel] [PATCH v2 0/3] Properly decode ogg metadata in ogg/flac chained bitstreams Romain Beauxis
  2025-02-04 11:15 ` [FFmpeg-devel] [PATCH v2 1/3] libavformat/oggdec: Allow first parameter in ff_vorbis_comment to be a generic AVClass struct Romain Beauxis
  2025-02-04 11:15 ` [FFmpeg-devel] [PATCH v2 2/3] libavcodec/flacdec: parse vorbis metadata from ogg packets, add them to the next decoded frame Romain Beauxis
@ 2025-02-04 11:15 ` Romain Beauxis
  2025-02-04 12:19 ` [FFmpeg-devel] [PATCH v2 0/3] Properly decode ogg metadata in ogg/flac chained bitstreams Romain Beauxis
  3 siblings, 0 replies; 5+ messages in thread
From: Romain Beauxis @ 2025-02-04 11:15 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: epirat07, Romain Beauxis

This is the new FATE test.

Test samples are available here: https://www.dropbox.com/scl/fo/fxt2edwkyj2mjc9qubku5/AICHxJyxMMAK8MIJqWLcvk4?rlkey=mlt12lsu741ejukz0p5qtn9rq&dl=0

Output prior to the changes is:
Stream ID: 0, codec name: flac, metadata: encoder=Lavc61.19.100 flac:title=First Stream
Stream ID: 0, packet PTS: 0, packet DTS: 0
Stream ID: 0, frame PTS: 0, metadata:
Stream ID: 0, packet PTS: 4608, packet DTS: 4608
Stream ID: 0, frame PTS: 4608, metadata:
Stream ID: 0, packet PTS: 0, packet DTS: 0
Stream ID: 0, packet PTS: 0, packet DTS: 0
Stream ID: 0, packet PTS: 0, packet DTS: 0
Stream ID: 0, frame PTS: 0, metadata:
Stream ID: 0, packet PTS: 4608, packet DTS: 4608
Stream ID: 0, frame PTS: 4608, metadata:

Output after the changes:
Stream ID: 0, codec name: flac, metadata: encoder=Lavc61.19.100 flac:title=First Stream
Stream ID: 0, packet PTS: 0, packet DTS: 0
Stream ID: 0, frame PTS: 0, metadata:
Stream ID: 0, packet PTS: 4608, packet DTS: 4608
Stream ID: 0, frame PTS: 4608, metadata:
Stream ID: 0, packet PTS: 0, packet DTS: 0
Stream ID: 0, packet PTS: 0, packet DTS: 0
Stream ID: 0, packet PTS: 0, packet DTS: 0
Stream ID: 0, frame PTS: 0, metadata: encoder=Lavc61.19.100 flac:title=Second Stream
Stream ID: 0, packet PTS: 4608, packet DTS: 4608
Stream ID: 0, frame PTS: 4608, metadata:

---
 tests/Makefile                        |   2 +
 tests/api/Makefile                    |   2 +-
 tests/api/api-dump-stream-meta-test.c | 169 ++++++++++++++++++++++++++
 tests/fate/api.mak                    |   5 +
 tests/fate/ogg-flac.mak               |  11 ++
 5 files changed, 188 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..4ffdfe8213
--- /dev/null
+++ b/tests/api/api-dump-stream-meta-test.c
@@ -0,0 +1,169 @@
+/*
+ * 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 "libavcodec/avcodec.h"
+#include "libavformat/avformat.h"
+#include "libavutil/timestamp.h"
+
+static int dump_stream_meta(const char *input_filename)
+{
+    const AVCodec *codec = NULL;
+    AVPacket *pkt = NULL;
+    AVFrame *fr = NULL;
+    AVFormatContext *fmt_ctx = NULL;
+    AVCodecContext *ctx = NULL;
+    AVCodecParameters *origin_par = NULL;
+    int audio_stream;
+    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;
+    }
+
+    // TODO: add ability to work with video format
+    audio_stream =
+        av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
+    if (audio_stream < 0) {
+        av_log(NULL, AV_LOG_ERROR, "Can't find audio stream in input file\n");
+        result = audio_stream;
+        goto end;
+    }
+
+    origin_par = fmt_ctx->streams[audio_stream]->codecpar;
+
+    result = av_dict_get_string(
+        fmt_ctx->streams[audio_stream]->metadata, &metadata, '=', ':');
+    if (result < 0)
+        goto end;
+
+    printf("Stream ID: %d, codec name: %s, metadata: %s\n", audio_stream,
+        avcodec_get_name(origin_par->codec_id), metadata);
+
+    codec = avcodec_find_decoder(origin_par->codec_id);
+    if (!codec) {
+        av_log(NULL, AV_LOG_ERROR, "Can't find decoder\n");
+        result = AVERROR_DECODER_NOT_FOUND;
+        goto end;
+    }
+
+    ctx = avcodec_alloc_context3(codec);
+    if (!ctx) {
+        av_log(NULL, AV_LOG_ERROR, "Can't allocate decoder context\n");
+        result = AVERROR(ENOMEM);
+        goto end;
+    }
+
+    result = avcodec_parameters_to_context(ctx, origin_par);
+    if (result) {
+        av_log(NULL, AV_LOG_ERROR, "Can't copy decoder context\n");
+        goto end;
+    }
+
+    result = avcodec_open2(ctx, codec, NULL);
+    if (result < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Can't open decoder\n");
+        goto end;
+    }
+
+    pkt = av_packet_alloc();
+    if (!pkt) {
+        av_log(NULL, AV_LOG_ERROR, "Cannot allocate packet\n");
+        result = AVERROR(ENOMEM);
+        goto end;
+    }
+
+    fr = av_frame_alloc();
+    if (!fr) {
+        av_log(NULL, AV_LOG_ERROR, "Can't allocate frame\n");
+        result = AVERROR(ENOMEM);
+        goto end;
+    }
+
+    for (;;) {
+        result = av_read_frame(fmt_ctx, pkt);
+        if (result)
+            goto end;
+
+        if (pkt->stream_index != audio_stream) {
+            av_packet_unref(pkt);
+            continue;
+        }
+
+        printf("Stream ID: %d, packet PTS: %s, packet DTS: %s\n",
+            pkt->stream_index, av_ts2str(pkt->pts), av_ts2str(pkt->dts));
+
+        result = avcodec_send_packet(ctx, pkt);
+        av_packet_unref(pkt);
+
+        if (result < 0)
+            goto end;
+
+        result = avcodec_receive_frame(ctx, fr);
+        if (result == AVERROR_EOF) {
+            result = 0;
+            goto end;
+        }
+
+        if (result == AVERROR(EAGAIN))
+            continue;
+
+        result = av_dict_get_string(fr->metadata, &metadata, '=', ':');
+        if (result < 0)
+            goto end;
+
+        printf("Stream ID: %d, frame PTS: %s, metadata: %s\n",
+            pkt->stream_index, av_ts2str(fr->pts), metadata);
+    }
+
+end:
+    av_packet_free(&pkt);
+    av_frame_free(&fr);
+    avformat_close_input(&fmt_ctx);
+    avcodec_free_context(&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] 5+ messages in thread

* Re: [FFmpeg-devel] [PATCH v2 0/3] Properly decode ogg metadata in ogg/flac chained bitstreams
  2025-02-04 11:15 [FFmpeg-devel] [PATCH v2 0/3] Properly decode ogg metadata in ogg/flac chained bitstreams Romain Beauxis
                   ` (2 preceding siblings ...)
  2025-02-04 11:15 ` [FFmpeg-devel] [PATCH v2 3/3] Add stream dump test with test for ogg/flac Romain Beauxis
@ 2025-02-04 12:19 ` Romain Beauxis
  3 siblings, 0 replies; 5+ messages in thread
From: Romain Beauxis @ 2025-02-04 12:19 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: epirat07

Le mar. 4 févr. 2025 à 06:15, Romain Beauxis
<romain.beauxis@gmail.com> a écrit :
>
> This is a series of 3 patches to allow proper decoding of ogg metadata
> in chained ogg/flac streams.
>
> ogg/flac streams are pretty important because there are perhaps the only
> combination of lossless audio codec and open-source container that
> allows for proper transmittion of lossless audio data accross systems
> such as Icecast, browser media tags and more.
>
> In the context of long-running audio streams, the ogg bitstream specs[1]
> have historically been very badly implemented. For each new track and
> each new metadata, the specs require the logical bitstream to come to a
> full EOF and then start with a full new logical stream.
>
> These specs have often been confused with a gobal EOF by most
> implementations.
>
> Furtunately, FFmpeg is a little better at that in that it is capable to
> parsing chained logical ogg bitstreams and properly output either
> encoded ogg packets or decoded audio.
>
> Chained bitstreams with more than one underlying type of content
> (audio+video, etc) is not yet supported though this is a much less needed
> feature.
>
> The purpose of these changes is to also allow proper decoding of
> metadata associated with subsequent streams in chained ogg/flac
> bitstream.
>
> This is done by simply intercepting ogg packets with comments in the
> flac decoded, parsing the comment block and retaining it to be attached
> with the next decoded audio frame.
>
> Along with the changes is a new FATE test validating the implementation.
>
> This solution keeps a proper separation of concerns: ogg packets are
> sill output by the demuxer (as shown in the test) but consumer of decoded
> data see decoded metadata in the decoded frames.
>
> Only drawback is that this adds a dependency on libavformat to
> libavcodec.
>
> I have looked at moving the vorbis metadata parsing to libavutil but a
> lot of definitions and utilities related to metadata are in fact located
> in libavformat so perhaps this makes sense.

Of course, it was only after posting all this that I figured out how
to properly do this.

About to send an updated patch set sorry for the noise.

-- Romain

> Follow-up work not addressed in this series of patch:
> * Ensure valid PTS in decoded frames of subsequent streams?
> * Generalize this approach to other chained ogg codec.
>
> Thanks,
> -- Romain
>
> Romain Beauxis (3):
>   libavformat/oggdec: Allow first parameter in ff_vorbis_comment to be a
>     generic AVClass struct
>   libavcodec/flacdec: parse vorbis metadata from ogg packets, add them
>     to the next decoded frame.
>   Add stream dump test with test for ogg/flac.
>
>  libavcodec/flacdec.c                  |  12 +-
>  libavformat/oggdec.h                  |   5 +-
>  libavformat/oggparsevorbis.c          |   4 +-
>  tests/Makefile                        |   2 +
>  tests/api/Makefile                    |   2 +-
>  tests/api/api-dump-stream-meta-test.c | 169 ++++++++++++++++++++++++++
>  tests/fate/api.mak                    |   5 +
>  tests/fate/ogg-flac.mak               |  11 ++
>  8 files changed, 205 insertions(+), 5 deletions(-)
>  create mode 100644 tests/api/api-dump-stream-meta-test.c
>  create mode 100644 tests/fate/ogg-flac.mak
>
> --
> 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] 5+ messages in thread

end of thread, other threads:[~2025-02-04 12:19 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-04 11:15 [FFmpeg-devel] [PATCH v2 0/3] Properly decode ogg metadata in ogg/flac chained bitstreams Romain Beauxis
2025-02-04 11:15 ` [FFmpeg-devel] [PATCH v2 1/3] libavformat/oggdec: Allow first parameter in ff_vorbis_comment to be a generic AVClass struct Romain Beauxis
2025-02-04 11:15 ` [FFmpeg-devel] [PATCH v2 2/3] libavcodec/flacdec: parse vorbis metadata from ogg packets, add them to the next decoded frame Romain Beauxis
2025-02-04 11:15 ` [FFmpeg-devel] [PATCH v2 3/3] Add stream dump test with test for ogg/flac Romain Beauxis
2025-02-04 12:19 ` [FFmpeg-devel] [PATCH v2 0/3] Properly decode ogg metadata in ogg/flac chained bitstreams 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