[vlc-commits] [Git][videolan/vlc][master] 4 commits: sout: hls: add a legacy-codec option

Steve Lhomme (@robUx4) gitlab at videolan.org
Wed Sep 2 08:53:55 UTC 2026



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
de871d76 by Alaric Senat at 2026-09-02T08:39:18+00:00
sout: hls: add a legacy-codec option

In preparation of flac and opus introduction. These codecs were
supported by browsers before being standardized and the spec chose a
different codec identifier than the pre-standard one.
Some clients support both, some older ones only support the legacy
codec. Let's bring an option so it's up to the user to choose.

This firefox bug report sumarize the situation: <https://bugzilla.mozilla.org/show_bug.cgi?id=1783453>

- - - - -
7d65e5e6 by Alaric Senat at 2026-09-02T08:39:18+00:00
sout: hls: add FLAC support

- - - - -
e93bd5c8 by Alaric Senat at 2026-09-02T08:39:18+00:00
sout: hls: add Opus support

Opus is not a standardized entry for HLS, however it has been supported
by many clients for a long time. The chromecast default receiver
supports it which is very valuable to avoid unecessary transcoding.

- - - - -
3b1d73b3 by Alaric Senat at 2026-09-02T08:39:18+00:00
sout: hls: add AC-3 and E-AC-3 support

- - - - -


4 changed files:

- modules/stream_out/hls/codecs.c
- modules/stream_out/hls/codecs.h
- modules/stream_out/hls/hls.c
- modules/stream_out/hls/hls.h


Changes:

=====================================
modules/stream_out/hls/codecs.c
=====================================
@@ -157,13 +157,37 @@ static int FormatMP4A(struct vlc_memstream *ms, const es_format_t *fmt)
     return (written < 0) ? VLC_ENOMEM : VLC_SUCCESS;
 }
 
+static int FormatOpus(struct vlc_memstream *ms, bool legacy)
+{
+    // Legacy lower-cased "opus" is required by
+    // some receivers (e.g. Chromecast default receiver or old browsers).
+    const int written = vlc_memstream_puts(ms, legacy ? "opus" : "Opus");
+    return (written <= 0) ? VLC_ENOMEM : VLC_SUCCESS;
+}
+
+static int FormatFLAC(struct vlc_memstream *ms, bool legacy)
+{
+    // Legacy lower-cased "flac" is required by some receivers (e.g. Chromecast
+    // default receiver or old browsers).
+    const int written = vlc_memstream_puts(ms, legacy ? "flac" : "fLaC");
+    return (written <= 0) ? VLC_ENOMEM : VLC_SUCCESS;
+}
+
+static int FormatAC3(struct vlc_memstream *ms, const es_format_t *fmt)
+{
+    const int written = vlc_memstream_puts(
+        ms, (fmt->i_codec == VLC_CODEC_EAC3) ? "ec-3" : "ac-3");
+    return (written <= 0) ? VLC_ENOMEM : VLC_SUCCESS;
+}
+
 static int FormatWebVTT(struct vlc_memstream *ms)
 {
     const int written = vlc_memstream_puts(ms, "wvtt");
     return (written <= 0) ? VLC_ENOMEM : VLC_SUCCESS;
 }
 
