PR #22501 opened by zsien URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22501 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22501.patch
Parse OH_MD_KEY_VIDEO_NATIVE_BUFFER_FORMAT from decoder output format metadata and map it to FFmpeg pixel formats, so 10-bit outputs can be exposed as P010LE instead of remaining NV12. Also adjust P010 stride handling in sw buffer wrapping by converting byte stride to pixel width before calling av_image_fill_linesizes(). Signed-off-by: Que Zhiyong <[email protected]> >From ffd69d7762ddc3420cfa94fd3403b9228c191d15 Mon Sep 17 00:00:00 2001 From: Que Zhiyong <[email protected]> Date: Sat, 14 Mar 2026 23:28:40 +0800 Subject: [PATCH] avcodec/ohdec: Resolve native buffer format for SW output Parse OH_MD_KEY_VIDEO_NATIVE_BUFFER_FORMAT from decoder output format metadata and map it to FFmpeg pixel formats, so 10-bit outputs can be exposed as P010LE instead of remaining NV12. Also adjust P010 stride handling in sw buffer wrapping by converting byte stride to pixel width before calling av_image_fill_linesizes(). Signed-off-by: Que Zhiyong <[email protected]> --- libavcodec/ohcodec.c | 16 +++++++++++++ libavcodec/ohcodec.h | 3 +++ libavcodec/ohdec.c | 54 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/libavcodec/ohcodec.c b/libavcodec/ohcodec.c index f8a6faaba5..b1cfc340ff 100644 --- a/libavcodec/ohcodec.c +++ b/libavcodec/ohcodec.c @@ -69,6 +69,22 @@ enum AVPixelFormat ff_oh_pix_to_ff_pix(OH_AVPixelFormat oh_pix) return AV_PIX_FMT_NONE; } +enum AVPixelFormat +ff_oh_native_buffer_to_ff_pix(OH_NativeBuffer_Format native_buffer_format) +{ + switch (native_buffer_format) { + case NATIVEBUFFER_PIXEL_FMT_YCBCR_420_SP: + return AV_PIX_FMT_NV12; + case NATIVEBUFFER_PIXEL_FMT_YCRCB_420_SP: + return AV_PIX_FMT_NV21; + case NATIVEBUFFER_PIXEL_FMT_YCBCR_P010: + case NATIVEBUFFER_PIXEL_FMT_YCRCB_P010: + return AV_PIX_FMT_P010LE; + default: + return AV_PIX_FMT_NONE; + } +} + int ff_oh_pix_from_ff_pix(enum AVPixelFormat pix) { for (size_t i = 0; i < FF_ARRAY_ELEMS(oh_pix_map); i++) diff --git a/libavcodec/ohcodec.h b/libavcodec/ohcodec.h index 074747247b..82bec80d97 100644 --- a/libavcodec/ohcodec.h +++ b/libavcodec/ohcodec.h @@ -25,6 +25,7 @@ #include <multimedia/player_framework/native_avcodec_base.h> #include <multimedia/player_framework/native_averrors.h> #include <multimedia/player_framework/native_avformat.h> +#include <native_buffer/buffer_common.h> #include "libavutil/pixfmt.h" @@ -52,6 +53,8 @@ static inline const char *ff_oh_mime(enum AVCodecID codec_id, void *log) } enum AVPixelFormat ff_oh_pix_to_ff_pix(OH_AVPixelFormat oh_pix); +enum AVPixelFormat +ff_oh_native_buffer_to_ff_pix(OH_NativeBuffer_Format native_buffer_format); int ff_oh_pix_from_ff_pix(enum AVPixelFormat pix); #endif diff --git a/libavcodec/ohdec.c b/libavcodec/ohdec.c index 943b027681..bc1700354a 100644 --- a/libavcodec/ohdec.c +++ b/libavcodec/ohdec.c @@ -30,6 +30,7 @@ #include "libavutil/mem.h" #include "libavutil/opt.h" #include "libavutil/refstruct.h" +#include "libavutil/pixdesc.h" #include "libavutil/thread.h" #include "avcodec.h" @@ -85,6 +86,25 @@ typedef struct OHCodecBuffer { OH_AVCodec **dec_ref; ///< RefStruct reference } OHCodecBuffer; +static enum AVPixelFormat +oh_decode_resolve_pix_fmt(AVCodecContext *avctx, + OH_NativeBuffer_Format native_buffer_format) +{ + enum AVPixelFormat base_pix_fmt = avctx->pix_fmt; + enum AVPixelFormat pix_fmt = + ff_oh_native_buffer_to_ff_pix(native_buffer_format); + + if (pix_fmt == AV_PIX_FMT_NONE || pix_fmt == base_pix_fmt) + return base_pix_fmt; + + av_log(avctx, AV_LOG_INFO, + "Using decoder output native buffer format %d, resolve %s -> %s\n", + native_buffer_format, av_get_pix_fmt_name(base_pix_fmt), + av_get_pix_fmt_name(pix_fmt)); + + return pix_fmt; +} + static void oh_decode_release(AVRefStructOpaque unused, void *obj) { OH_AVCodec **decp = obj; @@ -251,13 +271,22 @@ static void oh_decode_on_stream_changed(OH_AVCodec *codec, OH_AVFormat *format, */ if (s->output_to_window) avctx->pix_fmt = AV_PIX_FMT_OHCODEC; - else + else { + int32_t native_buffer_format; + avctx->pix_fmt = ff_oh_pix_to_ff_pix(s->pix_fmt); - // Check whether this pixel format is supported - if (avctx->pix_fmt == AV_PIX_FMT_NONE) { - av_log(avctx, AV_LOG_ERROR, "Unsupported OH_AVPixelFormat %d\n", - n); - goto out; + if (OH_AVFormat_GetIntValue(format, + OH_MD_KEY_VIDEO_NATIVE_BUFFER_FORMAT, + &native_buffer_format)) + avctx->pix_fmt = oh_decode_resolve_pix_fmt( + avctx, (OH_NativeBuffer_Format)native_buffer_format); + + // Check whether this pixel format is supported + if (avctx->pix_fmt == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Unsupported OH_AVPixelFormat %d\n", + s->pix_fmt); + goto out; + } } } else { av_log(avctx, AV_LOG_ERROR, "Failed to get pixel format\n"); @@ -511,7 +540,18 @@ static int oh_decode_wrap_sw_buffer(AVCodecContext *avctx, AVFrame *frame, uint8_t *src[4] = {0}; int src_linesizes[4] = {0}; - ret = av_image_fill_linesizes(src_linesizes, frame->format, s->stride); + int source_width = s->stride; + if (frame->format == AV_PIX_FMT_P010LE) { + if (s->stride & 1) { + av_log(avctx, AV_LOG_ERROR, + "Invalid P010 stride %d, expected even byte stride\n", + s->stride); + return AVERROR(EINVAL); + } + source_width = s->stride / 2; + } + + ret = av_image_fill_linesizes(src_linesizes, frame->format, source_width); if (ret < 0) return ret; ret = av_image_fill_pointers(src, frame->format, s->slice_height, p, -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
