什么快递比较快| 高血压中医叫什么病| 马克华菲是什么档次| beko是什么牌子| 大便有血是什么原因男性| 脚环肿是什么原因引起的| 青霉素是什么| 天蝎座有什么特点| 女人脸黄是什么原因该怎么调理| 什么是快闪| 葡萄糖偏高是什么原因| 穗字五行属什么| 品牌是什么意思| 颈动脉彩超能查出什么| 坤宁宫是干什么的| 中性粒细胞比率偏高是什么意思| 什么是靶向治疗| 火加同念什么| 痣长在什么地方不好| 孩子血铅高有什么症状| 老妹是什么意思| 好汉不吃眼前亏是什么意思| dna是什么意思| 过敏擦什么药膏好得快| 透明质酸钠是什么东西| 碘伏遇到什么会变白| 腰疼吃什么药最有效| wba是什么意思| 什么什么若狂| 封闭针是什么药| 人生苦短是什么意思| 梦见别人家盖房子是什么意思| 子宫在什么位置| 喝咖啡对身体有什么好处| 梦见着火了是什么征兆| classic是什么意思| 下午5点是什么时辰| 张学友属什么生肖| 伤食是什么意思| 血红蛋白低是什么原因| 什么口红好| qid医学上是什么意思| 打嗝吃什么药| 65年属什么| 纳差什么意思| 舌头开裂吃什么药| 超声科是什么科室| 甲片是什么| 血小板低吃什么水果好| 跳跳糖为什么会跳| 梦到狗是什么意思| 财评是什么意思| 转念是什么意思| 高铁上什么东西不能带| 氧化剂是什么| 洋溢着什么样的笑容| cpr是什么意思| 干你什么事| 祛痣挂什么科| 抑郁症是什么意思| 头头是道什么意思| 查脂肪肝挂什么科室| 助产士一般什么学历| 黄疸是什么| 死海为什么叫死海| 尿液分析是检查什么| 胃胀胃不消化吃什么药| ACEI是什么药| 风代表什么数字| 中药天龙又叫什么| 88年属什么的| 芯字五行属什么| 说三道四的意思是什么| 加拿大现在什么季节| 什么是双重人格| 心衰病人吃什么食物好| 木薯是什么东西图片| pla是什么意思| 11点是什么时辰| 县级以上医院是指什么| 脏器灰阶立体成像是检查什么的| 睡觉空调开什么模式| 很能睡觉是什么原因| outdoor是什么意思| 黏膜是什么意思| 5月30号是什么星座| 忤逆是什么意思| 五彩的什么| 盐吃多了有什么危害| 香菇炒什么菜好吃| 服兵役是什么意思| 乙肝两对半45阳性是什么意思| 琪字五行属什么| 刘五行属性是什么| 硒酵母胶囊对甲状腺的作用是什么| 美国今天是什么节日| 什么牌的笔记本电脑好| 为什么英文怎么说| 葛洲坝集团是什么级别| 孕检都检查什么项目| 看乳房挂什么科| 男人吃什么补肾壮阳效果最好| 百雀羚适合什么年龄段| 螺旋杆菌吃什么药| 何弃疗是什么意思| 便秘吃什么药见效快| 流产有什么症状| 鸡肉和什么菜搭配最好| 浸猪笼是什么意思| 扭捏是什么意思| 盆腔炎用什么药最好| 黄芪味道是什么味道| 去香港需要准备什么| 舌根部淋巴滤泡增生吃什么药| 送老师什么礼物好| 亲戚是什么意思| 食品级pp材质是什么| 肚子痛拉稀吃什么药| 手麻木是什么引起的| 咽炎雾化用什么药最好| 父亲节做什么礼物好| 阑尾炎术后吃什么| 硼砂是什么东西| 喝碳酸饮料有什么危害| 吃什么补气| 天为什么会下雨| 尿红细胞阳性什么意思| 喉咙嘶哑吃什么药| 60岁男人喜欢什么样的女人| 胰腺的作用和功能是什么| 免疫力下降吃什么好| 尖湿锐吃什么药最好| 布拉吉是什么| ITIB跟薇娅什么关系| 标准偏差是什么意思| 尿道感染看什么科| 大便发绿色是什么原因| 六月初九是什么日子| 什么的糯米| 梦见好多蛇是什么意思| 麦冬是什么| 浓缩汁是什么意思| 上午12点是什么时候| 吃什么会引起尿酸高| 天气热吃什么好| 自渎什么意思| 吃狗肉有什么危害| 1997年属牛是什么命| 拉肚子去医院挂什么科| 七月一号是什么节| 狗是什么生肖| 醉酒当歌什么意思| 处女座什么性格| 什么是风湿热| 检查hpv需要注意什么提前注意什么| 平板支撑练什么| 梦见自己嫁人了预示着什么| 手脚脱皮吃什么维生素| 凌五行属性是什么| 奶瓶pp和ppsu有什么区别| 羊球是什么| 打坐有什么好处| 口业是什么意思| 手上起小水泡痒是什么原因| 湿气重可以吃什么水果| 胃窦小弯是什么意思| 直肠疾病都有什么症状| 韧带是什么样子图片| 喝什么茶去湿气| 越位是什么意思| 今年流行什么发型女| 哺乳期吃什么下奶| 为什么会有肾结石| 彩金是什么材质| 男人气血不足吃什么药| 血止不住是什么原因| 做梦梦见马是什么意思| 小苏打和食用碱有什么区别| 叶酸什么时间段吃最好| 什么叫宫腔粘连| 什么叫五音不全| 怀孕10天左右有什么症状| 清明节在什么时候| 30周做什么检查| 微信上面有个耳朵是什么意思| 海绵体是什么| 射手男和什么星座最配| 骨折吃什么药好得快| 橄榄色是什么颜色| 18年属什么生肖| 膝盖不好的人适合什么运动| 初恋什么意思| electrolux是什么牌子| 2001年属什么生肖| 什么数字最听话| 黄芪泡水喝有什么好处| 尿里红细胞高什么原因| 八月十七是什么星座| 金枝玉叶什么生肖| 上嘴唇上有痣代表什么| 圣罗兰是什么档次| 骨相美是什么意思| 胰腺炎吃什么药见效快| 干部是什么意思| 唯女子与小人难养也什么意思| 开车撞死猫有什么预兆| 阴道干涩用什么药| 为什么不来大姨妈也没有怀孕| 丝瓜有什么功效| 百依百顺是什么生肖| 视功能是什么| 过敏性鼻炎吃什么药好| 脚后跟痛是什么问题| 家里飞蛾多是什么原因| 孕晚期血糖高对胎儿有什么影响| 女人喝什么茶好| 龟头有红点用什么药| 四五行属什么| g750和au750有什么区别| 胰腺炎是什么原因引起的| 呃是什么意思| 什么情况下会怀孕| 梦见自己拉了很多屎是什么意思| 肠管积气是什么原因| 什么叫腔梗| 喉结下面是什么部位| 津津有味什么意思| 腰间盘突出有什么好的治疗方法| her是什么意思| 宵夜和夜宵有什么区别| 人造石是什么材料做的| 吃完饭就想睡觉是什么原因| 最近我和你都有一样的心情什么歌| 胎儿左肾盂分离是什么意思| 黄豆加什么打豆浆好喝又营养| 十余年是什么意思| 地球是什么意思| 去减一笔变成什么字| 一个厂一个人念什么| 蚂蚁喜欢吃什么食物| quest是什么车| 什么是伴手礼| 清朝是什么时候灭亡的| 腰底部疼痛跟什么病有关| 为什么做着做着就软了| 小孩子注意力不集中是什么原因| cpi什么意思| 喝苦荞茶有什么好处和坏处| 中国古代四大发明是什么| 人为什么会觉得累| 什么是犯太岁| 脑部缺氧有什么症状| 为什么十二生肖老鼠排第一| 施华洛世奇什么档次| 喜筵和喜宴是什么意思| 业力是什么意思| 女性喝什么利尿最快| 抽搐是什么原因引起的| 剖腹产后可以吃什么水果| 新股配号数量是什么意思| 漱口杯什么材质好| 胖头鱼又叫什么鱼| 玉竹长什么样子| 此物非彼物是什么意思| 百度

第九届中国曲艺节在天津开幕


Directory: ../../../ffmpeg/
File: src/libavutil/hwcontext_vaapi.c
Date: 2025-08-04 00:43:16
Exec Total Coverage
Lines: 0 911 0.0%
Functions: 0 33 0.0%
Branches: 0 446 0.0%

