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]

Reply via email to