Some devices (some phones, apparently) will support only this opaque
format. Of course this won't work with CLI, because copying data
directly is not supported.

Automatic frame allocation (setting AVCodecContext.hw_device_ctx) does
not support this mode, even if it's the only supported mode. But since
opaque surfaces are generally less useful, that's probably ok.
---
 libavcodec/dxva2.c            | 13 +++++++++++--
 libavutil/hwcontext_d3d11va.c | 12 ++++++++++--
 libavutil/hwcontext_d3d11va.h |  4 ++++
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
index 23d96687dc..79b77150d0 100644
--- a/libavcodec/dxva2.c
+++ b/libavcodec/dxva2.c
@@ -389,19 +389,28 @@ static int 
d3d11va_get_decoder_configuration(AVCodecContext *avctx,
     return ret;
 }
 
+static DXGI_FORMAT d3d11va_map_sw_to_hw_format(enum AVPixelFormat pix_fmt)
+{
+    switch (pix_fmt) {
+    case AV_PIX_FMT_NV12:       return DXGI_FORMAT_NV12;
+    case AV_PIX_FMT_P010:       return DXGI_FORMAT_P010;
+    case AV_PIX_FMT_YUV420P:    return DXGI_FORMAT_420_OPAQUE;
+    default:                    return DXGI_FORMAT_UNKNOWN;
+    }
+}
+
 static int d3d11va_create_decoder(AVCodecContext *avctx)
 {
     FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
     GUID *guid_list;
     unsigned guid_count, i;
     GUID decoder_guid;
-    DXGI_FORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
-                                 DXGI_FORMAT_P010 : DXGI_FORMAT_NV12;
     D3D11_VIDEO_DECODER_DESC desc = { 0 };
     D3D11_VIDEO_DECODER_CONFIG config;
     AVHWFramesContext *frames_ctx = (AVHWFramesContext 
*)avctx->hw_frames_ctx->data;
     AVD3D11VADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
     AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx;
+    DXGI_FORMAT surface_format = 
d3d11va_map_sw_to_hw_format(frames_ctx->sw_format);
     D3D11_TEXTURE2D_DESC texdesc;
     HRESULT hr;
     int ret;
diff --git a/libavutil/hwcontext_d3d11va.c b/libavutil/hwcontext_d3d11va.c
index b0d04d03c9..4e3c0c00e0 100644
--- a/libavutil/hwcontext_d3d11va.c
+++ b/libavutil/hwcontext_d3d11va.c
@@ -51,8 +51,11 @@ static const struct {
     DXGI_FORMAT d3d_format;
     enum AVPixelFormat pix_fmt;
 } supported_formats[] = {
-    { DXGI_FORMAT_NV12, AV_PIX_FMT_NV12 },
-    { DXGI_FORMAT_P010, AV_PIX_FMT_P010 },
+    { DXGI_FORMAT_NV12,         AV_PIX_FMT_NV12 },
+    { DXGI_FORMAT_P010,         AV_PIX_FMT_P010 },
+    // Special opaque formats. The pix_fmt is merely a place holder, as the
+    // opaque format cannot be accessed directly.
+    { DXGI_FORMAT_420_OPAQUE,   AV_PIX_FMT_YUV420P },
 };
 
 static void d3d11va_default_lock(void *ctx)
@@ -238,6 +241,7 @@ static int d3d11va_transfer_get_formats(AVHWFramesContext 
*ctx,
                                         enum AVHWFrameTransferDirection dir,
                                         enum AVPixelFormat **formats)
 {
+    D3D11VAFramesContext *s = ctx->internal->priv;
     enum AVPixelFormat *fmts;
 
     fmts = av_malloc_array(2, sizeof(*fmts));
@@ -247,6 +251,10 @@ static int d3d11va_transfer_get_formats(AVHWFramesContext 
*ctx,
     fmts[0] = ctx->sw_format;
     fmts[1] = AV_PIX_FMT_NONE;
 
+    // Don't signal support for opaque formats. Actual access would fail.
+    if (s->format == DXGI_FORMAT_420_OPAQUE)
+        fmts[0] = AV_PIX_FMT_NONE;
+
     *formats = fmts;
 
     return 0;
diff --git a/libavutil/hwcontext_d3d11va.h b/libavutil/hwcontext_d3d11va.h
index 676349d7b8..d41451580e 100644
--- a/libavutil/hwcontext_d3d11va.h
+++ b/libavutil/hwcontext_d3d11va.h
@@ -26,6 +26,10 @@
  * The default pool implementation will be fixed-size if initial_pool_size is
  * set (and allocate elements from an array texture). Otherwise it will 
allocate
  * individual textures. Be aware that decoding requires a single array texture.
+ *
+ * Using sw_format==AV_PIX_FMT_YUV420P has special semantics, and maps to
+ * DXGI_FORMAT_420_OPAQUE. av_hwframe_transfer_data() is not supported for
+ * this format. Refer to MSDN for details.
  */
 
 #include <d3d11.h>
-- 
2.11.0

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to