PR #24191 opened by Kacper Michajłow (kasper93)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24191
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24191.patch

# Summary of changes

Briefly describe what this PR does and why.

<!--
If this PR requires new FATE test samples, attach them to the PR and
list their target paths below (relative to the fate-suite root).

Attached filenames must match the sample's filename:

```fate-samples
# e.g. vorbis/new-sample.ogg
```
-->



From 51562a6e0bc905d6a579cf1ef313012f117f8ffe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Sun, 16 Aug 2026 14:55:37 +0200
Subject: [PATCH 1/2] fftools/textformat: terminate parent's line before an
 array of row elements
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Sections like programs print their member streams as separate rows, but
the parent's own line was only terminated by its footer, which runs after
the children. This fused the parent's fields with the first member row:

Before:

  program|tag:variant_bitrate=1945335|stream|index=0
  stream|index=2

After

  program|tag:variant_bitrate=1945335
  stream|index=0
  stream|index=2

Write the newline when such an array starts. Arrays with typed elements
(e.g. side data) keep continuing the line, as their elements print inline.

Signed-off-by: Kacper Michajłow <[email protected]>
---
 fftools/textformat/tf_compact.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/fftools/textformat/tf_compact.c b/fftools/textformat/tf_compact.c
index fc6bd5250b..9cb89b3fe9 100644
--- a/fftools/textformat/tf_compact.c
+++ b/fftools/textformat/tf_compact.c
@@ -138,6 +138,15 @@ static av_cold int compact_init(AVTextFormatContext *wctx)
     return 0;
 }
 
+static int array_has_inline_elems(const AVTextFormatContext *wctx,
+                                  const AVTextFormatSection *section)
+{
+    for (int i = 0; section->children_ids[i] != -1; i++)
+        if (wctx->sections[section->children_ids[i]].flags & 
AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE)
+            return 1;
+    return 0;
+}
+
 static void compact_print_section_header(AVTextFormatContext *wctx, const void 
*data)
 {
     CompactContext *compact = wctx->priv;
@@ -184,9 +193,12 @@ static void 
compact_print_section_header(AVTextFormatContext *wctx, const void *
 
         wctx->nb_item[wctx->level] = wctx->nb_item[wctx->level - 1];
     } else {
-        if (parent_section && !(parent_section->flags & 
(AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER | AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)) 
&&
-            wctx->level && wctx->nb_item[wctx->level - 1])
-            writer_w8(wctx, compact->item_sep);
+        if (parent_section && !(parent_section->flags & 
(AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER | AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))) 
{
+            if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY && 
!array_has_inline_elems(wctx, section))
+                writer_w8(wctx, '\n');
+            else if (wctx->level && wctx->nb_item[wctx->level - 1])
+                writer_w8(wctx, compact->item_sep);
+        }
         if (compact->print_section &&
             !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER | 
AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
             writer_printf(wctx, "%s%c", section->name, compact->item_sep);
-- 
2.52.0


From 959cee008ecb50f662268eec03fd63d21b1951c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= <[email protected]>
Date: Mon, 17 Aug 2026 15:10:03 +0200
Subject: [PATCH 2/2] avformat/hls: fix variant_bitrate on streams shared by
 multiple variants
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The -1 sentinel marking inconsistent bandwidths was overwritten by the
next variant containing the same playlist. Depending on the number of
variants the tag ended up unset or set to the last variant's bandwidth.
Keep a separate flag so shared streams are never tagged.

The stream-level variant_bitrate is kept for backward compatibility and
should not be relied upon. It can be missing, and its value describes
the whole variant rather than the stream itself. The per-variant value
is always available in the program metadata.

Signed-off-by: Kacper Michajłow <[email protected]>
---
 doc/demuxers.texi      | 4 +++-
 libavformat/avformat.h | 4 +++-
 libavformat/hls.c      | 5 +++--
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/doc/demuxers.texi b/doc/demuxers.texi
index 8603069949..cd3e88f59e 100644
--- a/doc/demuxers.texi
+++ b/doc/demuxers.texi
@@ -554,7 +554,9 @@ The id field is set to the bitrate variant index number. By 
setting
 the discard flags on AVStreams (by pressing 'a' or 'v' in ffplay),
 the caller can decide which variant streams to actually receive.
 The total bitrate of the variant that the stream belongs to is
-available in a metadata key named "variant_bitrate".
+available in a metadata key named "variant_bitrate". It is unset when
+the stream is shared by variants with different bitrates. The value is
+always available in the corresponding program's metadata.
 
 It accepts the following options:
 
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 9df6459f91..4682e105e8 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -421,7 +421,9 @@ struct AVFrame;
  service_provider -- name of the service provider in broadcasting.
  title        -- name of the work.
  track        -- number of this work in the set, can be in form current/total.
- variant_bitrate -- the total bitrate of the bitrate variant that the current 
stream is part of
+ variant_bitrate -- the total bitrate of the bitrate variant that the program
+                    represents or that the current stream is part of. On
+                    streams it is only set when unambiguous.
  @endverbatim
  *
  * Look in the examples section for an application example how to use the 
Metadata API.
diff --git a/libavformat/hls.c b/libavformat/hls.c
index c7b80a4cdd..fdb3a3efb9 100644
--- a/libavformat/hls.c
+++ b/libavformat/hls.c
@@ -2166,6 +2166,7 @@ static void add_stream_to_programs(AVFormatContext *s, 
struct playlist *pls, AVS
     HLSContext *c = s->priv_data;
     int i, j;
     int bandwidth = -1;
+    int consistent = 1;
 
     for (i = 0; i < c->n_variants; i++) {
         struct variant *v = c->variants[i];
@@ -2179,11 +2180,11 @@ static void add_stream_to_programs(AVFormatContext *s, 
struct playlist *pls, AVS
             if (bandwidth < 0)
                 bandwidth = v->bandwidth;
             else if (bandwidth != v->bandwidth)
-                bandwidth = -1; /* stream in multiple variants with different 
bandwidths */
+                consistent = 0; /* stream in multiple variants with different 
bandwidths */
         }
     }
 
-    if (bandwidth >= 0)
+    if (consistent && bandwidth >= 0)
         av_dict_set_int(&stream->metadata, "variant_bitrate", bandwidth, 0);
 }
 
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to