Commit 9b738770b4 for ffmpeg

commit 9b738770b44ac2358c307588de51822924231861
Author: Jun Zhao <barryjzhao@tencent.com>
Date:   Sat Oct 24 15:40:00 2026 +0800

    avformat/au: select G.726LE encoding tag from sample bit width

    au_write_header() looked up the AU encoding tag with ff_codec_get_tag(),
    which always returned the first AV_CODEC_ID_ADPCM_G726LE entry (23, 4-bit
    32 kbit/s) regardless of the stream bit width. Remuxing 16, 24 or
    40 kbit/s G.726LE into AU wrote encoding 23, so reopening the file read
    it back as 4-bit 32 kbit/s with the wrong duration.

    Select the tag from bits_per_coded_sample, falling back to bit_rate,
    sample_rate and channel count when bits_per_coded_sample is unset: 25 for
    3-bit, 23 for 4-bit, 26 for 5-bit, and the existing '7262' tag (with a
    warning, since Sun AU defines no standard 2-bit code) for 2-bit. Reject
    other widths.

    Use overflow-safe rescaling to derive the per-channel width from the total
    bitrate, preserving nearest-integer rounding.

    Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/25401
    Signed-off-by: Jun Zhao <barryjzhao@tencent.com>

diff --git a/libavformat/au.c b/libavformat/au.c
index 2244995825..5382f8b813 100644
--- a/libavformat/au.c
+++ b/libavformat/au.c
@@ -32,6 +32,7 @@
 #include "libavutil/bprint.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
+#include "libavutil/mathematics.h"
 #include "avformat.h"
 #include "demux.h"
 #include "internal.h"
@@ -284,6 +285,46 @@ static int au_get_annotations(AVFormatContext *s, AVBPrint *annotations)
     return av_bprint_is_complete(annotations) ? 0 : AVERROR(ENOMEM);
 }

+/* Sun encodings 25, 23 and 26 are 3-, 4- and 5-bit G.726. There is no Sun
+ * number for 2-bit G.726; '7262' is the private tag the demuxer reads. */
+static int au_g726le_tag(AVFormatContext *s, AVCodecParameters *par)
+{
+    int64_t bps = par->bits_per_coded_sample;
+
+    if (bps <= 0) {
+        if (par->bit_rate <= 0 || par->sample_rate <= 0 ||
+            par->ch_layout.nb_channels <= 0) {
+            av_log(s, AV_LOG_ERROR, "Cannot determine G.726LE bit width\n");
+            return AVERROR(EINVAL);
+        }
+        bps = av_rescale(par->bit_rate, 1,
+                         (int64_t)par->sample_rate * par->ch_layout.nb_channels);
+    }
+
+    switch (bps) {
+    case 2:
+        av_log(s, AV_LOG_WARNING,
+               "Sun AU has no standard encoding for 2-bit G.726LE; "
+               "writing non-standard '7262' tag\n");
+        par->codec_tag = MKBETAG('7', '2', '6', '2');
+        break;
+    case 3:
+        par->codec_tag = 25;
+        break;
+    case 4:
+        par->codec_tag = 23;
+        break;
+    case 5:
+        par->codec_tag = 26;
+        break;
+    default:
+        av_log(s, AV_LOG_ERROR,
+               "Unsupported G.726LE bit width %"PRId64"\n", bps);
+        return AVERROR(EINVAL);
+    }
+    return 0;
+}
+
 static int au_write_header(AVFormatContext *s)
 {
     int ret;
@@ -292,10 +333,16 @@ static int au_write_header(AVFormatContext *s)
     AVCodecParameters *par = s->streams[0]->codecpar;
     AVBPrint annotations;

-    par->codec_tag = ff_codec_get_tag(codec_au_tags, par->codec_id);
-    if (!par->codec_tag) {
-        av_log(s, AV_LOG_ERROR, "unsupported codec\n");
-        return AVERROR(EINVAL);
+    if (par->codec_id == AV_CODEC_ID_ADPCM_G726LE) {
+        ret = au_g726le_tag(s, par);
+        if (ret < 0)
+            return ret;
+    } else {
+        par->codec_tag = ff_codec_get_tag(codec_au_tags, par->codec_id);
+        if (!par->codec_tag) {
+            av_log(s, AV_LOG_ERROR, "unsupported codec\n");
+            return AVERROR(EINVAL);
+        }
     }

     av_bprint_init(&annotations, 0, INT_MAX - 24);