Browse code

vdpau: add helper for surface chroma type and size

Since the VDPAU pixel format does not distinguish between different
VDPAU video surface chroma types, we need another way to pass this
data to the application.

Originally VDPAU in libavcodec only supported decoding to 8-bits YUV
with 4:2:0 chroma sampling. Correspondingly, applications assumed that
libavcodec expected VDP_CHROMA_TYPE_420 video surfaces for output.
However some of the new HEVC profiles proposed for addition to VDPAU
would require different depth and/or sampling:
http://lists.freedesktop.org/archives/vdpau/2014-July/000167.html
...as would lossless AVC profiles:
http://lists.freedesktop.org/archives/vdpau/2014-November/000241.html

To preserve backward binary compatibility with existing applications,
a new av_vdpau_bind_context() flag is introduced in a further change.

Signed-off-by: Rémi Denis-Courmont <remi@remlab.net>
Signed-off-by: Anton Khirnov <anton@khirnov.net>

Rémi Denis-Courmont authored on 2014/12/20 02:15:09
Showing 4 changed files
... ...
@@ -13,6 +13,9 @@ libavutil:     2014-08-09
13 13
 
14 14
 API changes, most recent first:
15 15
 
16
+201x-xx-xx - xxxxxxx - lavc 56.10.0 - vdpau.h
17
+  Add av_vdpau_get_surface_parameters().
18
+
16 19
 201x-xx-xx - xxxxxxx - lavc 56.9.0 - avcodec.h
17 20
   Add AV_HWACCEL_FLAG_ALLOW_HIGH_DEPTH flag to av_vdpau_bind_context().
18 21
 
... ...
@@ -64,6 +64,46 @@ static int vdpau_error(VdpStatus status)
64 64
     }
65 65
 }
66 66
 
67
+int av_vdpau_get_surface_parameters(AVCodecContext *avctx,
68
+                                    VdpChromaType *type,
69
+                                    uint32_t *width, uint32_t *height)
70
+{
71
+    VdpChromaType t;
72
+    uint32_t w = avctx->coded_width;
73
+    uint32_t h = avctx->coded_height;
74
+
75
+    /* See <vdpau/vdpau.h> for per-type alignment constraints. */
76
+    switch (avctx->sw_pix_fmt) {
77
+    case AV_PIX_FMT_YUV420P:
78
+    case AV_PIX_FMT_YUVJ420P:
79
+        t = VDP_CHROMA_TYPE_420;
80
+        w = (w + 1) & ~1;
81
+        h = (h + 3) & ~3;
82
+        break;
83
+    case AV_PIX_FMT_YUV422P:
84
+    case AV_PIX_FMT_YUVJ422P:
85
+        t = VDP_CHROMA_TYPE_422;
86
+        w = (w + 1) & ~1;
87
+        h = (h + 1) & ~1;
88
+        break;
89
+    case AV_PIX_FMT_YUV444P:
90
+    case AV_PIX_FMT_YUVJ444P:
91
+        t = VDP_CHROMA_TYPE_444;
92
+        h = (h + 1) & ~1;
93
+        break;
94
+    default:
95
+        return AVERROR(ENOSYS);
96
+    }
97
+
98
+    if (type)
99
+        *type = t;
100
+    if (width)
101
+        *width = w;
102
+    if (height)
103
+        *height = h;
104
+    return 0;
105
+}
106
+
67 107
 int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
68 108
                          int level)
69 109
 {
... ...
@@ -76,9 +116,9 @@ int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
76 76
     VdpStatus status;
77 77
     VdpBool supported;
78 78
     uint32_t max_level, max_mb, max_width, max_height;
79
-    /* See vdpau/vdpau.h for alignment constraints. */
80
-    uint32_t width  = (avctx->coded_width + 1) & ~1;
81
-    uint32_t height = (avctx->coded_height + 3) & ~3;
79
+    VdpChromaType type;
80
+    uint32_t width;
81
+    uint32_t height;
82 82
 
83 83
     vdctx->width            = UINT32_MAX;
84 84
     vdctx->height           = UINT32_MAX;
... ...
@@ -99,6 +139,9 @@ int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
99 99
     else if (level < 0)
100 100
         return AVERROR(ENOTSUP);
101 101
 
102
+    if (av_vdpau_get_surface_parameters(avctx, &type, &width, &height))
103
+        return AVERROR(ENOSYS);
104
+
102 105
     status = vdctx->get_proc_address(vdctx->device,
103 106
                                      VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES,
104 107
                                      &func);
... ...
@@ -107,7 +150,7 @@ int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
107 107
     else
108 108
         surface_query_caps = func;
109 109
 
110
-    status = surface_query_caps(vdctx->device, VDP_CHROMA_TYPE_420, &supported,
110
+    status = surface_query_caps(vdctx->device, type, &supported,
111 111
                                 &max_width, &max_height);
112 112
     if (status != VDP_STATUS_OK)
113 113
         return vdpau_error(status);
... ...
@@ -151,6 +151,26 @@ int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device,
151 151
                           VdpGetProcAddress *get_proc_address, unsigned flags);
152 152
 
153 153
 /**
154
+ * Gets the parameters to create an adequate VDPAU video surface for the codec
155
+ * context using VDPAU hardware decoding acceleration.
156
+ *
157
+ * @note Behavior is undefined if the context was not successfully bound to a
158
+ * VDPAU device using av_vdpau_bind_context().
159
+ *
160
+ * @param avctx the codec context being used for decoding the stream
161
+ * @param type storage space for the VDPAU video surface chroma type
162
+ *              (or NULL to ignore)
163
+ * @param width storage space for the VDPAU video surface pixel width
164
+ *              (or NULL to ignore)
165
+ * @param height storage space for the VDPAU video surface pixel height
166
+ *              (or NULL to ignore)
167
+ *
168
+ * @return 0 on success, a negative AVERROR code on failure.
169
+ */
170
+int av_vdpau_get_surface_parameters(AVCodecContext *avctx, VdpChromaType *type,
171
+                                    uint32_t *width, uint32_t *height);
172
+
173
+/**
154 174
  * Allocate an AVVDPAUContext.
155 175
  *
156 176
  * @return Newly-allocated AVVDPAUContext or NULL on failure.
... ...
@@ -29,7 +29,7 @@
29 29
 #include "libavutil/version.h"
30 30
 
31 31
 #define LIBAVCODEC_VERSION_MAJOR 56
32
-#define LIBAVCODEC_VERSION_MINOR  9
32
+#define LIBAVCODEC_VERSION_MINOR 10
33 33
 #define LIBAVCODEC_VERSION_MICRO  0
34 34
 
35 35
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \