1
0
mirror of https://git.ffmpeg.org/ffmpeg.git synced 2026-10-24 02:09:03 +03:00

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.
This commit is contained in:
Zhao Zhili
2026-10-13 19:15:39 +08:00
committed by Zhao Zhili
parent 23045b25ed
commit 379f568b5c
2 changed files with 30 additions and 0 deletions

View File

@@ -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;

View File

@@ -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;