Commit 379f568b5c for ffmpeg

commit 379f568b5cc0f0a0b57dfed03efbc326a107d90f
Author: Zhao Zhili <quinkblack@foxmail.com>
Date:   Tue Oct 13 19:15:39 2026 +0800

    avcodec/mediacodecdec_common: ignore stream info of the initial format

    Until the codec signals INFO_OUTPUT_FORMAT_CHANGED, MediaCodec returns
    the output format set up at configure time. The decoder parsed that
    format right after start() and copied its crop rectangle, display size
    and color description into the codec context, although at that point
    the codec has not decoded anything and these fields hold its defaults.
    For a 1920x1080 HLG stream, c2.xring.hevc.decoder reports the crop
    rectangle Rect(0, 0, 175, 143) and BT.601 SDR color there, and MediaTek
    decoders report rectangles such as Rect(0, 0, 318, 238). Callers reading
    the codec context after avcodec_open2() got 176x144 or 319x239 and a
    wrong color description instead of the stream properties.

    Keep the values set by the caller until the codec signals a format
    change. The pixel format is still taken from the initial format, as it
    reflects the configuration. If the first output buffer arrives without
    a format change, the initial format describes the decoded frames and is
    applied at that point.

diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c
index 0cb9c092d7..fda5a3d9ce 100644
--- a/libavcodec/mediacodecdec_common.c
+++ b/libavcodec/mediacodecdec_common.c
@@ -597,6 +597,17 @@ static int mediacodec_dec_parse_video_format(AVCodecContext *avctx, MediaCodecDe
         goto fail;
     }

+    /* Until the codec signals a format change, the output format is the one
+     * set up by configure(), before the codec has seen any input. Its crop
+     * rectangle, display size and color description do not describe the
+     * stream, so keep the values set by the caller. The fields above
+     * describe the configured output buffers and always apply.
+     */
+    if (!s->has_output_format) {
+        av_freep(&format);
+        return 0;
+    }
+
     /* Optional fields */
     AMEDIAFORMAT_GET_INT32(s->crop_top,    "crop-top",    0);
     AMEDIAFORMAT_GET_INT32(s->crop_bottom, "crop-bottom", 0);
@@ -1028,6 +1039,19 @@ int ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecDecContext *s,
         }

         if (info.size) {
+            if (s->format && !s->has_output_format) {
+                /* No format change preceded the first output buffer, so the
+                 * initial output format describes the decoded frames. Only
+                 * video fetches that format at init.
+                 */
+                s->has_output_format = true;
+                if ((ret = mediacodec_dec_parse_format(avctx, s)) < 0) {
+                    av_log(avctx, AV_LOG_ERROR, "Failed to parse output format\n");
+                    ff_AMediaCodec_releaseOutputBuffer(codec, index, 0);
+                    return ret;
+                }
+            }
+
             if (s->surface) {
                 if ((ret = mediacodec_wrap_hw_buffer(avctx, s, index, &info, frame)) < 0) {
                     av_log(avctx, AV_LOG_ERROR, "Failed to wrap MediaCodec buffer\n");
@@ -1066,6 +1090,7 @@ int ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecDecContext *s,
         }

         s->format = ff_AMediaCodec_getOutputFormat(codec);
+        s->has_output_format = true;
         if (!s->format) {
             av_log(avctx, AV_LOG_ERROR, "Failed to get output format\n");
             return AVERROR_EXTERNAL;
diff --git a/libavcodec/mediacodecdec_common.h b/libavcodec/mediacodecdec_common.h
index 0ab29036bd..15a35390e0 100644
--- a/libavcodec/mediacodecdec_common.h
+++ b/libavcodec/mediacodecdec_common.h
@@ -44,6 +44,11 @@ typedef struct MediaCodecDecContext {

     FFAMediaCodec *codec;
     FFAMediaFormat *format;
+    /* Set once the codec has signalled an output format or produced output.
+     * Until then format is the one set up at configure time and its stream
+     * info is not applied.
+     */
+    bool has_output_format;

     void *surface;