-int hls_codec_Format(struct vlc_memstream *ms, const es_format_t *fmt)
+int hls_codec_Format(struct vlc_memstream *ms, const es_format_t *fmt,
+                     bool legacy_codecs)
 {
     switch (fmt->i_codec)
     {
@@ -173,6 +197,13 @@ int hls_codec_Format(struct vlc_memstream *ms, const es_format_t *fmt)
             return FormatHEVC(ms, fmt);
         case VLC_CODEC_MP4A:
             return FormatMP4A(ms, fmt);
+        case VLC_CODEC_OPUS:
+            return FormatOpus(ms, legacy_codecs);
+        case VLC_CODEC_FLAC:
+            return FormatFLAC(ms, legacy_codecs);
+        case VLC_CODEC_A52:
+        case VLC_CODEC_EAC3:
+            return FormatAC3(ms, fmt);
         case VLC_CODEC_TEXT:
         case VLC_CODEC_WEBVTT:
             return FormatWebVTT(ms);
@@ -184,6 +215,8 @@ int hls_codec_Format(struct vlc_memstream *ms, const es_format_t *fmt)
 bool hls_codec_IsSupported(const es_format_t *fmt)
 {
     return fmt->i_codec == VLC_CODEC_H264 || fmt->i_codec == VLC_CODEC_HEVC ||
-           fmt->i_codec == VLC_CODEC_MP4A || fmt->i_codec == VLC_CODEC_TEXT ||
+           fmt->i_codec == VLC_CODEC_MP4A || fmt->i_codec == VLC_CODEC_OPUS ||
+           fmt->i_codec == VLC_CODEC_FLAC || fmt->i_codec == VLC_CODEC_A52 ||
+           fmt->i_codec == VLC_CODEC_EAC3 || fmt->i_codec == VLC_CODEC_TEXT ||
            fmt->i_codec == VLC_CODEC_WEBVTT;
 }


=====================================
modules/stream_out/hls/codecs.h
=====================================
@@ -20,7 +20,7 @@
 #ifndef HLS_CODECS_H
 #define HLS_CODECS_H
 
-int hls_codec_Format(struct vlc_memstream *, const es_format_t *);
+int hls_codec_Format(struct vlc_memstream *, const es_format_t *, bool legacy_codecs);
 bool hls_codec_IsSupported(const es_format_t *);
 
 #endif


=====================================
modules/stream_out/hls/hls.c
=====================================
@@ -247,7 +247,8 @@ static inline hls_track_t *MediaGetTrack(const hls_playlist_t *media_playlist)
 }
 
 VLC_MALLOC static char *GeneratePlaylistCodecInfo(const struct vlc_list *media_list,
-                                                  const hls_playlist_t *playlist)
+                                                  const hls_playlist_t *playlist,
+                                                  bool legacy_codecs)
 {
     es_format_vec_t already_described = VLC_VECTOR_INITIALIZER;
 
@@ -264,7 +265,7 @@ VLC_MALLOC static char *GeneratePlaylistCodecInfo(const struct vlc_list *media_l
 
         if (!is_stream_empty)
             vlc_memstream_putc(&out, ',');
-        if (hls_codec_Format(&out, &track->input->fmt) != VLC_SUCCESS)
+        if (hls_codec_Format(&out, &track->input->fmt, legacy_codecs) != VLC_SUCCESS)
             goto error;
         is_stream_empty = false;
         vlc_vector_push(&already_described, &track->input->fmt);
@@ -281,7 +282,7 @@ VLC_MALLOC static char *GeneratePlaylistCodecInfo(const struct vlc_list *media_l
 
         if (!is_stream_empty)
             vlc_memstream_putc(&out, ',');
-        if (hls_codec_Format(&out, &track->input->fmt) != VLC_SUCCESS)
+        if (hls_codec_Format(&out, &track->input->fmt, legacy_codecs) != VLC_SUCCESS)
             goto error;
         is_stream_empty = false;
         vlc_vector_push(&already_described, &track->input->fmt);
@@ -424,8 +425,8 @@ static int GenerateMainManifest(const sout_stream_sys_t *sys,
                 bandwidth += track->input->fmt.i_bitrate;
             MANIFEST_ADD_ATTRIBUTE("BANDWIDTH=%u", bandwidth);
 
-            char *codecs =
-                GeneratePlaylistCodecInfo(&sys->media_playlists, playlist);
+            char *codecs = GeneratePlaylistCodecInfo(
+                &sys->media_playlists, playlist, sys->config.legacy_codecs);
             if (unlikely(codecs == NULL))
                 goto error;
             MANIFEST_ADD_ATTRIBUTE("CODECS=\"%s\"", codecs);
@@ -1501,6 +1502,7 @@ static int Open(vlc_object_t *this)
         "base-url",
         "host-http",
         "max-memory",
+        "legacy-codecs",
         "num-seg",
         "out-dir",
         "pace",
@@ -1518,6 +1520,8 @@ static int Open(vlc_object_t *this)
     sys->config.max_segments =
         var_GetInteger(stream, SOUT_CFG_PREFIX "num-seg");
     sys->config.pace = var_GetBool(stream, SOUT_CFG_PREFIX "pace");
+    sys->config.legacy_codecs =
+        var_GetBool(stream, SOUT_CFG_PREFIX "legacy-codecs");
     sys->config.segment_length =
         VLC_TICK_FROM_SEC(var_GetInteger(stream, SOUT_CFG_PREFIX "seg-len"));
     sys->config.max_segment_length =
@@ -1659,6 +1663,14 @@ variant_error:
 
 #define SEGTYPE_LONGTEXT N_("Specifies the segments container")
 #define SEGTYPE_TEXT N_("Segment muxed format")
+#define LEGACYCODECS_TEXT N_("Use legacy codec identifiers")
+#define LEGACYCODECS_LONGTEXT                                                  \
+    N_("Use legacy codec identifiers instead of the spec-compliant ones. "     \
+       "Some codecs that were unofficially supported before an official "      \
+       "MPEG standardization differ in identifiers (eg. flac and opus). "      \
+       "Enable this for compatibility with clients that do not support the "   \
+       "standard identifiers.")
+
 static const char *const SEGMENT_TYPE_LIST[] = {
     "ts",
     "fmp4",
@@ -1686,6 +1698,7 @@ vlc_module_begin()
     add_integer(SOUT_CFG_PREFIX "num-seg", 0, NUMSEG_TEXT, NUMSEG_TEXT)
     add_string(SOUT_CFG_PREFIX "out-dir", NULL, OUTDIR_TEXT, OUTDIR_LONGTEXT)
     add_bool(SOUT_CFG_PREFIX "pace", false, PACE_TEXT, PACE_LONGTEXT)
+    add_bool(SOUT_CFG_PREFIX "legacy-codecs", false, LEGACYCODECS_TEXT, LEGACYCODECS_LONGTEXT)
     add_integer(SOUT_CFG_PREFIX "seg-len", 4, SEGLEN_TEXT, SEGLEN_LONGTEXT)
         change_integer_range(1, 60)
     add_integer(SOUT_CFG_PREFIX "max-seg-len", 0, MAXSEGLEN_TEXT, MAXSEGLEN_LONGTEXT)


=====================================
modules/stream_out/hls/hls.h
=====================================
@@ -60,6 +60,7 @@ struct hls_config
     vlc_tick_t max_segment_length;
     size_t max_memory;
     enum hls_playlist_type preferred_type;
+    bool legacy_codecs;
 };
 
 #define BYTES_FROM_KB(x) ((x) * 1000)



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/f175076990e14a714a359a1333921cb21d80fb6e...3b1d73b30c5f6220164acdecb745842c6eabcb03

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/f175076990e14a714a359a1333921cb21d80fb6e...3b1d73b30c5f6220164acdecb745842c6eabcb03
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help




More information about the vlc-commits mailing list