* [FFmpeg-devel] [PATCH v2 1/3] libavformat/oggparseflac.c: Decode metadata packets.
@ 2023-05-05 13:28 toots
2023-05-05 13:28 ` [FFmpeg-devel] [PATCH v2 2/3] libavformat/oggparseopus.c: Accept empty packets, decode " toots
2023-05-05 13:28 ` [FFmpeg-devel] [PATCH v2 3/3] libavformat/oggdec.c: keep reading on empty packets to accommodate for chained bitstreams toots
0 siblings, 2 replies; 3+ messages in thread
From: toots @ 2023-05-05 13:28 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Romain Beauxis
From: Romain Beauxis <toots@rastageeks.org>
This is the second version of a patch to add support for in-stream metadata
updates in the ogg/flac parser.
Currently, FFmpeg is unable to decode metadata in chained ogg/flac bitstreams
past the initial track. This impacts all users relying on the FFmpeg backend to
decode chained ogg/flac streams.
Documentation on ogg chained bitstreams can be found here: https://xiph.org/ogg/doc/oggstream.html
Code for detecting metadata frame is based on libavcodec/flacdec.c, code for
handling comment update is based on libavformat/oggparsevorbis.c.
This fix has been successfully tested locally. To reproduce:
* Find a ogg/flac icecast stream, for instance from: https://dir.xiph.org/
* Decode the stream using FFMpeg API
* Check the associated AVStream metadata
I have not been able to find a reproduction test with the ffmpeg or ffplay
CLI. However, the patch is confirmed to fix the backend from liquidsoplaySee:
https://github.com/savonet/liquidsoap/issues/3010
I would be happy to provide more details or even a reproduction minimal example
using the C API.
---
libavformat/oggparseflac.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c
index eef6e09927..1dd292483d 100644
--- a/libavformat/oggparseflac.c
+++ b/libavformat/oggparseflac.c
@@ -126,10 +126,30 @@ fail:
return ret;
}
+static int flac_packet(AVFormatContext *s, int idx)
+{
+ struct ogg *ogg = s->priv_data;
+ struct ogg_stream *os = ogg->streams + idx;
+ int ret;
+
+ if (os->psize > 4 && (*(os->buf + os->pstart) & 0x7F) == FLAC_METADATA_TYPE_VORBIS_COMMENT) {
+ AVStream *st = s->streams[idx];
+ av_dict_free(&st->metadata);
+ ret = ff_vorbis_stream_comment(s, st, os->buf + os->pstart + 4,
+ os->psize - 4);
+
+ if (ret < 0) return ret;
+ }
+
+ return 0;
+}
+
+
const struct ogg_codec ff_flac_codec = {
.magic = "\177FLAC",
.magicsize = 5,
.header = flac_header,
+ .packet = flac_packet,
.nb_header = 2,
};
--
2.37.1 (Apple Git-137.1)
_______________________________________________
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] 3+ messages in thread
* [FFmpeg-devel] [PATCH v2 2/3] libavformat/oggparseopus.c: Accept empty packets, decode metadata packets.
2023-05-05 13:28 [FFmpeg-devel] [PATCH v2 1/3] libavformat/oggparseflac.c: Decode metadata packets toots
@ 2023-05-05 13:28 ` toots
2023-05-05 13:28 ` [FFmpeg-devel] [PATCH v2 3/3] libavformat/oggdec.c: keep reading on empty packets to accommodate for chained bitstreams toots
1 sibling, 0 replies; 3+ messages in thread
From: toots @ 2023-05-05 13:28 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Romain Beauxis
From: Romain Beauxis <toots@rastageeks.org>
This patch provides the same functionality as the previous patch but for
ogg/opus.
The need to accept empty packets on end of stream (EOS) is explained in the
final patch of the series.
---
libavformat/oggparseopus.c | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/libavformat/oggparseopus.c b/libavformat/oggparseopus.c
index 54aa725be6..7991e9db42 100644
--- a/libavformat/oggparseopus.c
+++ b/libavformat/oggparseopus.c
@@ -117,8 +117,9 @@ static int opus_packet(AVFormatContext *avf, int idx)
uint8_t *packet = os->buf + os->pstart;
int ret;
- if (!os->psize)
+ if (!os->psize && !(os->flags & OGG_FLAG_EOS))
return AVERROR_INVALIDDATA;
+
if (os->granule > (1LL << 62)) {
av_log(avf, AV_LOG_ERROR, "Unsupported huge granule pos %"PRId64 "\n", os->granule);
return AVERROR_INVALIDDATA;
@@ -152,14 +153,23 @@ static int opus_packet(AVFormatContext *avf, int idx)
os->lastdts = os->granule - duration;
}
- if ((ret = opus_duration(packet, os->psize)) < 0)
- return ret;
+ if (os->psize > 0) {
+ if ((ret = opus_duration(packet, os->psize)) < 0)
+ return ret;
+
+ os->pduration = ret;
+ if (os->lastpts != AV_NOPTS_VALUE) {
+ if (st->start_time == AV_NOPTS_VALUE)
+ st->start_time = os->lastpts;
+ priv->cur_dts = os->lastdts = os->lastpts -= priv->pre_skip;
+ }
+ }
- os->pduration = ret;
- if (os->lastpts != AV_NOPTS_VALUE) {
- if (st->start_time == AV_NOPTS_VALUE)
- st->start_time = os->lastpts;
- priv->cur_dts = os->lastdts = os->lastpts -= priv->pre_skip;
+ if (os->psize > 8 && !memcmp(os->buf + os->pstart, "OpusTags", 8)) {
+ av_dict_free(&st->metadata);
+ ret = ff_vorbis_stream_comment(avf, st, os->buf + os->pstart + 8,
+ os->psize - 8);
+ if (ret < 0) return ret;
}
priv->cur_dts += os->pduration;
--
2.37.1 (Apple Git-137.1)
_______________________________________________
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] 3+ messages in thread
* [FFmpeg-devel] [PATCH v2 3/3] libavformat/oggdec.c: keep reading on empty packets to accommodate for chained bitstreams.
2023-05-05 13:28 [FFmpeg-devel] [PATCH v2 1/3] libavformat/oggparseflac.c: Decode metadata packets toots
2023-05-05 13:28 ` [FFmpeg-devel] [PATCH v2 2/3] libavformat/oggparseopus.c: Accept empty packets, decode " toots
@ 2023-05-05 13:28 ` toots
1 sibling, 0 replies; 3+ messages in thread
From: toots @ 2023-05-05 13:28 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Romain Beauxis
From: Romain Beauxis <toots@rastageeks.org>
This patch is the last of a series of patch to enhance FFmpeg's handling of
chained ogg streams.
Documentation for chained (and multiplexed) ogg bitstream can be found here:
https://xiph.org/ogg/doc/oggstream.html
My understanding of the current code is that the ogg demuxer will process all
pages from the current ogg track and, after reaching the last page, if another
page follows, will try to match the new stream with the previous one using
its codec. (See ogg_replace_stream in libavformat/oggdec.c).
Meanwhile, the underlying resources for the old stream are destroyed and new
resources are created. There seems to be issues with flushing remaining data
in such cases (see oggvorbis_decode_frame in libavcodec/libvorbisdec.c).
However, on the ogg bitstream side, sending an empty packet as the last packet
of the stream is common practice in ogg/opus streams.
For this reason, the previous patch in this series allowed opus_packet
in libavformat/oggparseopus.c to process empty EOS packets without failing
the stream for having invalid data.
However, if this packet is allowed to go through ogg_read_packet in
libavformat/oggdec.c, then the returned size from the function is 0, which
results in a EINVAL error while reading the stream.
Thus, this patch makes it so that empty packets are ignored. The bitstream
is read further and, if it ends, a proper EOF is returned. Otherwise, a new
chained bitream can begin and the demuxer can try to match it.
Without this patch, typically, decoding a chained ogg/opus stream with a final
empty ogg packet (very common) raises an error on each end of track.
To reproduce or test:
- Try this command: ffmpeg -re -i http://content.radiosega.net:8006/rs-opus-low.ogg \
-loglevel verbose -f null -
This a typical log on track change before this series of patch is applied:
<---- LOG BEGIN HERE ---->
[ogg @ 0x13b004080] Packet processing failed: Invalid data found when processing input
Error demuxing input file 0: Invalid data found when processing input
Terminating demuxer thread 0
http://content.radiosega.net:8006/rs-opus-low.ogg: Invalid data found when processing input
No more output streams to write to, finishing.
[out#0/null @ 0x600000b5c180] All streams finished
[out#0/null @ 0x600000b5c180] Terminating muxer thread
size=N/A time=00:00:43.12 bitrate=N/A speed= 1x
video:0kB audio:8089kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Input file #0 (http://content.radiosega.net:8006/rs-opus-low.ogg):
Input stream #0:0 (audio): 2161 packets read (229129 bytes); 2157 frames decoded (2070720 samples);
Total: 2161 packets (229129 bytes) demuxed
Output file #0 (pipe:):
Output stream #0:0 (audio): 2157 frames encoded (2070720 samples); 2157 packets muxed (8282880 bytes);
Total: 2157 packets (8282880 bytes) muxed
[AVIOContext @ 0x13b104080] Statistics: 273900 bytes read, 0 seeks
<---- LOG END HERE ---->
(stream processing stops afterward)
This means that, currently, the ffmpeg command line is not able to process
chained ogg/opus that typically end with an empty packet beyong its first
track.
After the patch series is applied: processing continues sucessfully.
---
libavformat/oggdec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c
index 3b19e0bd89..b0d850a406 100644
--- a/libavformat/oggdec.c
+++ b/libavformat/oggdec.c
@@ -835,7 +835,7 @@ retry:
ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
if (ret < 0)
return ret;
- } while (idx < 0 || !s->streams[idx]);
+ } while (idx < 0 || !s->streams[idx] || psize == 0);
ogg = s->priv_data;
os = ogg->streams + idx;
--
2.37.1 (Apple Git-137.1)
_______________________________________________
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] 3+ messages in thread
end of thread, other threads:[~2023-05-05 13:35 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-05 13:28 [FFmpeg-devel] [PATCH v2 1/3] libavformat/oggparseflac.c: Decode metadata packets toots
2023-05-05 13:28 ` [FFmpeg-devel] [PATCH v2 2/3] libavformat/oggparseopus.c: Accept empty packets, decode " toots
2023-05-05 13:28 ` [FFmpeg-devel] [PATCH v2 3/3] libavformat/oggdec.c: keep reading on empty packets to accommodate for chained bitstreams toots
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