History

vo: hwdec: drmprime: add separate hwdecs for v4l2request

With all the machinery in place, we can now add the v4l2request hwdecs with a different hw device type, and a different initialisation path. This applies to both the drmprime and drmprime_overlay hwdecs. At the moment, the device initialisation is done in the bare minimum way, but it can be extended to take a device path (for example) if that makes sense as we better understand what meaningful configuration will be.

Philip Langdale committed 2 years agompv-0.40.0-v4l2request

Commit bb4e53c1 parent ad0dc6c7 files · +212 −41Browse files

Unified · Split

7 files
  1. video/hwdec.c +3 −0
  2. video/hwdec.h +1 −0
  3. video/out/gpu/hwdec.c +6 −0
  4. video/out/hwdec/hwdec_drmprime.c +94 −31
  5. video/out/hwdec/hwdec_drmprime_overlay.c +71 −10
  6. video/out/vo_dmabuf_wayland.c +3 −0
  7. video/v4l2request.c +34 −0
video/hwdec.c+3−0
@@ -125,6 +125,9 @@ static const struct hwcontext_fns *const hwcontext_fns[] = { · 124 unmodified lines
125#if HAVE_DRM125#if HAVE_DRM
126 &hwcontext_fns_drmprime,126 &hwcontext_fns_drmprime,
127#endif127#endif
128#if HAVE_V4L2REQUEST
129 &hwcontext_fns_v4l2request,
130#endif
128#if HAVE_VAAPI131#if HAVE_VAAPI
129 &hwcontext_fns_vaapi,132 &hwcontext_fns_vaapi,
130#endif133#endif
video/hwdec.h+1−0
@@ -121,6 +121,7 @@ extern const struct hwcontext_fns hwcontext_fns_cuda; · 120 unmodified lines
121extern const struct hwcontext_fns hwcontext_fns_d3d11;121extern const struct hwcontext_fns hwcontext_fns_d3d11;
122extern const struct hwcontext_fns hwcontext_fns_drmprime;122extern const struct hwcontext_fns hwcontext_fns_drmprime;
123extern const struct hwcontext_fns hwcontext_fns_dxva2;123extern const struct hwcontext_fns hwcontext_fns_dxva2;
124extern const struct hwcontext_fns hwcontext_fns_v4l2request;
124extern const struct hwcontext_fns hwcontext_fns_vaapi;125extern const struct hwcontext_fns hwcontext_fns_vaapi;
125extern const struct hwcontext_fns hwcontext_fns_vdpau;126extern const struct hwcontext_fns hwcontext_fns_vdpau;
126 127
video/out/gpu/hwdec.c+6−0
@@ -38,6 +38,8 @@ extern const struct ra_hwdec_driver ra_hwdec_drmprime; · 37 unmodified lines
38extern const struct ra_hwdec_driver ra_hwdec_drmprime_overlay;38extern const struct ra_hwdec_driver ra_hwdec_drmprime_overlay;
39extern const struct ra_hwdec_driver ra_hwdec_aimagereader;39extern const struct ra_hwdec_driver ra_hwdec_aimagereader;
40extern const struct ra_hwdec_driver ra_hwdec_vulkan;40extern const struct ra_hwdec_driver ra_hwdec_vulkan;
41extern const struct ra_hwdec_driver ra_hwdec_v4l2request;
42extern const struct ra_hwdec_driver ra_hwdec_v4l2request_overlay;
41 43
42const struct ra_hwdec_driver *const ra_hwdec_drivers[] = {44const struct ra_hwdec_driver *const ra_hwdec_drivers[] = {
43#if HAVE_VAAPI45#if HAVE_VAAPI
@@ -73,6 +75,10 @@ const struct ra_hwdec_driver *const ra_hwdec_drivers[] = { · 29 unmodified lines
73 &ra_hwdec_drmprime,75 &ra_hwdec_drmprime,
74 &ra_hwdec_drmprime_overlay,76 &ra_hwdec_drmprime_overlay,
75#endif77#endif
78#if HAVE_V4L2REQUEST
79 &ra_hwdec_v4l2request,
80 &ra_hwdec_v4l2request_overlay,
81#endif
76#if HAVE_ANDROID_MEDIA_NDK82#if HAVE_ANDROID_MEDIA_NDK
77 &ra_hwdec_aimagereader,83 &ra_hwdec_aimagereader,
78#endif84#endif
video/out/hwdec/hwdec_drmprime.c+94−31
@@ -77,7 +77,7 @@ static const char *forked_pix_fmt_names[] = { · 76 unmodified lines
77 "rpi4_10",77 "rpi4_10",
78};78};
79 79
80static int init(struct ra_hwdec *hw)80static int pre_init(struct ra_hwdec *hw)
81{81{
82 struct priv_owner *p = hw->priv;82 struct priv_owner *p = hw->priv;
83 83
@@ -92,36 +92,12 @@ static int init(struct ra_hwdec *hw) · 8 unmodified lines
92 return -1;92 return -1;
93 }93 }
94 94
95 /*95 return 0;
96 * The drm_params resource is not provided when using X11 or Wayland, but96}
97 * there are extensions that supposedly provide this information from the
98 * drivers. Not properly documented. Of course.
99 */
100 mpv_opengl_drm_params_v2 *params = ra_get_native_resource(hw->ra_ctx->ra,
101 "drm_params_v2");
102
103 /*
104 * Respect drm_device option, so there is a way to control this when not
105 * using a DRM gpu context. If drm_params_v2 are present, they will already
106 * respect this option.
107 */
108 void *tmp = talloc_new(NULL);
109 struct drm_opts *drm_opts = mp_get_config_group(tmp, hw->global, &drm_conf);
110 const char *opt_path = drm_opts->device_path;
111
112 const char *device_path = params && params->render_fd > -1 ?
113 drmGetRenderDeviceNameFromFd(params->render_fd) :
114 opt_path ? opt_path : "/dev/dri/renderD128";
115 MP_VERBOSE(hw, "Using DRM device: %s\n", device_path);
116 97
117 int ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,98static int post_init(struct ra_hwdec *hw)
118 AV_HWDEVICE_TYPE_DRM,99{
119 device_path, NULL, 0);100 struct priv_owner *p = hw->priv;
120 talloc_free(tmp);
121 if (ret != 0) {
122 MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
123 return -1;
124 }
125 101
126 /*102 /*
127 * At the moment, there is no way to discover compatible formats103 * At the moment, there is no way to discover compatible formats
@@ -154,6 +130,75 @@ static int init(struct ra_hwdec *hw) · 26 unmodified lines
154 return 0;130 return 0;
155}131}
156 132
133static int init_drmprime(struct ra_hwdec *hw)
134{
135 struct priv_owner *p = hw->priv;
136
137 int ret = pre_init(hw);
138 if (ret < 0)
139 return ret;
140
141 /*
142 * The drm_params resource is not provided when using X11 or Wayland, but
143 * there are extensions that supposedly provide this information from the
144 * drivers. Not properly documented. Of course.
145 */
146 mpv_opengl_drm_params_v2 *params = ra_get_native_resource(hw->ra_ctx->ra,
147 "drm_params_v2");
148
149 /*
150 * Respect drm_device option, so there is a way to control this when not
151 * using a DRM gpu context. If drm_params_v2 are present, they will already
152 * respect this option.
153 */
154 void *tmp = talloc_new(NULL);
155 struct drm_opts *drm_opts = mp_get_config_group(tmp, hw->global, &drm_conf);
156 const char *opt_path = drm_opts->device_path;
157
158 const char *device_path = params && params->render_fd > -1 ?
159 drmGetRenderDeviceNameFromFd(params->render_fd) :
160 opt_path ? opt_path : "/dev/dri/renderD128";
161 MP_VERBOSE(hw, "Using DRM device: %s\n", device_path);
162
163 ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
164 AV_HWDEVICE_TYPE_DRM,
165 device_path, NULL, 0);
166 talloc_free(tmp);
167 if (ret < 0) {
168 MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
169 return ret;
170 }
171
172 return post_init(hw);
173}
174
175#if HAVE_V4L2REQUEST
176static int init_v4l2request(struct ra_hwdec *hw)
177{
178 struct priv_owner *p = hw->priv;
179
180 int ret = pre_init(hw);
181 if (ret < 0)
182 return ret;
183
184 /*
185 * AVCodecHWConfig contains a combo of a pixel format and hwdevice type,
186 * correct type must be created here or hwaccel will fail.
187 *
188 * FIXME: Create hwdevice based on type in AVCodecHWConfig
189 */
190 ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
191 AV_HWDEVICE_TYPE_V4L2REQUEST,
192 NULL, NULL, 0);
193 if (ret < 0) {
194 MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
195 return ret;
196 }
197
198 return post_init(hw);
199}
200#endif
201
157static void mapper_unmap(struct ra_hwdec_mapper *mapper)202static void mapper_unmap(struct ra_hwdec_mapper *mapper)
158{203{
159 struct priv_owner *p_owner = mapper->owner->priv;204 struct priv_owner *p_owner = mapper->owner->priv;
@@ -308,7 +353,7 @@ const struct ra_hwdec_driver ra_hwdec_drmprime = { · 148 unmodified lines
308 .priv_size = sizeof(struct priv_owner),353 .priv_size = sizeof(struct priv_owner),
309 .imgfmts = {IMGFMT_DRMPRIME, 0},354 .imgfmts = {IMGFMT_DRMPRIME, 0},
310 .device_type = AV_HWDEVICE_TYPE_DRM,355 .device_type = AV_HWDEVICE_TYPE_DRM,
311 .init = init,356 .init = init_drmprime,
312 .uninit = uninit,357 .uninit = uninit,
313 .mapper = &(const struct ra_hwdec_mapper_driver){358 .mapper = &(const struct ra_hwdec_mapper_driver){
314 .priv_size = sizeof(struct dmabuf_interop_priv),359 .priv_size = sizeof(struct dmabuf_interop_priv),
@@ -318,3 +363,21 @@ const struct ra_hwdec_driver ra_hwdec_drmprime = { · 3 unmodified lines
318 .unmap = mapper_unmap,363 .unmap = mapper_unmap,
319 },364 },
320};365};
366
367#if HAVE_V4L2REQUEST
368const struct ra_hwdec_driver ra_hwdec_v4l2request = {
369 .name = "v4l2request",
370 .priv_size = sizeof(struct priv_owner),
371 .imgfmts = {IMGFMT_DRMPRIME, 0},
372 .device_type = AV_HWDEVICE_TYPE_V4L2REQUEST,
373 .init = init_v4l2request,
374 .uninit = uninit,
375 .mapper = &(const struct ra_hwdec_mapper_driver){
376 .priv_size = sizeof(struct dmabuf_interop_priv),
377 .init = mapper_init,
378 .uninit = mapper_uninit,
379 .map = mapper_map,
380 .unmap = mapper_unmap,
381 },
382};
383#endif
video/out/hwdec/hwdec_drmprime_overlay.c+71−10
@@ -246,7 +246,7 @@ static void uninit(struct ra_hwdec *hw) · 245 unmodified lines
246 }246 }
247}247}
248 248
249static int init(struct ra_hwdec *hw)249static int pre_init(struct ra_hwdec *hw)
250{250{
251 struct priv *p = hw->priv;251 struct priv *p = hw->priv;
252 int draw_plane, drmprime_video_plane;252 int draw_plane, drmprime_video_plane;
@@ -267,15 +267,15 @@ static int init(struct ra_hwdec *hw) · 14 unmodified lines
267 drm_params->connector_id, draw_plane, drmprime_video_plane);267 drm_params->connector_id, draw_plane, drmprime_video_plane);
268 if (!p->ctx) {268 if (!p->ctx) {
269 mp_err(p->log, "Failed to retrieve DRM atomic context.\n");269 mp_err(p->log, "Failed to retrieve DRM atomic context.\n");
270 goto err;270 return -1;
271 }271 }
272 if (!p->ctx->drmprime_video_plane) {272 if (!p->ctx->drmprime_video_plane) {
273 mp_warn(p->log, "No drmprime video plane. You might need to specify it manually using --drm-drmprime-video-plane\n");273 mp_warn(p->log, "No drmprime video plane. You might need to specify it manually using --drm-drmprime-video-plane\n");
274 goto err;274 return -1;
275 }275 }
276 } else {276 } else {
277 mp_verbose(p->log, "Failed to retrieve DRM fd from native display.\n");277 mp_verbose(p->log, "Failed to retrieve DRM fd from native display.\n");
278 goto err;278 return -1;
279 }279 }
280 280
281 drmModeCrtcPtr crtc;281 drmModeCrtcPtr crtc;
@@ -289,7 +289,7 @@ static int init(struct ra_hwdec *hw) · 7 unmodified lines
289 uint64_t has_prime;289 uint64_t has_prime;
290 if (drmGetCap(p->ctx->fd, DRM_CAP_PRIME, &has_prime) < 0) {290 if (drmGetCap(p->ctx->fd, DRM_CAP_PRIME, &has_prime) < 0) {
291 MP_ERR(hw, "Card does not support prime handles.\n");291 MP_ERR(hw, "Card does not support prime handles.\n");
292 goto err;292 return -1;
293 }293 }
294 294
295 if (has_prime) {295 if (has_prime) {
@@ -298,19 +298,67 @@ static int init(struct ra_hwdec *hw) · 2 unmodified lines
298 298
299 disable_video_plane(hw);299 disable_video_plane(hw);
300 300
301 return 0;
302}
303
304static int init_drmprime(struct ra_hwdec *hw)
305{
306 struct priv *p = hw->priv;
307
308 int ret = pre_init(hw);
309 if (ret < 0)
310 goto err;
311
301 p->hwctx = (struct mp_hwdec_ctx) {312 p->hwctx = (struct mp_hwdec_ctx) {
302 .driver_name = hw->driver->name,313 .driver_name = hw->driver->name,
303 .hw_imgfmt = IMGFMT_DRMPRIME,314 .hw_imgfmt = IMGFMT_DRMPRIME,
304 };315 };
305 316
306 char *device = drmGetDeviceNameFromFd2(p->ctx->fd);317 char *device = drmGetDeviceNameFromFd2(p->ctx->fd);
307 int ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,318 ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
308 AV_HWDEVICE_TYPE_DRM, device, NULL, 0);319 AV_HWDEVICE_TYPE_DRM, device, NULL, 0);
309 320
310 if (device)321 if (device)
311 free(device);322 free(device);
312 323
313 if (ret != 0) {324 if (ret < 0) {
325 MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
326 goto err;
327 }
328
329 hwdec_devices_add(hw->devs, &p->hwctx);
330
331 return 0;
332
333err:
334 uninit(hw);
335 return ret;
336}
337
338#if HAVE_V4L2REQUEST
339static int init_v4l2request(struct ra_hwdec *hw)
340{
341 struct priv *p = hw->priv;
342
343 int ret = pre_init(hw);
344 if (ret < 0)
345 goto err;
346
347 p->hwctx = (struct mp_hwdec_ctx) {
348 .driver_name = hw->driver->name,
349 .hw_imgfmt = IMGFMT_DRMPRIME,
350 };
351
352 /*
353 * AVCodecHWConfig contains a combo of a pixel format and hwdevice type,
354 * correct type must be created here or hwaccel will fail.
355 *
356 * FIXME: Create hwdevice based on type in AVCodecHWConfig
357 */
358 ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
359 AV_HWDEVICE_TYPE_V4L2REQUEST,
360 NULL, NULL, 0);
361 if (ret < 0) {
314 MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));362 MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
315 goto err;363 goto err;
316 }364 }
@@ -321,15 +369,28 @@ static int init(struct ra_hwdec *hw) · 4 unmodified lines
321 369
322err:370err:
323 uninit(hw);371 uninit(hw);
324 return -1;372 return ret;
325}373}
374#endif
326 375
327const struct ra_hwdec_driver ra_hwdec_drmprime_overlay = {376const struct ra_hwdec_driver ra_hwdec_drmprime_overlay = {
328 .name = "drmprime-overlay",377 .name = "drmprime-overlay",
329 .priv_size = sizeof(struct priv),378 .priv_size = sizeof(struct priv),
330 .imgfmts = {IMGFMT_DRMPRIME, 0},379 .imgfmts = {IMGFMT_DRMPRIME, 0},
331 .device_type = AV_HWDEVICE_TYPE_DRM,380 .device_type = AV_HWDEVICE_TYPE_DRM,
332 .init = init,381 .init = init_drmprime,
382 .overlay_frame = overlay_frame,
383 .uninit = uninit,
384};
385
386#if HAVE_V4L2REQUEST
387const struct ra_hwdec_driver ra_hwdec_v4l2request_overlay = {
388 .name = "v4l2request-overlay",
389 .priv_size = sizeof(struct priv),
390 .imgfmts = {IMGFMT_DRMPRIME, 0},
391 .device_type = AV_HWDEVICE_TYPE_V4L2REQUEST,
392 .init = init_v4l2request,
333 .overlay_frame = overlay_frame,393 .overlay_frame = overlay_frame,
334 .uninit = uninit,394 .uninit = uninit,
335};395};
396#endif
video/out/vo_dmabuf_wayland.c+3−0
@@ -52,6 +52,7 @@ enum hwdec_type { · 51 unmodified lines
52 HWDEC_NONE,52 HWDEC_NONE,
53 HWDEC_VAAPI,53 HWDEC_VAAPI,
54 HWDEC_DRMPRIME,54 HWDEC_DRMPRIME,
55 HWDEC_V4L2REQUEST,
55};56};
56 57
57struct buffer {58struct buffer {
@@ -843,6 +844,8 @@ static int preinit(struct vo *vo) · 785 unmodified lines
843 p->hwdec_type = HWDEC_VAAPI;844 p->hwdec_type = HWDEC_VAAPI;
844 } else if (strcmp(hw->driver->name, "drmprime") == 0) {845 } else if (strcmp(hw->driver->name, "drmprime") == 0) {
845 p->hwdec_type = HWDEC_DRMPRIME;846 p->hwdec_type = HWDEC_DRMPRIME;
847 } else if (strcmp(hw->driver->name, "v4l2request") == 0) {
848 p->hwdec_type = HWDEC_V4L2REQUEST;
846 }849 }
847 }850 }
848 851
video/v4l2request.c+34−0
@@ -0,0 +1,34 @@
1/*
2 * This file is part of mpv.
3 *
4 * mpv 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 * mpv 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
12 * GNU 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 mpv. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <libavutil/hwcontext.h>
19
20#include "hwdec.h"
21
22static struct AVBufferRef *v4l2request_create_standalone(struct mpv_global *global,
23 struct mp_log *log, struct hwcontext_create_dev_params *params)
24{
25 AVBufferRef* ref = NULL;
26 av_hwdevice_ctx_create(&ref, AV_HWDEVICE_TYPE_V4L2REQUEST, NULL, NULL, 0);
27
28 return ref;
29}
30
31const struct hwcontext_fns hwcontext_fns_v4l2request = {
32 .av_hwdevice_type = AV_HWDEVICE_TYPE_V4L2REQUEST,
33 .create_dev = v4l2request_create_standalone,
34};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t