Line Branch Exec Source
1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "config.h"
20
21 #if HAVE_VAAPI_WIN32
22 # include <windows.h>
23 #define COBJMACROS
24 # include <initguid.h>
25 # include <dxgi1_2.h>
26 # include "compat/w32dlfcn.h"
27 # include <va/va_win32.h>
28 typedef HRESULT (WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
29 #endif
30 #if HAVE_VAAPI_X11
31 # include <va/va_x11.h>
32 #endif
33 #if HAVE_VAAPI_DRM
34 # include <va/va_drm.h>
35 #endif
36
37 #if CONFIG_LIBDRM
38 # include <va/va_drmcommon.h>
39 # include <xf86drm.h>
40 # include <drm_fourcc.h>
41 # ifndef DRM_FORMAT_MOD_INVALID
42 # define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
43 # endif
44 #endif
45
46 #include <fcntl.h>
47 #if HAVE_UNISTD_H
48 # include <unistd.h>
49 #endif
50
51
52 #include "avassert.h"
53 #include "buffer.h"
54 #include "common.h"
55 #include "hwcontext.h"
56 #include "hwcontext_drm.h"
57 #include "hwcontext_internal.h"
58 #include "hwcontext_vaapi.h"
59 #include "mem.h"
60 #include "pixdesc.h"
61 #include "pixfmt.h"
62
63
64 typedef struct VAAPIDevicePriv {
65 #if HAVE_VAAPI_X11
66 Display *x11_display;
67 #endif
68
69 int drm_fd;
70 } VAAPIDevicePriv;
71
72 typedef struct VAAPISurfaceFormat {
73 enum AVPixelFormat pix_fmt;
74 VAImageFormat image_format;
75 } VAAPISurfaceFormat;
76
77 typedef struct VAAPIDeviceContext {
78 /**
79 * The public AVVAAPIDeviceContext. See hwcontext_vaapi.h for it.
80 */
81 AVVAAPIDeviceContext p;
82
83 // Surface formats which can be used with this device.
84 VAAPISurfaceFormat *formats;
85 int nb_formats;
86 } VAAPIDeviceContext;
87
88 typedef struct VAAPIFramesContext {
89 /**
90 * The public AVVAAPIFramesContext. See hwcontext_vaapi.h for it.
91 */
92 AVVAAPIFramesContext p;
93
94 // Surface attributes set at create time.
95 VASurfaceAttrib *attributes;
96 int nb_attributes;
97 // RT format of the underlying surface (Intel driver ignores this anyway).
98 unsigned int rt_format;
99 // Whether vaDeriveImage works.
100 int derive_works;
101 // Caches whether VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 is unsupported for
102 // surface imports.
103 int prime_2_import_unsupported;
104 } VAAPIFramesContext;
105
106 typedef struct VAAPIMapping {
107 // Handle to the derived or copied image which is mapped.
108 VAImage image;
109 // The mapping flags actually used.
110 int flags;
111 } VAAPIMapping;
112
113 typedef struct VAAPIFormat {
114 unsigned int fourcc;
115 unsigned int rt_format;
116 enum AVPixelFormat pix_fmt;
117 int chroma_planes_swapped;
118 } VAAPIFormatDescriptor;
119
120 #define MAP(va, rt, av, swap_uv) { \
121 VA_FOURCC_ ## va, \
122 VA_RT_FORMAT_ ## rt, \
123 AV_PIX_FMT_ ## av, \
124 swap_uv, \
125 }
126 // The map fourcc <-> pix_fmt isn't bijective because of the annoying U/V
127 // plane swap cases. The frame handling below tries to hide these.
128 static const VAAPIFormatDescriptor vaapi_format_map[] = {
129 MAP(NV12, YUV420, NV12, 0),
130 #ifdef VA_FOURCC_I420
131 MAP(I420, YUV420, YUV420P, 0),
132 #endif
133 MAP(YV12, YUV420, YUV420P, 1),
134 MAP(IYUV, YUV420, YUV420P, 0),
135 MAP(422H, YUV422, YUV422P, 0),
136 #ifdef VA_FOURCC_YV16
137 MAP(YV16, YUV422, YUV422P, 1),
138 #endif
139 MAP(UYVY, YUV422, UYVY422, 0),
140 MAP(YUY2, YUV422, YUYV422, 0),
141 #ifdef VA_FOURCC_Y210
142 MAP(Y210, YUV422_10, Y210, 0),
143 #endif
144 #ifdef VA_FOURCC_Y212
145 MAP(Y212, YUV422_12, Y212, 0),
146 #endif
147 MAP(411P, YUV411, YUV411P, 0),
148 MAP(422V, YUV422, YUV440P, 0),
149 MAP(444P, YUV444, YUV444P, 0),
150 #ifdef VA_FOURCC_XYUV
151 MAP(XYUV, YUV444, VUYX, 0),
152 #endif
153 MAP(Y800, YUV400, GRAY8, 0),
154 #ifdef VA_FOURCC_P010
155 MAP(P010, YUV420_10BPP, P010, 0),
156 #endif
157 #ifdef VA_FOURCC_P012
158 MAP(P012, YUV420_12, P012, 0),
159 #endif
160 MAP(BGRA, RGB32, BGRA, 0),
161 MAP(BGRX, RGB32, BGR0, 0),
162 MAP(RGBA, RGB32, RGBA, 0),
163 MAP(RGBX, RGB32, RGB0, 0),
164 #ifdef VA_FOURCC_ABGR
165 MAP(ABGR, RGB32, ABGR, 0),
166 MAP(XBGR, RGB32, 0BGR, 0),
167 #endif
168 MAP(ARGB, RGB32, ARGB, 0),
169 MAP(XRGB, RGB32, 0RGB, 0),
170 #ifdef VA_FOURCC_X2R10G10B10
171 MAP(X2R10G10B10, RGB32_10, X2RGB10, 0),
172 #endif
173 #ifdef VA_FOURCC_Y410
174 // libva doesn't include a fourcc for XV30 and the driver only declares
175 // support for Y410, so we must fudge the mapping here.
176 MAP(Y410, YUV444_10, XV30, 0),
177 #endif
178 #ifdef VA_FOURCC_Y412
179 // libva doesn't include a fourcc for XV36 and the driver only declares
180 // support for Y412, so we must fudge the mapping here.
181 MAP(Y412, YUV444_12, XV36, 0),
182 #endif
183 };
184 #undef MAP
185
186 static const VAAPIFormatDescriptor *
187 vaapi_format_from_fourcc(unsigned int fourcc)
188 {
189 int i;
190 for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
191 if (vaapi_format_map[i].fourcc == fourcc)
192 return &vaapi_format_map[i];
193 return NULL;
194 }
195
196 static const VAAPIFormatDescriptor *
197 vaapi_format_from_pix_fmt(enum AVPixelFormat pix_fmt)
198 {
199 int i;
200 for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
201 if (vaapi_format_map[i].pix_fmt == pix_fmt)
202 return &vaapi_format_map[i];
203 return NULL;
204 }
205
206 static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc)
207 {
208 const VAAPIFormatDescriptor *desc;
209 desc = vaapi_format_from_fourcc(fourcc);
210 if (desc)
211 return desc->pix_fmt;
212 else
213 return AV_PIX_FMT_NONE;
214 }
215
216 static int vaapi_get_image_format(AVHWDeviceContext *hwdev,
217 enum AVPixelFormat pix_fmt,
218 VAImageFormat **image_format)
219 {
220 VAAPIDeviceContext *ctx = hwdev->hwctx;
221 int i;
222
223 for (i = 0; i < ctx->nb_formats; i++) {
224 if (ctx->formats[i].pix_fmt == pix_fmt) {
225 if (image_format)
226 *image_format = &ctx->formats[i].image_format;
227 return 0;
228 }
229 }
230 return AVERROR(ENOSYS);
231 }
232
233 static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev,
234 const void *hwconfig,
235 AVHWFramesConstraints *constraints)
236 {
237 VAAPIDeviceContext *ctx = hwdev->hwctx;
238 AVVAAPIDeviceContext *hwctx = &ctx->p;
239 const AVVAAPIHWConfig *config = hwconfig;
240 VASurfaceAttrib *attr_list = NULL;
241 VAStatus vas;
242 enum AVPixelFormat pix_fmt;
243 unsigned int fourcc;
244 int err, i, j, attr_count, pix_fmt_count;
245
246 if (config &&
247 !(hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES)) {
248 attr_count = 0;
249 vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id,
250 0, &attr_count);
251 if (vas != VA_STATUS_SUCCESS) {
252 av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: "
253 "%d (%s).\n", vas, vaErrorStr(vas));
254 err = AVERROR(ENOSYS);
255 goto fail;
256 }
257
258 attr_list = av_malloc(attr_count * sizeof(*attr_list));
259 if (!attr_list) {
260 err = AVERROR(ENOMEM);
261 goto fail;
262 }
263
264 vas = vaQuerySurfaceAttributes(hwctx->display, config->config_id,
265 attr_list, &attr_count);
266 if (vas != VA_STATUS_SUCCESS) {
267 av_log(hwdev, AV_LOG_ERROR, "Failed to query surface attributes: "
268 "%d (%s).\n", vas, vaErrorStr(vas));
269 err = AVERROR(ENOSYS);
270 goto fail;
271 }
272
273 pix_fmt_count = 0;
274 for (i = 0; i < attr_count; i++) {
275 switch (attr_list[i].type) {
276 case VASurfaceAttribPixelFormat:
277 fourcc = attr_list[i].value.value.i;
278 pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
279 if (pix_fmt != AV_PIX_FMT_NONE) {
280 ++pix_fmt_count;
281 } else {
282 // Something unsupported - ignore.
283 }
284 break;
285 case VASurfaceAttribMinWidth:
286 constraints->min_width = attr_list[i].value.value.i;
287 break;
288 case VASurfaceAttribMinHeight:
289 constraints->min_height = attr_list[i].value.value.i;
290 break;
291 case VASurfaceAttribMaxWidth:
292 constraints->max_width = attr_list[i].value.value.i;
293 break;
294 case VASurfaceAttribMaxHeight:
295 constraints->max_height = attr_list[i].value.value.i;
296 break;
297 }
298 }
299 if (pix_fmt_count == 0) {
300 // Nothing usable found. Presumably there exists something which
301 // works, so leave the set null to indicate unknown.
302 constraints->valid_sw_formats = NULL;
303 } else {
304 constraints->valid_sw_formats = av_malloc_array(pix_fmt_count + 1,
305 sizeof(pix_fmt));
306 if (!constraints->valid_sw_formats) {
307 err = AVERROR(ENOMEM);
308 goto fail;
309 }
310
311 for (i = j = 0; i < attr_count; i++) {
312 int k;
313
314 if (attr_list[i].type != VASurfaceAttribPixelFormat)
315 continue;
316 fourcc = attr_list[i].value.value.i;
317 pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
318
319 if (pix_fmt == AV_PIX_FMT_NONE)
320 continue;
321
322 for (k = 0; k < j; k++) {
323 if (constraints->valid_sw_formats[k] == pix_fmt)
324 break;
325 }
326
327 if (k == j)
328 constraints->valid_sw_formats[j++] = pix_fmt;
329 }
330 constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE;
331 }
332 } else {
333 // No configuration supplied.
334 // Return the full set of image formats known by the implementation.
335 constraints->valid_sw_formats = av_malloc_array(ctx->nb_formats + 1,
336 sizeof(pix_fmt));
337 if (!constraints->valid_sw_formats) {
338 err = AVERROR(ENOMEM);
339 goto fail;
340 }
341 for (i = j = 0; i < ctx->nb_formats; i++) {
342 int k;
343
344 for (k = 0; k < j; k++) {
345 if (constraints->valid_sw_formats[k] == ctx->formats[i].pix_fmt)
346 break;
347 }
348
349 if (k == j)
350 constraints->valid_sw_formats[j++] = ctx->formats[i].pix_fmt;
351 }
352
353 constraints->valid_sw_formats[j] = AV_PIX_FMT_NONE;
354 }
355
356 constraints->valid_hw_formats = av_malloc_array(2, sizeof(pix_fmt));
357 if (!constraints->valid_hw_formats) {
358 err = AVERROR(ENOMEM);
359 goto fail;
360 }
361 constraints->valid_hw_formats[0] = AV_PIX_FMT_VAAPI;
362 constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
363
364 err = 0;
365 fail:
366 av_freep(&attr_list);
367 return err;
368 }
369
370 static const struct {
371 const char *friendly_name;
372 const char *match_string;
373 unsigned int quirks;
374 } vaapi_driver_quirks_table[] = {
375 #if !VA_CHECK_VERSION(1, 0, 0)
376 // The i965 driver did not conform before version 2.0.
377 {
378 "Intel i965 (Quick Sync)",
379 "i965",
380 AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS,
381 },
382 #endif
383 {
384 "Intel iHD",
385 "ubit",
386 AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE,
387 },
388 {
389 "VDPAU wrapper",
390 "Splitted-Desktop Systems VDPAU backend for VA-API",
391 AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES,
392 },
393 };
394
395 static int vaapi_device_init(AVHWDeviceContext *hwdev)
396 {
397 VAAPIDeviceContext *ctx = hwdev->hwctx;
398 AVVAAPIDeviceContext *hwctx = &ctx->p;
399 VAImageFormat *image_list = NULL;
400 VAStatus vas;
401 const char *vendor_string;
402 int err, i, image_count;
403 enum AVPixelFormat pix_fmt;
404 unsigned int fourcc;
405
406 image_count = vaMaxNumImageFormats(hwctx->display);
407 if (image_count <= 0) {
408 err = AVERROR(EIO);
409 goto fail;
410 }
411 image_list = av_malloc(image_count * sizeof(*image_list));
412 if (!image_list) {
413 err = AVERROR(ENOMEM);
414 goto fail;
415 }
416 vas = vaQueryImageFormats(hwctx->display, image_list, &image_count);
417 if (vas != VA_STATUS_SUCCESS) {
418 err = AVERROR(EIO);
419 goto fail;
420 }
421
422 ctx->formats = av_malloc(image_count * sizeof(*ctx->formats));
423 if (!ctx->formats) {
424 err = AVERROR(ENOMEM);
425 goto fail;
426 }
427 ctx->nb_formats = 0;
428 for (i = 0; i < image_count; i++) {
429 fourcc = image_list[i].fourcc;
430 pix_fmt = vaapi_pix_fmt_from_fourcc(fourcc);
431 if (pix_fmt == AV_PIX_FMT_NONE) {
432 av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> unknown.\n",
433 fourcc);
434 } else {
435 av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> %s.\n",
436 fourcc, av_get_pix_fmt_name(pix_fmt));
437 ctx->formats[ctx->nb_formats].pix_fmt = pix_fmt;
438 ctx->formats[ctx->nb_formats].image_format = image_list[i];
439 ++ctx->nb_formats;
440 }
441 }
442
443 vendor_string = vaQueryVendorString(hwctx->display);
444 if (vendor_string)
445 av_log(hwdev, AV_LOG_VERBOSE, "VAAPI driver: %s.\n", vendor_string);
446
447 if (hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_USER_SET) {
448 av_log(hwdev, AV_LOG_VERBOSE, "Using quirks set by user (%#x).\n",
449 hwctx->driver_quirks);
450 } else {
451 // Detect the driver in use and set quirk flags if necessary.
452 hwctx->driver_quirks = 0;
453 if (vendor_string) {
454 for (i = 0; i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table); i++) {
455 if (strstr(vendor_string,
456 vaapi_driver_quirks_table[i].match_string)) {
457 av_log(hwdev, AV_LOG_VERBOSE, "Matched driver string "
458 "as known nonstandard driver \"%s\", setting "
459 "quirks (%#x).\n",
460 vaapi_driver_quirks_table[i].friendly_name,
461 vaapi_driver_quirks_table[i].quirks);
462 hwctx->driver_quirks |=
463 vaapi_driver_quirks_table[i].quirks;
464 break;
465 }
466 }
467 if (!(i < FF_ARRAY_ELEMS(vaapi_driver_quirks_table))) {
468 av_log(hwdev, AV_LOG_VERBOSE, "Driver not found in known "
469 "nonstandard list, using standard behaviour.\n");
470 }
471 } else {
472 av_log(hwdev, AV_LOG_VERBOSE, "Driver has no vendor string, "
473 "assuming standard behaviour.\n");
474 }
475 }
476
477 av_free(image_list);
478 return 0;
479 fail:
480 av_freep(&ctx->formats);
481 av_free(image_list);
482 return err;
483 }
484
485 static void vaapi_device_uninit(AVHWDeviceContext *hwdev)
486 {
487 VAAPIDeviceContext *ctx = hwdev->hwctx;
488
489 av_freep(&ctx->formats);
490 }
491
492 static void vaapi_buffer_free(void *opaque, uint8_t *data)
493 {
494 AVHWFramesContext *hwfc = opaque;
495 AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
496 VASurfaceID surface_id;
497 VAStatus vas;
498
499 surface_id = (VASurfaceID)(uintptr_t)data;
500
501 vas = vaDestroySurfaces(hwctx->display, &surface_id, 1);
502 if (vas != VA_STATUS_SUCCESS) {
503 av_log(hwfc, AV_LOG_ERROR, "Failed to destroy surface %#x: "
504 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
505 }
506 }
507
508 static AVBufferRef *vaapi_pool_alloc(void *opaque, size_t size)
509 {
510 AVHWFramesContext *hwfc = opaque;
511 VAAPIFramesContext *ctx = hwfc->hwctx;
512 AVVAAPIFramesContext *avfc = &ctx->p;
513 AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
514 VASurfaceID surface_id;
515 VAStatus vas;
516 AVBufferRef *ref;
517
518 if (hwfc->initial_pool_size > 0 &&
519 avfc->nb_surfaces >= hwfc->initial_pool_size)
520 return NULL;
521
522 vas = vaCreateSurfaces(hwctx->display, ctx->rt_format,
523 hwfc->width, hwfc->height,
524 &surface_id, 1,
525 ctx->attributes, ctx->nb_attributes);
526 if (vas != VA_STATUS_SUCCESS) {
527 av_log(hwfc, AV_LOG_ERROR, "Failed to create surface: "
528 "%d (%s).\n", vas, vaErrorStr(vas));
529 return NULL;
530 }
531 av_log(hwfc, AV_LOG_DEBUG, "Created surface %#x.\n", surface_id);
532
533 ref = av_buffer_create((uint8_t*)(uintptr_t)surface_id,
534 sizeof(surface_id), &vaapi_buffer_free,
535 hwfc, AV_BUFFER_FLAG_READONLY);
536 if (!ref) {
537 vaDestroySurfaces(hwctx->display, &surface_id, 1);
538 return NULL;
539 }
540
541 if (hwfc->initial_pool_size > 0) {
542 // This is a fixed-size pool, so we must still be in the initial
543 // allocation sequence.
544 av_assert0(avfc->nb_surfaces < hwfc->initial_pool_size);
545 avfc->surface_ids[avfc->nb_surfaces] = surface_id;
546 ++avfc->nb_surfaces;
547 }
548
549 return ref;
550 }
551
552 static int vaapi_frames_init(AVHWFramesContext *hwfc)
553 {
554 VAAPIFramesContext *ctx = hwfc->hwctx;
555 AVVAAPIFramesContext *avfc = &ctx->p;
556 AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
557 const VAAPIFormatDescriptor *desc;
558 VAImageFormat *expected_format;
559 AVBufferRef *test_surface = NULL;
560 VASurfaceID test_surface_id;
561 VAImage test_image;
562 VAStatus vas;
563 int err, i;
564
565 desc = vaapi_format_from_pix_fmt(hwfc->sw_format);
566 if (!desc) {
567 av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n",
568 av_get_pix_fmt_name(hwfc->sw_format));
569 return AVERROR(EINVAL);
570 }
571
572 if (!hwfc->pool) {
573 if (!(hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_SURFACE_ATTRIBUTES)) {
574 int need_memory_type = !(hwctx->driver_quirks & AV_VAAPI_DRIVER_QUIRK_ATTRIB_MEMTYPE);
575 int need_pixel_format = 1;
576 for (i = 0; i < avfc->nb_attributes; i++) {
577 if (avfc->attributes[i].type == VASurfaceAttribMemoryType)
578 need_memory_type = 0;
579 if (avfc->attributes[i].type == VASurfaceAttribPixelFormat)
580 need_pixel_format = 0;
581 }
582 ctx->nb_attributes =
583 avfc->nb_attributes + need_memory_type + need_pixel_format;
584
585 ctx->attributes = av_malloc(ctx->nb_attributes *
586 sizeof(*ctx->attributes));
587 if (!ctx->attributes) {
588 err = AVERROR(ENOMEM);
589 goto fail;
590 }
591
592 for (i = 0; i < avfc->nb_attributes; i++)
593 ctx->attributes[i] = avfc->attributes[i];
594 if (need_memory_type) {
595 ctx->attributes[i++] = (VASurfaceAttrib) {
596 .type = VASurfaceAttribMemoryType,
597 .flags = VA_SURFACE_ATTRIB_SETTABLE,
598 .value.type = VAGenericValueTypeInteger,
599 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA,
600 };
601 }
602 if (need_pixel_format) {
603 ctx->attributes[i++] = (VASurfaceAttrib) {
604 .type = VASurfaceAttribPixelFormat,
605 .flags = VA_SURFACE_ATTRIB_SETTABLE,
606 .value.type = VAGenericValueTypeInteger,
607 .value.value.i = desc->fourcc,
608 };
609 }
610 av_assert0(i == ctx->nb_attributes);
611 } else {
612 ctx->attributes = NULL;
613 ctx->nb_attributes = 0;
614 }
615
616 ctx->rt_format = desc->rt_format;
617
618 if (hwfc->initial_pool_size > 0) {
619 // This pool will be usable as a render target, so we need to store
620 // all of the surface IDs somewhere that vaCreateContext() calls
621 // will be able to access them.
622 avfc->nb_surfaces = 0;
623 avfc->surface_ids = av_malloc(hwfc->initial_pool_size *
624 sizeof(*avfc->surface_ids));
625 if (!avfc->surface_ids) {
626 err = AVERROR(ENOMEM);
627 goto fail;
628 }
629 } else {
630 // This pool allows dynamic sizing, and will not be usable as a
631 // render target.
632 avfc->nb_surfaces = 0;
633 avfc->surface_ids = NULL;
634 }
635
636 ffhwframesctx(hwfc)->pool_internal =
637 av_buffer_pool_init2(sizeof(VASurfaceID), hwfc,
638 &vaapi_pool_alloc, NULL);
639 if (!ffhwframesctx(hwfc)->pool_internal) {
640 av_log(hwfc, AV_LOG_ERROR, "Failed to create VAAPI surface pool.\n");
641 err = AVERROR(ENOMEM);
642 goto fail;
643 }
644 }
645
646 // Allocate a single surface to test whether vaDeriveImage() is going
647 // to work for the specific configuration.
648 if (hwfc->pool) {
649 test_surface = av_buffer_pool_get(hwfc->pool);
650 if (!test_surface) {
651 av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from "
652 "user-configured buffer pool.\n");
653 err = AVERROR(ENOMEM);
654 goto fail;
655 }
656 } else {
657 test_surface = av_buffer_pool_get(ffhwframesctx(hwfc)->pool_internal);
658 if (!test_surface) {
659 av_log(hwfc, AV_LOG_ERROR, "Unable to allocate a surface from "
660 "internal buffer pool.\n");
661 err = AVERROR(ENOMEM);
662 goto fail;
663 }
664 }
665 test_surface_id = (VASurfaceID)(uintptr_t)test_surface->data;
666
667 ctx->derive_works = 0;
668
669 err = vaapi_get_image_format(hwfc->device_ctx,
670 hwfc->sw_format, &expected_format);
671 if (err == 0) {
672 vas = vaDeriveImage(hwctx->display, test_surface_id, &test_image);
673 if (vas == VA_STATUS_SUCCESS) {
674 if (expected_format->fourcc == test_image.format.fourcc) {
675 av_log(hwfc, AV_LOG_DEBUG, "Direct mapping possible.\n");
676 ctx->derive_works = 1;
677 } else {
678 av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
679 "derived image format %08x does not match "
680 "expected format %08x.\n",
681 expected_format->fourcc, test_image.format.fourcc);
682 }
683 vaDestroyImage(hwctx->display, test_image.image_id);
684 } else {
685 av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
686 "deriving image does not work: "
687 "%d (%s).\n", vas, vaErrorStr(vas));
688 }
689 } else {
690 av_log(hwfc, AV_LOG_DEBUG, "Direct mapping disabled: "
691 "image format is not supported.\n");
692 }
693
694 av_buffer_unref(&test_surface);
695 return 0;
696
697 fail:
698 av_buffer_unref(&test_surface);
699 av_freep(&avfc->surface_ids);
700 av_freep(&ctx->attributes);
701 return err;
702 }
703
704 static void vaapi_frames_uninit(AVHWFramesContext *hwfc)
705 {
706 VAAPIFramesContext *ctx = hwfc->hwctx;
707 AVVAAPIFramesContext *avfc = &ctx->p;
708
709 av_freep(&avfc->surface_ids);
710 av_freep(&ctx->attributes);
711 }
712
713 static int vaapi_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
714 {
715 frame->buf[0] = av_buffer_pool_get(hwfc->pool);
716 if (!frame->buf[0])
717 return AVERROR(ENOMEM);
718
719 frame->data[3] = frame->buf[0]->data;
720 frame->format = AV_PIX_FMT_VAAPI;
721 frame->width = hwfc->width;
722 frame->height = hwfc->height;
723
724 return 0;
725 }
726
727 static int vaapi_transfer_get_formats(AVHWFramesContext *hwfc,
728 enum AVHWFrameTransferDirection dir,
729 enum AVPixelFormat **formats)
730 {
731 VAAPIDeviceContext *ctx = hwfc->device_ctx->hwctx;
732 enum AVPixelFormat *pix_fmts;
733 int i, k, sw_format_available;
734
735 sw_format_available = 0;
736 for (i = 0; i < ctx->nb_formats; i++) {
737 if (ctx->formats[i].pix_fmt == hwfc->sw_format)
738 sw_format_available = 1;
739 }
740
741 pix_fmts = av_malloc((ctx->nb_formats + 1) * sizeof(*pix_fmts));
742 if (!pix_fmts)
743 return AVERROR(ENOMEM);
744
745 if (sw_format_available) {
746 pix_fmts[0] = hwfc->sw_format;
747 k = 1;
748 } else {
749 k = 0;
750 }
751 for (i = 0; i < ctx->nb_formats; i++) {
752 if (ctx->formats[i].pix_fmt == hwfc->sw_format)
753 continue;
754 av_assert0(k < ctx->nb_formats);
755 pix_fmts[k++] = ctx->formats[i].pix_fmt;
756 }
757 pix_fmts[k] = AV_PIX_FMT_NONE;
758
759 *formats = pix_fmts;
760 return 0;
761 }
762
763 static void vaapi_unmap_frame(AVHWFramesContext *hwfc,
764 HWMapDescriptor *hwmap)
765 {
766 AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
767 VAAPIMapping *map = hwmap->priv;
768 VASurfaceID surface_id;
769 VAStatus vas;
770
771 surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3];
772 av_log(hwfc, AV_LOG_DEBUG, "Unmap surface %#x.\n", surface_id);
773
774 vas = vaUnmapBuffer(hwctx->display, map->image.buf);
775 if (vas != VA_STATUS_SUCCESS) {
776 av_log(hwfc, AV_LOG_ERROR, "Failed to unmap image from surface "
777 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
778 }
779
780 if ((map->flags & AV_HWFRAME_MAP_WRITE) &&
781 !(map->flags & AV_HWFRAME_MAP_DIRECT)) {
782 vas = vaPutImage(hwctx->display, surface_id, map->image.image_id,
783 0, 0, hwfc->width, hwfc->height,
784 0, 0, hwfc->width, hwfc->height);
785 if (vas != VA_STATUS_SUCCESS) {
786 av_log(hwfc, AV_LOG_ERROR, "Failed to write image to surface "
787 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
788 }
789 }
790
791 vas = vaDestroyImage(hwctx->display, map->image.image_id);
792 if (vas != VA_STATUS_SUCCESS) {
793 av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image from surface "
794 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
795 }
796
797 av_free(map);
798 }
799
800 static int vaapi_map_frame(AVHWFramesContext *hwfc,
801 AVFrame *dst, const AVFrame *src, int flags)
802 {
803 AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
804 VAAPIFramesContext *ctx = hwfc->hwctx;
805 VASurfaceID surface_id;
806 const VAAPIFormatDescriptor *desc;
807 VAImageFormat *image_format;
808 VAAPIMapping *map;
809 VAStatus vas;
810 void *address = NULL;
811 int err, i;
812 #if VA_CHECK_VERSION(1, 21, 0)
813 uint32_t vaflags = 0;
814 #endif
815
816 surface_id = (VASurfaceID)(uintptr_t)src->data[3];
817 av_log(hwfc, AV_LOG_DEBUG, "Map surface %#x.\n", surface_id);
818
819 if (!ctx->derive_works && (flags & AV_HWFRAME_MAP_DIRECT)) {
820 // Requested direct mapping but it is not possible.
821 return AVERROR(EINVAL);
822 }
823 if (dst->format == AV_PIX_FMT_NONE)
824 dst->format = hwfc->sw_format;
825 if (dst->format != hwfc->sw_format && (flags & AV_HWFRAME_MAP_DIRECT)) {
826 // Requested direct mapping but the formats do not match.
827 return AVERROR(EINVAL);
828 }
829
830 err = vaapi_get_image_format(hwfc->device_ctx, dst->format, &image_format);
831 if (err < 0) {
832 // Requested format is not a valid output format.
833 return err;
834 }
835
836 map = av_malloc(sizeof(*map));
837 if (!map)
838 return AVERROR(ENOMEM);
839 map->flags = flags;
840 map->image.image_id = VA_INVALID_ID;
841
842 vas = vaSyncSurface(hwctx->display, surface_id);
843 if (vas != VA_STATUS_SUCCESS) {
844 av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface "
845 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
846 err = AVERROR(EIO);
847 goto fail;
848 }
849
850 // The memory which we map using derive need not be connected to the CPU
851 // in a way conducive to fast access. On Gen7-Gen9 Intel graphics, the
852 // memory is mappable but not cached, so normal memcpy()-like access is
853 // very slow to read it (but writing is ok). It is possible to read much
854 // faster with a copy routine which is aware of the limitation, but we
855 // assume for now that the user is not aware of that and would therefore
856 // prefer not to be given direct-mapped memory if they request read access.
857 if (ctx->derive_works && dst->format == hwfc->sw_format &&
858 ((flags & AV_HWFRAME_MAP_DIRECT) || !(flags & AV_HWFRAME_MAP_READ))) {
859 vas = vaDeriveImage(hwctx->display, surface_id, &map->image);
860 if (vas != VA_STATUS_SUCCESS) {
861 av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from "
862 "surface %#x: %d (%s).\n",
863 surface_id, vas, vaErrorStr(vas));
864 err = AVERROR(EIO);
865 goto fail;
866 }
867 if (map->image.format.fourcc != image_format->fourcc) {
868 av_log(hwfc, AV_LOG_ERROR, "Derive image of surface %#x "
869 "is in wrong format: expected %#08x, got %#08x.\n",
870 surface_id, image_format->fourcc, map->image.format.fourcc);
871 err = AVERROR(EIO);
872 goto fail;
873 }
874 map->flags |= AV_HWFRAME_MAP_DIRECT;
875 } else {
876 vas = vaCreateImage(hwctx->display, image_format,
877 hwfc->width, hwfc->height, &map->image);
878 if (vas != VA_STATUS_SUCCESS) {
879 av_log(hwfc, AV_LOG_ERROR, "Failed to create image for "
880 "surface %#x: %d (%s).\n",
881 surface_id, vas, vaErrorStr(vas));
882 err = AVERROR(EIO);
883 goto fail;
884 }
885 if (!(flags & AV_HWFRAME_MAP_OVERWRITE)) {
886 vas = vaGetImage(hwctx->display, surface_id, 0, 0,
887 hwfc->width, hwfc->height, map->image.image_id);
888 if (vas != VA_STATUS_SUCCESS) {
889 av_log(hwfc, AV_LOG_ERROR, "Failed to read image from "
890 "surface %#x: %d (%s).\n",
891 surface_id, vas, vaErrorStr(vas));
892 err = AVERROR(EIO);
893 goto fail;
894 }
895 }
896 }
897
898 #if VA_CHECK_VERSION(1, 21, 0)
899 if (flags & AV_HWFRAME_MAP_READ)
900 vaflags |= VA_MAPBUFFER_FLAG_READ;
901 if (flags & AV_HWFRAME_MAP_WRITE)
902 vaflags |= VA_MAPBUFFER_FLAG_WRITE;
903 // On drivers not implementing vaMapBuffer2 libva calls vaMapBuffer instead.
904 vas = vaMapBuffer2(hwctx->display, map->image.buf, &address, vaflags);
905 #else
906 vas = vaMapBuffer(hwctx->display, map->image.buf, &address);
907 #endif
908 if (vas != VA_STATUS_SUCCESS) {
909 av_log(hwfc, AV_LOG_ERROR, "Failed to map image from surface "
910 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
911 err = AVERROR(EIO);
912 goto fail;
913 }
914
915 err = ff_hwframe_map_create(src->hw_frames_ctx,
916 dst, src, &vaapi_unmap_frame, map);
917 if (err < 0)
918 goto fail;
919
920 dst->width = src->width;
921 dst->height = src->height;
922
923 for (i = 0; i < map->image.num_planes; i++) {
924 dst->data[i] = (uint8_t*)address + map->image.offsets[i];
925 dst->linesize[i] = map->image.pitches[i];
926 }
927
928 desc = vaapi_format_from_fourcc(map->image.format.fourcc);
929 if (desc && desc->chroma_planes_swapped) {
930 // Chroma planes are YVU rather than YUV, so swap them.
931 FFSWAP(uint8_t*, dst->data[1], dst->data[2]);
932 }
933
934 return 0;
935
936 fail:
937 if (map) {
938 if (address)
939 vaUnmapBuffer(hwctx->display, map->image.buf);
940 if (map->image.image_id != VA_INVALID_ID)
941 vaDestroyImage(hwctx->display, map->image.image_id);
942 av_free(map);
943 }
944 return err;
945 }
946
947 static int vaapi_transfer_data_from(AVHWFramesContext *hwfc,
948 AVFrame *dst, const AVFrame *src)
949 {
950 AVFrame *map;
951 int err;
952
953 if (dst->width > hwfc->width || dst->height > hwfc->height)
954 return AVERROR(EINVAL);
955
956 map = av_frame_alloc();
957 if (!map)
958 return AVERROR(ENOMEM);
959 map->format = dst->format;
960
961 err = vaapi_map_frame(hwfc, map, src, AV_HWFRAME_MAP_READ);
962 if (err)
963 goto fail;
964
965 map->width = dst->width;
966 map->height = dst->height;
967
968 err = av_frame_copy(dst, map);
969 if (err)
970 goto fail;
971
972 err = 0;
973 fail:
974 av_frame_free(&map);
975 return err;
976 }
977
978 static int vaapi_transfer_data_to(AVHWFramesContext *hwfc,
979 AVFrame *dst, const AVFrame *src)
980 {
981 AVFrame *map;
982 int err;
983
984 if (src->width > hwfc->width || src->height > hwfc->height)
985 return AVERROR(EINVAL);
986
987 map = av_frame_alloc();
988 if (!map)
989 return AVERROR(ENOMEM);
990 map->format = src->format;
991
992 err = vaapi_map_frame(hwfc, map, dst, AV_HWFRAME_MAP_WRITE | AV_HWFRAME_MAP_OVERWRITE);
993 if (err)
994 goto fail;
995
996 map->width = src->width;
997 map->height = src->height;
998
999 err = av_frame_copy(map, src);
1000 if (err)
1001 goto fail;
1002
1003 err = 0;
1004 fail:
1005 av_frame_free(&map);
1006 return err;
1007 }
1008
1009 static int vaapi_map_to_memory(AVHWFramesContext *hwfc, AVFrame *dst,
1010 const AVFrame *src, int flags)
1011 {
1012 int err;
1013
1014 if (dst->format != AV_PIX_FMT_NONE) {
1015 err = vaapi_get_image_format(hwfc->device_ctx, dst->format, NULL);
1016 if (err < 0)
1017 return err;
1018 }
1019
1020 err = vaapi_map_frame(hwfc, dst, src, flags);
1021 if (err)
1022 return err;
1023
1024 err = av_frame_copy_props(dst, src);
1025 if (err)
1026 return err;
1027
1028 return 0;
1029 }
1030
1031 #if CONFIG_LIBDRM
1032
1033 #define DRM_MAP(va, layers, ...) { \
1034 VA_FOURCC_ ## va, \
1035 layers, \
1036 { __VA_ARGS__ } \
1037 }
1038 static const struct {
1039 uint32_t va_fourcc;
1040 int nb_layer_formats;
1041 uint32_t layer_formats[AV_DRM_MAX_PLANES];
1042 } vaapi_drm_format_map[] = {
1043 #ifdef DRM_FORMAT_R8
1044 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88),
1045 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88),
1046 #endif
1047 DRM_MAP(NV12, 1, DRM_FORMAT_NV12),
1048 #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16)
1049 DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1050 #endif
1051 #if defined(VA_FOURCC_P012) && defined(DRM_FORMAT_R16)
1052 DRM_MAP(P012, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
1053 #endif
1054 DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888),
1055 DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888),
1056 DRM_MAP(RGBA, 1, DRM_FORMAT_ABGR8888),
1057 DRM_MAP(RGBX, 1, DRM_FORMAT_XBGR8888),
1058 #ifdef VA_FOURCC_ABGR
1059 DRM_MAP(ABGR, 1, DRM_FORMAT_RGBA8888),
1060 DRM_MAP(XBGR, 1, DRM_FORMAT_RGBX8888),
1061 #endif
1062 DRM_MAP(ARGB, 1, DRM_FORMAT_BGRA8888),
1063 DRM_MAP(XRGB, 1, DRM_FORMAT_BGRX8888),
1064 #if defined(VA_FOURCC_XYUV) && defined(DRM_FORMAT_XYUV8888)
1065 DRM_MAP(XYUV, 1, DRM_FORMAT_XYUV8888),
1066 #endif
1067 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU2101010)
1068 DRM_MAP(Y410, 1, DRM_FORMAT_XVYU2101010),
1069 #endif
1070 #if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU12_16161616)
1071 DRM_MAP(Y412, 1, DRM_FORMAT_XVYU12_16161616),
1072 #endif
1073 #if defined(VA_FOURCC_X2R10G10B10) && defined(DRM_FORMAT_XRGB2101010)
1074 DRM_MAP(X2R10G10B10, 1, DRM_FORMAT_XRGB2101010),
1075 #endif
1076 };
1077 #undef DRM_MAP
1078
1079 static void vaapi_unmap_from_drm(AVHWFramesContext *dst_fc,
1080 HWMapDescriptor *hwmap)
1081 {
1082 AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
1083
1084 VASurfaceID surface_id = (VASurfaceID)(uintptr_t)hwmap->priv;
1085
1086 av_log(dst_fc, AV_LOG_DEBUG, "Destroy surface %#x.\n", surface_id);
1087
1088 vaDestroySurfaces(dst_dev->display, &surface_id, 1);
1089 }
1090
1091 static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst,
1092 const AVFrame *src, int flags)
1093 {
1094 #if VA_CHECK_VERSION(1, 1, 0)
1095 VAAPIFramesContext *src_vafc = src_fc->hwctx;
1096 int use_prime2;
1097 #else
1098 int k;
1099 #endif
1100 AVHWFramesContext *dst_fc =
1101 (AVHWFramesContext*)dst->hw_frames_ctx->data;
1102 AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
1103 const AVDRMFrameDescriptor *desc;
1104 const VAAPIFormatDescriptor *format_desc;
1105 VASurfaceID surface_id;
1106 VAStatus vas = VA_STATUS_SUCCESS;
1107 uint32_t va_fourcc;
1108 int err, i, j;
1109
1110 #if !VA_CHECK_VERSION(1, 1, 0)
1111 unsigned long buffer_handle;
1112 VASurfaceAttribExternalBuffers buffer_desc;
1113 VASurfaceAttrib attrs[2] = {
1114 {
1115 .type = VASurfaceAttribMemoryType,
1116 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1117 .value.type = VAGenericValueTypeInteger,
1118 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1119 },
1120 {
1121 .type = VASurfaceAttribExternalBufferDescriptor,
1122 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1123 .value.type = VAGenericValueTypePointer,
1124 .value.value.p = &buffer_desc,
1125 }
1126 };
1127 #endif
1128
1129 desc = (AVDRMFrameDescriptor*)src->data[0];
1130
1131 if (desc->nb_objects != 1) {
1132 av_log(dst_fc, AV_LOG_ERROR, "VAAPI can only map frames "
1133 "made from a single DRM object.\n");
1134 return AVERROR(EINVAL);
1135 }
1136
1137 va_fourcc = 0;
1138 for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) {
1139 if (desc->nb_layers != vaapi_drm_format_map[i].nb_layer_formats)
1140 continue;
1141 for (j = 0; j < desc->nb_layers; j++) {
1142 if (desc->layers[j].format !=
1143 vaapi_drm_format_map[i].layer_formats[j])
1144 break;
1145 }
1146 if (j != desc->nb_layers)
1147 continue;
1148 va_fourcc = vaapi_drm_format_map[i].va_fourcc;
1149 break;
1150 }
1151 if (!va_fourcc) {
1152 av_log(dst_fc, AV_LOG_ERROR, "DRM format not supported "
1153 "by VAAPI.\n");
1154 return AVERROR(EINVAL);
1155 }
1156
1157 av_log(dst_fc, AV_LOG_DEBUG, "Map DRM object %d to VAAPI as "
1158 "%08x.\n", desc->objects[0].fd, va_fourcc);
1159
1160 format_desc = vaapi_format_from_fourcc(va_fourcc);
1161 av_assert0(format_desc);
1162
1163 #if VA_CHECK_VERSION(1, 1, 0)
1164 use_prime2 = !src_vafc->prime_2_import_unsupported &&
1165 desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID;
1166 if (use_prime2) {
1167 VADRMPRIMESurfaceDescriptor prime_desc;
1168 VASurfaceAttrib prime_attrs[2] = {
1169 {
1170 .type = VASurfaceAttribMemoryType,
1171 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1172 .value.type = VAGenericValueTypeInteger,
1173 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1174 },
1175 {
1176 .type = VASurfaceAttribExternalBufferDescriptor,
1177 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1178 .value.type = VAGenericValueTypePointer,
1179 .value.value.p = &prime_desc,
1180 }
1181 };
1182 prime_desc.fourcc = va_fourcc;
1183 prime_desc.width = src_fc->width;
1184 prime_desc.height = src_fc->height;
1185 prime_desc.num_objects = desc->nb_objects;
1186 for (i = 0; i < desc->nb_objects; ++i) {
1187 prime_desc.objects[i].fd = desc->objects[i].fd;
1188 prime_desc.objects[i].size = desc->objects[i].size;
1189 prime_desc.objects[i].drm_format_modifier =
1190 desc->objects[i].format_modifier;
1191 }
1192
1193 prime_desc.num_layers = desc->nb_layers;
1194 for (i = 0; i < desc->nb_layers; ++i) {
1195 prime_desc.layers[i].drm_format = desc->layers[i].format;
1196 prime_desc.layers[i].num_planes = desc->layers[i].nb_planes;
1197 for (j = 0; j < desc->layers[i].nb_planes; ++j) {
1198 prime_desc.layers[i].object_index[j] =
1199 desc->layers[i].planes[j].object_index;
1200 prime_desc.layers[i].offset[j] = desc->layers[i].planes[j].offset;
1201 prime_desc.layers[i].pitch[j] = desc->layers[i].planes[j].pitch;
1202 }
1203
1204 if (format_desc->chroma_planes_swapped &&
1205 desc->layers[i].nb_planes == 3) {
1206 FFSWAP(uint32_t, prime_desc.layers[i].pitch[1],
1207 prime_desc.layers[i].pitch[2]);
1208 FFSWAP(uint32_t, prime_desc.layers[i].offset[1],
1209 prime_desc.layers[i].offset[2]);
1210 }
1211 }
1212
1213 /*
1214 * We can query for PRIME_2 support with vaQuerySurfaceAttributes, but that
1215 * that needs the config_id which we don't have here . Both Intel and
1216 * Gallium seem to do the correct error checks, so lets just try the
1217 * PRIME_2 import first.
1218 */
1219 vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
1220 src->width, src->height, &surface_id, 1,
1221 prime_attrs, FF_ARRAY_ELEMS(prime_attrs));
1222 if (vas != VA_STATUS_SUCCESS)
1223 src_vafc->prime_2_import_unsupported = 1;
1224 }
1225
1226 if (!use_prime2 || vas != VA_STATUS_SUCCESS) {
1227 int k;
1228 uintptr_t buffer_handle;
1229 VASurfaceAttribExternalBuffers buffer_desc;
1230 VASurfaceAttrib buffer_attrs[2] = {
1231 {
1232 .type = VASurfaceAttribMemoryType,
1233 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1234 .value.type = VAGenericValueTypeInteger,
1235 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
1236 },
1237 {
1238 .type = VASurfaceAttribExternalBufferDescriptor,
1239 .flags = VA_SURFACE_ATTRIB_SETTABLE,
1240 .value.type = VAGenericValueTypePointer,
1241 .value.value.p = &buffer_desc,
1242 }
1243 };
1244
1245 buffer_handle = desc->objects[0].fd;
1246 buffer_desc.pixel_format = va_fourcc;
1247 buffer_desc.width = src_fc->width;
1248 buffer_desc.height = src_fc->height;
1249 buffer_desc.data_size = desc->objects[0].size;
1250 buffer_desc.buffers = &buffer_handle;
1251 buffer_desc.num_buffers = 1;
1252 buffer_desc.flags = 0;
1253
1254 k = 0;
1255 for (i = 0; i < desc->nb_layers; i++) {
1256 for (j = 0; j < desc->layers[i].nb_planes; j++) {
1257 buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch;
1258 buffer_desc.offsets[k] = desc->layers[i].planes[j].offset;
1259 ++k;
1260 }
1261 }
1262 buffer_desc.num_planes = k;
1263
1264 if (format_desc->chroma_planes_swapped &&
1265 buffer_desc.num_planes == 3) {
1266 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1267 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1268 }
1269
1270 vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
1271 src->width, src->height,
1272 &surface_id, 1,
1273 buffer_attrs, FF_ARRAY_ELEMS(buffer_attrs));
1274 }
1275 #else
1276 buffer_handle = desc->objects[0].fd;
1277 buffer_desc.pixel_format = va_fourcc;
1278 buffer_desc.width = src_fc->width;
1279 buffer_desc.height = src_fc->height;
1280 buffer_desc.data_size = desc->objects[0].size;
1281 buffer_desc.buffers = &buffer_handle;
1282 buffer_desc.num_buffers = 1;
1283 buffer_desc.flags = 0;
1284
1285 k = 0;
1286 for (i = 0; i < desc->nb_layers; i++) {
1287 for (j = 0; j < desc->layers[i].nb_planes; j++) {
1288 buffer_desc.pitches[k] = desc->layers[i].planes[j].pitch;
1289 buffer_desc.offsets[k] = desc->layers[i].planes[j].offset;
1290 ++k;
1291 }
1292 }
1293 buffer_desc.num_planes = k;
1294
1295 if (format_desc->chroma_planes_swapped &&
1296 buffer_desc.num_planes == 3) {
1297 FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
1298 FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
1299 }
1300
1301 vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
1302 src->width, src->height,
1303 &surface_id, 1,
1304 attrs, FF_ARRAY_ELEMS(attrs));
1305 #endif
1306 if (vas != VA_STATUS_SUCCESS) {
1307 av_log(dst_fc, AV_LOG_ERROR, "Failed to create surface from DRM "
1308 "object: %d (%s).\n", vas, vaErrorStr(vas));
1309 return AVERROR(EIO);
1310 }
1311 av_log(dst_fc, AV_LOG_DEBUG, "Create surface %#x.\n", surface_id);
1312
1313 err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src,
1314 &vaapi_unmap_from_drm,
1315 (void*)(uintptr_t)surface_id);
1316 if (err < 0)
1317 return err;
1318
1319 dst->width = src->width;
1320 dst->height = src->height;
1321 dst->data[3] = (uint8_t*)(uintptr_t)surface_id;
1322
1323 av_log(dst_fc, AV_LOG_DEBUG, "Mapped DRM object %d to "
1324 "surface %#x.\n", desc->objects[0].fd, surface_id);
1325
1326 return 0;
1327 }
1328
1329 #if VA_CHECK_VERSION(1, 1, 0)
1330 static void vaapi_unmap_to_drm_esh(AVHWFramesContext *hwfc,
1331 HWMapDescriptor *hwmap)
1332 {
1333 AVDRMFrameDescriptor *drm_desc = hwmap->priv;
1334 int i;
1335
1336 for (i = 0; i < drm_desc->nb_objects; i++)
1337 close(drm_desc->objects[i].fd);
1338
1339 av_freep(&drm_desc);
1340 }
1341
1342 static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst,
1343 const AVFrame *src, int flags)
1344 {
1345 AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1346 VASurfaceID surface_id;
1347 VAStatus vas;
1348 VADRMPRIMESurfaceDescriptor va_desc;
1349 AVDRMFrameDescriptor *drm_desc = NULL;
1350 uint32_t export_flags;
1351 int err, i, j;
1352
1353 surface_id = (VASurfaceID)(uintptr_t)src->data[3];
1354
1355 export_flags = VA_EXPORT_SURFACE_SEPARATE_LAYERS;
1356 if (flags & AV_HWFRAME_MAP_READ) {
1357 export_flags |= VA_EXPORT_SURFACE_READ_ONLY;
1358
1359 vas = vaSyncSurface(hwctx->display, surface_id);
1360 if (vas != VA_STATUS_SUCCESS) {
1361 av_log(hwfc, AV_LOG_ERROR, "Failed to sync surface "
1362 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
1363 return AVERROR(EIO);
1364 }
1365 }
1366
1367 if (flags & AV_HWFRAME_MAP_WRITE)
1368 export_flags |= VA_EXPORT_SURFACE_WRITE_ONLY;
1369
1370 vas = vaExportSurfaceHandle(hwctx->display, surface_id,
1371 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2,
1372 export_flags, &va_desc);
1373 if (vas != VA_STATUS_SUCCESS) {
1374 if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
1375 return AVERROR(ENOSYS);
1376 av_log(hwfc, AV_LOG_ERROR, "Failed to export surface %#x: "
1377 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
1378 return AVERROR(EIO);
1379 }
1380
1381 drm_desc = av_mallocz(sizeof(*drm_desc));
1382 if (!drm_desc) {
1383 err = AVERROR(ENOMEM);
1384 goto fail;
1385 }
1386
1387 // By some bizarre coincidence, these structures are very similar...
1388 drm_desc->nb_objects = va_desc.num_objects;
1389 for (i = 0; i < va_desc.num_objects; i++) {
1390 drm_desc->objects[i].fd = va_desc.objects[i].fd;
1391 drm_desc->objects[i].size = va_desc.objects[i].size;
1392 drm_desc->objects[i].format_modifier =
1393 va_desc.objects[i].drm_format_modifier;
1394 }
1395 drm_desc->nb_layers = va_desc.num_layers;
1396 for (i = 0; i < va_desc.num_layers; i++) {
1397 drm_desc->layers[i].format = va_desc.layers[i].drm_format;
1398 drm_desc->layers[i].nb_planes = va_desc.layers[i].num_planes;
1399 for (j = 0; j < va_desc.layers[i].num_planes; j++) {
1400 drm_desc->layers[i].planes[j].object_index =
1401 va_desc.layers[i].object_index[j];
1402 drm_desc->layers[i].planes[j].offset =
1403 va_desc.layers[i].offset[j];
1404 drm_desc->layers[i].planes[j].pitch =
1405 va_desc.layers[i].pitch[j];
1406 }
1407 }
1408
1409 err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src,
1410 &vaapi_unmap_to_drm_esh, drm_desc);
1411 if (err < 0)
1412 goto fail;
1413
1414 dst->width = src->width;
1415 dst->height = src->height;
1416 dst->data[0] = (uint8_t*)drm_desc;
1417
1418 return 0;
1419
1420 fail:
1421 for (i = 0; i < va_desc.num_objects; i++)
1422 close(va_desc.objects[i].fd);
1423 av_freep(&drm_desc);
1424 return err;
1425 }
1426 #endif
1427
1428 #if VA_CHECK_VERSION(0, 36, 0)
1429 typedef struct VAAPIDRMImageBufferMapping {
1430 VAImage image;
1431 VABufferInfo buffer_info;
1432
1433 AVDRMFrameDescriptor drm_desc;
1434 } VAAPIDRMImageBufferMapping;
1435
1436 static void vaapi_unmap_to_drm_abh(AVHWFramesContext *hwfc,
1437 HWMapDescriptor *hwmap)
1438 {
1439 AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1440 VAAPIDRMImageBufferMapping *mapping = hwmap->priv;
1441 VASurfaceID surface_id;
1442 VAStatus vas;
1443
1444 surface_id = (VASurfaceID)(uintptr_t)hwmap->source->data[3];
1445 av_log(hwfc, AV_LOG_DEBUG, "Unmap VAAPI surface %#x from DRM.\n",
1446 surface_id);
1447
1448 // DRM PRIME file descriptors are closed by vaReleaseBufferHandle(),
1449 // so we shouldn't close them separately.
1450
1451 vas = vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
1452 if (vas != VA_STATUS_SUCCESS) {
1453 av_log(hwfc, AV_LOG_ERROR, "Failed to release buffer "
1454 "handle of image %#x (derived from surface %#x): "
1455 "%d (%s).\n", mapping->image.buf, surface_id,
1456 vas, vaErrorStr(vas));
1457 }
1458
1459 vas = vaDestroyImage(hwctx->display, mapping->image.image_id);
1460 if (vas != VA_STATUS_SUCCESS) {
1461 av_log(hwfc, AV_LOG_ERROR, "Failed to destroy image "
1462 "derived from surface %#x: %d (%s).\n",
1463 surface_id, vas, vaErrorStr(vas));
1464 }
1465
1466 av_free(mapping);
1467 }
1468
1469 static int vaapi_map_to_drm_abh(AVHWFramesContext *hwfc, AVFrame *dst,
1470 const AVFrame *src, int flags)
1471 {
1472 AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
1473 VAAPIDRMImageBufferMapping *mapping = NULL;
1474 VASurfaceID surface_id;
1475 VAStatus vas;
1476 int err, i, p;
1477
1478 surface_id = (VASurfaceID)(uintptr_t)src->data[3];
1479 av_log(hwfc, AV_LOG_DEBUG, "Map VAAPI surface %#x to DRM.\n",
1480 surface_id);
1481
1482 mapping = av_mallocz(sizeof(*mapping));
1483 if (!mapping)
1484 return AVERROR(ENOMEM);
1485
1486 vas = vaDeriveImage(hwctx->display, surface_id,
1487 &mapping->image);
1488 if (vas != VA_STATUS_SUCCESS) {
1489 av_log(hwfc, AV_LOG_ERROR, "Failed to derive image from "
1490 "surface %#x: %d (%s).\n",
1491 surface_id, vas, vaErrorStr(vas));
1492 err = AVERROR(EIO);
1493 goto fail;
1494 }
1495
1496 for (i = 0; i < FF_ARRAY_ELEMS(vaapi_drm_format_map); i++) {
1497 if (vaapi_drm_format_map[i].va_fourcc ==
1498 mapping->image.format.fourcc)
1499 break;
1500 }
1501 if (i >= FF_ARRAY_ELEMS(vaapi_drm_format_map)) {
1502 av_log(hwfc, AV_LOG_ERROR, "No matching DRM format for "
1503 "VAAPI format %#x.\n", mapping->image.format.fourcc);
1504 err = AVERROR(EINVAL);
1505 goto fail_derived;
1506 }
1507
1508 mapping->buffer_info.mem_type =
1509 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME;
1510
1511 mapping->drm_desc.nb_layers =
1512 vaapi_drm_format_map[i].nb_layer_formats;
1513 if (mapping->drm_desc.nb_layers > 1) {
1514 if (mapping->drm_desc.nb_layers != mapping->image.num_planes) {
1515 av_log(hwfc, AV_LOG_ERROR, "Image properties do not match "
1516 "expected format: got %d planes, but expected %d.\n",
1517 mapping->image.num_planes, mapping->drm_desc.nb_layers);
1518 err = AVERROR(EINVAL);
1519 goto fail_derived;
1520 }
1521
1522 for(p = 0; p < mapping->drm_desc.nb_layers; p++) {
1523 mapping->drm_desc.layers[p] = (AVDRMLayerDescriptor) {
1524 .format = vaapi_drm_format_map[i].layer_formats[p],
1525 .nb_planes = 1,
1526 .planes[0] = {
1527 .object_index = 0,
1528 .offset = mapping->image.offsets[p],
1529 .pitch = mapping->image.pitches[p],
1530 },
1531 };
1532 }
1533 } else {
1534 mapping->drm_desc.layers[0].format =
1535 vaapi_drm_format_map[i].layer_formats[0];
1536 mapping->drm_desc.layers[0].nb_planes = mapping->image.num_planes;
1537 for (p = 0; p < mapping->image.num_planes; p++) {
1538 mapping->drm_desc.layers[0].planes[p] = (AVDRMPlaneDescriptor) {
1539 .object_index = 0,
1540 .offset = mapping->image.offsets[p],
1541 .pitch = mapping->image.pitches[p],
1542 };
1543 }
1544 }
1545
1546 vas = vaAcquireBufferHandle(hwctx->display, mapping->image.buf,
1547 &mapping->buffer_info);
1548 if (vas != VA_STATUS_SUCCESS) {
1549 av_log(hwfc, AV_LOG_ERROR, "Failed to get buffer "
1550 "handle from image %#x (derived from surface %#x): "
1551 "%d (%s).\n", mapping->image.buf, surface_id,
1552 vas, vaErrorStr(vas));
1553 err = AVERROR(EIO);
1554 goto fail_derived;
1555 }
1556
1557 av_log(hwfc, AV_LOG_DEBUG, "DRM PRIME fd is %"PRIdPTR".\n",
1558 mapping->buffer_info.handle);
1559
1560 mapping->drm_desc.nb_objects = 1;
1561 mapping->drm_desc.objects[0] = (AVDRMObjectDescriptor) {
1562 .fd = mapping->buffer_info.handle,
1563 .size = mapping->image.data_size,
1564 // There is no way to get the format modifier with this API.
1565 .format_modifier = DRM_FORMAT_MOD_INVALID,
1566 };
1567
1568 err = ff_hwframe_map_create(src->hw_frames_ctx,
1569 dst, src, &vaapi_unmap_to_drm_abh,
1570 mapping);
1571 if (err < 0)
1572 goto fail_mapped;
1573
1574 dst->data[0] = (uint8_t*)&mapping->drm_desc;
1575 dst->width = src->width;
1576 dst->height = src->height;
1577
1578 return 0;
1579
1580 fail_mapped:
1581 vaReleaseBufferHandle(hwctx->display, mapping->image.buf);
1582 fail_derived:
1583 vaDestroyImage(hwctx->display, mapping->image.image_id);
1584 fail:
1585 av_freep(&mapping);
1586 return err;
1587 }
1588 #endif
1589
1590 static int vaapi_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst,
1591 const AVFrame *src, int flags)
1592 {
1593 #if VA_CHECK_VERSION(1, 1, 0)
1594 int err;
1595 err = vaapi_map_to_drm_esh(hwfc, dst, src, flags);
1596 if (err != AVERROR(ENOSYS))
1597 return err;
1598 #endif
1599 #if VA_CHECK_VERSION(0, 36, 0)
1600 return vaapi_map_to_drm_abh(hwfc, dst, src, flags);
1601 #endif
1602 return AVERROR(ENOSYS);
1603 }
1604
1605 #endif /* CONFIG_LIBDRM */
1606
1607 static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst,
1608 const AVFrame *src, int flags)
1609 {
1610 switch (src->format) {
1611 #if CONFIG_LIBDRM
1612 case AV_PIX_FMT_DRM_PRIME:
1613 return vaapi_map_from_drm(hwfc, dst, src, flags);
1614 #endif
1615 default:
1616 return AVERROR(ENOSYS);
1617 }
1618 }
1619
1620 static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst,
1621 const AVFrame *src, int flags)
1622 {
1623 switch (dst->format) {
1624 #if CONFIG_LIBDRM
1625 case AV_PIX_FMT_DRM_PRIME:
1626 return vaapi_map_to_drm(hwfc, dst, src, flags);
1627 #endif
1628 default:
1629 return vaapi_map_to_memory(hwfc, dst, src, flags);
1630 }
1631 }
1632
1633 static void vaapi_device_free(AVHWDeviceContext *ctx)
1634 {
1635 AVVAAPIDeviceContext *hwctx = ctx->hwctx;
1636 VAAPIDevicePriv *priv = ctx->user_opaque;
1637
1638 if (hwctx->display)
1639 vaTerminate(hwctx->display);
1640
1641 #if HAVE_VAAPI_X11
1642 if (priv->x11_display)
1643 XCloseDisplay(priv->x11_display);
1644 #endif
1645
1646 if (priv->drm_fd >= 0)
1647 close(priv->drm_fd);
1648
1649 av_freep(&priv);
1650 }
1651
1652 #if CONFIG_VAAPI_1
1653 static void vaapi_device_log_error(void *context, const char *message)
1654 {
1655 AVHWDeviceContext *ctx = context;
1656
1657 av_log(ctx, AV_LOG_ERROR, "libva: %s", message);
1658 }
1659
1660 static void vaapi_device_log_info(void *context, const char *message)
1661 {
1662 AVHWDeviceContext *ctx = context;
1663
1664 av_log(ctx, AV_LOG_VERBOSE, "libva: %s", message);
1665 }
1666 #endif
1667
1668 static int vaapi_device_connect(AVHWDeviceContext *ctx,
1669 VADisplay display)
1670 {
1671 AVVAAPIDeviceContext *hwctx = ctx->hwctx;
1672 int major, minor;
1673 VAStatus vas;
1674
1675 #if CONFIG_VAAPI_1
1676 vaSetErrorCallback(display, &vaapi_device_log_error, ctx);
1677 vaSetInfoCallback (display, &vaapi_device_log_info, ctx);
1678 #endif
1679
1680 hwctx->display = display;
1681
1682 vas = vaInitialize(display, &major, &minor);
1683 if (vas != VA_STATUS_SUCCESS) {
1684 av_log(ctx, AV_LOG_ERROR, "Failed to initialise VAAPI "
1685 "connection: %d (%s).\n", vas, vaErrorStr(vas));
1686 return AVERROR(EIO);
1687 }
1688 av_log(ctx, AV_LOG_VERBOSE, "Initialised VAAPI connection: "
1689 "version %d.%d\n", major, minor);
1690
1691 return 0;
1692 }
1693
1694 static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device,
1695 AVDictionary *opts, int flags)
1696 {
1697 VAAPIDevicePriv *priv;
1698 VADisplay display = NULL;
1699 const AVDictionaryEntry *ent;
1700 int try_drm, try_x11, try_win32, try_all;
1701
1702 priv = av_mallocz(sizeof(*priv));
1703 if (!priv)
1704 return AVERROR(ENOMEM);
1705
1706 priv->drm_fd = -1;
1707
1708 ctx->user_opaque = priv;
1709 ctx->free = vaapi_device_free;
1710
1711 ent = av_dict_get(opts, "connection_type", NULL, 0);
1712 if (ent) {
1713 try_all = try_drm = try_x11 = try_win32 = 0;
1714 if (!strcmp(ent->value, "drm")) {
1715 try_drm = 1;
1716 } else if (!strcmp(ent->value, "x11")) {
1717 try_x11 = 1;
1718 } else if (!strcmp(ent->value, "win32")) {
1719 try_win32 = 1;
1720 } else {
1721 av_log(ctx, AV_LOG_ERROR, "Invalid connection type %s.\n",
1722 ent->value);
1723 return AVERROR(EINVAL);
1724 }
1725 } else {
1726 try_all = 1;
1727 try_drm = HAVE_VAAPI_DRM;
1728 try_x11 = HAVE_VAAPI_X11;
1729 try_win32 = HAVE_VAAPI_WIN32;
1730 }
1731
1732 #if HAVE_VAAPI_DRM
1733 while (!display && try_drm) {
1734 // If the device is specified, try to open it as a DRM device node.
1735 // If not, look for a usable render node, possibly restricted to those
1736 // using a specified kernel driver.
1737 int loglevel = try_all ? AV_LOG_VERBOSE : AV_LOG_ERROR;
1738 if (device) {
1739 priv->drm_fd = open(device, O_RDWR);
1740 if (priv->drm_fd < 0) {
1741 av_log(ctx, loglevel, "Failed to open %s as "
1742 "DRM device node.\n", device);
1743 break;
1744 }
1745 } else {
1746 char path[64];
1747 int n, max_devices = 8;
1748 #if CONFIG_LIBDRM
1749 drmVersion *info;
1750 const AVDictionaryEntry *kernel_driver;
1751 const AVDictionaryEntry *vendor_id;
1752 kernel_driver = av_dict_get(opts, "kernel_driver", NULL, 0);
1753 vendor_id = av_dict_get(opts, "vendor_id", NULL, 0);
1754 #endif
1755 for (n = 0; n < max_devices; n++) {
1756 snprintf(path, sizeof(path),
1757 "/dev/dri/renderD%d", 128 + n);
1758 priv->drm_fd = open(path, O_RDWR);
1759 if (priv->drm_fd < 0) {
1760 if (errno == ENOENT) {
1761 if (n != max_devices - 1) {
1762 av_log(ctx, AV_LOG_VERBOSE,
1763 "No render device %s, try next device for "
1764 "DRM render node.\n", path);
1765 continue;
1766 }
1767
1768 av_log(ctx, AV_LOG_VERBOSE, "No available render device "
1769 "for DRM render node.\n");
1770 } else
1771 av_log(ctx, AV_LOG_VERBOSE, "Cannot open "
1772 "DRM render node for device %d.\n", n);
1773 break;
1774 }
1775 #if CONFIG_LIBDRM
1776 info = drmGetVersion(priv->drm_fd);
1777 if (!info) {
1778 av_log(ctx, AV_LOG_VERBOSE,
1779 "Failed to get DRM version for device %d.\n", n);
1780 close(priv->drm_fd);
1781 priv->drm_fd = -1;
1782 continue;
1783 }
1784 if (kernel_driver) {
1785 if (strcmp(kernel_driver->value, info->name)) {
1786 av_log(ctx, AV_LOG_VERBOSE, "Ignoring device %d "
1787 "with non-matching kernel driver (%s).\n",
1788 n, info->name);
1789 drmFreeVersion(info);
1790 close(priv->drm_fd);
1791 priv->drm_fd = -1;
1792 continue;
1793 }
1794 av_log(ctx, AV_LOG_VERBOSE, "Trying to use "
1795 "DRM render node for device %d, "
1796 "with matching kernel driver (%s).\n",
1797 n, info->name);
1798 drmFreeVersion(info);
1799 break;
1800 // drmGetVersion() ensures |info->name| is 0-terminated.
1801 } else if (!strcmp(info->name, "vgem")) {
1802 av_log(ctx, AV_LOG_VERBOSE,
1803 "Skipping vgem node for device %d.\n", n);
1804 drmFreeVersion(info);
1805 close(priv->drm_fd);
1806 priv->drm_fd = -1;
1807 continue;
1808 } else if (vendor_id) {
1809 drmDevicePtr device;
1810 char drm_vendor[8];
1811 if (drmGetDevice(priv->drm_fd, &device)) {
1812 av_log(ctx, AV_LOG_VERBOSE,
1813 "Failed to get DRM device info for device %d.\n", n);
1814 close(priv->drm_fd);
1815 priv->drm_fd = -1;
1816 continue;
1817 }
1818
1819 snprintf(drm_vendor, sizeof(drm_vendor), "0x%x", device->deviceinfo.pci->vendor_id);
1820 if (strcmp(vendor_id->value, drm_vendor)) {
1821 av_log(ctx, AV_LOG_VERBOSE, "Ignoring device %d "
1822 "with non-matching vendor id (%s).\n",
1823 n, vendor_id->value);
1824 drmFreeDevice(&device);
1825 close(priv->drm_fd);
1826 priv->drm_fd = -1;
1827 continue;
1828 }
1829 av_log(ctx, AV_LOG_VERBOSE, "Trying to use "
1830 "DRM render node for device %d, "
1831 "with matching vendor id (%s).\n",
1832 n, vendor_id->value);
1833 drmFreeDevice(&device);
1834 break;
1835 }
1836 drmFreeVersion(info);
1837 #endif
1838 av_log(ctx, AV_LOG_VERBOSE, "Trying to use "
1839 "DRM render node for device %d.\n", n);
1840 break;
1841 }
1842 if (n >= max_devices)
1843 break;
1844 }
1845
1846 display = vaGetDisplayDRM(priv->drm_fd);
1847 if (!display) {
1848 av_log(ctx, AV_LOG_VERBOSE, "Cannot open a VA display "
1849 "from DRM device %s.\n", device);
1850 return AVERROR_EXTERNAL;
1851 }
1852 break;
1853 }
1854 #endif
1855
1856 #if HAVE_VAAPI_X11
1857 if (!display && try_x11) {
1858 // Try to open the device as an X11 display.
1859 priv->x11_display = XOpenDisplay(device);
1860 if (!priv->x11_display) {
1861 av_log(ctx, AV_LOG_VERBOSE, "Cannot open X11 display "
1862 "%s.\n", XDisplayName(device));
1863 } else {
1864 display = vaGetDisplay(priv->x11_display);
1865 if (!display) {
1866 av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
1867 "from X11 display %s.\n", XDisplayName(device));
1868 return AVERROR_UNKNOWN;
1869 }
1870
1871 av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
1872 "X11 display %s.\n", XDisplayName(device));
1873 }
1874 }
1875 #endif
1876
1877 #if HAVE_VAAPI_WIN32
1878 if (!display && try_win32) {
1879 // Try to create a display from the specified device, if any.
1880 if (!device) {
1881 display = vaGetDisplayWin32(NULL);
1882 } else {
1883 IDXGIFactory2 *pDXGIFactory = NULL;
1884 IDXGIAdapter *pAdapter = NULL;
1885 #if !HAVE_UWP
1886 HANDLE dxgi = dlopen("dxgi.dll", 0);
1887 if (!dxgi) {
1888 av_log(ctx, AV_LOG_ERROR, "Failed to load dxgi.dll\n");
1889 return AVERROR_UNKNOWN;
1890 }
1891 PFN_CREATE_DXGI_FACTORY pfnCreateDXGIFactory =
1892 (PFN_CREATE_DXGI_FACTORY)dlsym(dxgi, "CreateDXGIFactory");
1893 if (!pfnCreateDXGIFactory) {
1894 av_log(ctx, AV_LOG_ERROR, "CreateDXGIFactory load failed\n");
1895 dlclose(dxgi);
1896 return AVERROR_UNKNOWN;
1897 }
1898 #else
1899 // In UWP (which lacks LoadLibrary), CreateDXGIFactory isn't
1900 // available, only CreateDXGIFactory1
1901 PFN_CREATE_DXGI_FACTORY pfnCreateDXGIFactory =
1902 (PFN_CREATE_DXGI_FACTORY)CreateDXGIFactory1;
1903 #endif
1904 if (SUCCEEDED(pfnCreateDXGIFactory(&IID_IDXGIFactory2,
1905 (void **)&pDXGIFactory))) {
1906 int adapter = atoi(device);
1907 if (SUCCEEDED(IDXGIFactory2_EnumAdapters(pDXGIFactory,
1908 adapter,
1909 &pAdapter))) {
1910 DXGI_ADAPTER_DESC desc;
1911 if (SUCCEEDED(IDXGIAdapter2_GetDesc(pAdapter, &desc))) {
1912 av_log(ctx, AV_LOG_INFO,
1913 "Using device %04x:%04x (%ls) - LUID %lu %ld.\n",
1914 desc.VendorId, desc.DeviceId, desc.Description,
1915 desc.AdapterLuid.LowPart,
1916 desc.AdapterLuid.HighPart);
1917 display = vaGetDisplayWin32(&desc.AdapterLuid);
1918 }
1919 IDXGIAdapter_Release(pAdapter);
1920 }
1921 IDXGIFactory2_Release(pDXGIFactory);
1922 }
1923 #if !HAVE_UWP
1924 dlclose(dxgi);
1925 #endif
1926 }
1927
1928 if (!display) {
1929 av_log(ctx, AV_LOG_ERROR, "Cannot open a VA display "
1930 "from Win32 display.\n");
1931 return AVERROR_UNKNOWN;
1932 }
1933
1934 av_log(ctx, AV_LOG_VERBOSE, "Opened VA display via "
1935 "Win32 display.\n");
1936 }
1937 #endif
1938
1939 if (!display) {
1940 if (device)
1941 av_log(ctx, AV_LOG_ERROR, "No VA display found for "
1942 "device %s.\n", device);
1943 else
1944 av_log(ctx, AV_LOG_ERROR, "No VA display found for "
1945 "any default device.\n");
1946 return AVERROR(EINVAL);
1947 }
1948
1949 ent = av_dict_get(opts, "driver", NULL, 0);
1950 if (ent) {
1951 #if VA_CHECK_VERSION(0, 38, 0)
1952 VAStatus vas;
1953 vas = vaSetDriverName(display, ent->value);
1954 if (vas != VA_STATUS_SUCCESS) {
1955 av_log(ctx, AV_LOG_ERROR, "Failed to set driver name to "
1956 "%s: %d (%s).\n", ent->value, vas, vaErrorStr(vas));
1957 vaTerminate(display);
1958 return AVERROR_EXTERNAL;
1959 }
1960 #else
1961 av_log(ctx, AV_LOG_WARNING, "Driver name setting is not "
1962 "supported with this VAAPI version.\n");
1963 #endif
1964 }
1965
1966 return vaapi_device_connect(ctx, display);
1967 }
1968
1969 static int vaapi_device_derive(AVHWDeviceContext *ctx,
1970 AVHWDeviceContext *src_ctx,
1971 AVDictionary *opts, int flags)
1972 {
1973 #if HAVE_VAAPI_DRM
1974 if (src_ctx->type == AV_HWDEVICE_TYPE_DRM) {
1975 AVDRMDeviceContext *src_hwctx = src_ctx->hwctx;
1976 VADisplay *display;
1977 VAAPIDevicePriv *priv;
1978 int fd;
1979
1980 if (src_hwctx->fd < 0) {
1981 av_log(ctx, AV_LOG_ERROR, "DRM instance requires an associated "
1982 "device to derive a VA display from.\n");
1983 return AVERROR(EINVAL);
1984 }
1985
1986 #if CONFIG_LIBDRM
1987 {
1988 int node_type = drmGetNodeTypeFromFd(src_hwctx->fd);
1989 char *render_node;
1990 if (node_type < 0) {
1991 av_log(ctx, AV_LOG_ERROR, "DRM instance fd does not appear "
1992 "to refer to a DRM device.\n");
1993 return AVERROR(EINVAL);
1994 }
1995 if (node_type == DRM_NODE_RENDER) {
1996 fd = src_hwctx->fd;
1997 } else {
1998 render_node = drmGetRenderDeviceNameFromFd(src_hwctx->fd);
1999 if (!render_node) {
2000 av_log(ctx, AV_LOG_VERBOSE, "Using non-render node "
2001 "because the device does not have an "
2002 "associated render node.\n");
2003 fd = src_hwctx->fd;
2004 } else {
2005 fd = open(render_node, O_RDWR);
2006 if (fd < 0) {
2007 av_log(ctx, AV_LOG_VERBOSE, "Using non-render node "
2008 "because the associated render node "
2009 "could not be opened.\n");
2010 fd = src_hwctx->fd;
2011 } else {
2012 av_log(ctx, AV_LOG_VERBOSE, "Using render node %s "
2013 "in place of non-render DRM device.\n",
2014 render_node);
2015 }
2016 free(render_node);
2017 }
2018 }
2019 }
2020 #else
2021 fd = src_hwctx->fd;
2022 #endif
2023
2024 priv = av_mallocz(sizeof(*priv));
2025 if (!priv) {
2026 if (fd != src_hwctx->fd) {
2027 // The fd was opened in this function.
2028 close(fd);
2029 }
2030 return AVERROR(ENOMEM);
2031 }
2032
2033 if (fd == src_hwctx->fd) {
2034 // The fd is inherited from the source context and we are holding
2035 // a reference to that, we don't want to close it from here.
2036 priv->drm_fd = -1;
2037 } else {
2038 priv->drm_fd = fd;
2039 }
2040
2041 ctx->user_opaque = priv;
2042 ctx->free = &vaapi_device_free;
2043
2044 display = vaGetDisplayDRM(fd);
2045 if (!display) {
2046 av_log(ctx, AV_LOG_ERROR, "Failed to open a VA display from "
2047 "DRM device.\n");
2048 return AVERROR(EIO);
2049 }
2050
2051 return vaapi_device_connect(ctx, display);
2052 }
2053 #endif
2054 return AVERROR(ENOSYS);
2055 }
2056
2057 const HWContextType ff_hwcontext_type_vaapi = {
2058 .type = AV_HWDEVICE_TYPE_VAAPI,
2059 .name = "VAAPI",
2060
2061 .device_hwctx_size = sizeof(VAAPIDeviceContext),
2062 .device_hwconfig_size = sizeof(AVVAAPIHWConfig),
2063 .frames_hwctx_size = sizeof(VAAPIFramesContext),
2064
2065 .device_create = &vaapi_device_create,
2066 .device_derive = &vaapi_device_derive,
2067 .device_init = &vaapi_device_init,
2068 .device_uninit = &vaapi_device_uninit,
2069 .frames_get_constraints = &vaapi_frames_get_constraints,
2070 .frames_init = &vaapi_frames_init,
2071 .frames_uninit = &vaapi_frames_uninit,
2072 .frames_get_buffer = &vaapi_get_buffer,
2073 .transfer_get_formats = &vaapi_transfer_get_formats,
2074 .transfer_data_to = &vaapi_transfer_data_to,
2075 .transfer_data_from = &vaapi_transfer_data_from,
2076 .map_to = &vaapi_map_to,
2077 .map_from = &vaapi_map_from,
2078
2079 .pix_fmts = (const enum AVPixelFormat[]) {
2080 AV_PIX_FMT_VAAPI,
2081 AV_PIX_FMT_NONE
2082 },
2083 };
2084

8月18日什么星座 樊字五行属什么 没什么大不了的 二尖瓣反流什么意思 临床医学学什么
胆囊炎什么症状 甲减长期服用优甲乐有什么危害 副鼻窦炎症是什么意思 奶瓶pp和ppsu有什么区别 居住证是什么
羊肉炖什么补肾壮阳 看守所和拘留所有什么区别 嘴硬是什么意思 吃生红枣有什么好处 pv是什么材质
补骨头吃什么最好 为什么心细的男人危险 滑石粉是什么 眼镜片什么材质的好 显赫是什么意思
黄金芽是什么茶zsyouku.com 无字五行属什么hcv8jop1ns6r.cn 反复发烧是什么原因hcv7jop5ns6r.cn 手脱皮用什么药好得快hcv8jop4ns2r.cn 检车需要什么手续jinxinzhichuang.com
乙肝五项25阳性是什么意思hcv7jop6ns8r.cn 冷漠是什么意思hcv8jop8ns0r.cn 梦见买黄金是什么兆头0297y7.com 什么的灵魂hcv7jop7ns1r.cn 过生日吃什么菜寓意好hcv9jop1ns0r.cn
钢铁锅含眼泪喊修瓢锅这是什么歌hcv7jop5ns1r.cn 破伤风疫苗什么时候打hcv9jop5ns1r.cn 血清碱性磷酸酶高是什么意思hcv9jop6ns6r.cn 活血化瘀吃什么cl108k.com 补气血用什么泡水喝hcv8jop4ns9r.cn
金蝉脱壳比喻什么hcv9jop6ns0r.cn 什么耳机比较好hcv8jop1ns0r.cn 5月30是什么星座hcv9jop6ns6r.cn 为什么月经期有性冲动96micro.com 心脏神经官能症吃什么药onlinewuye.com
百度