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
125125 #if HAVE_DRM
126126 &hwcontext_fns_drmprime,
127127 #endif
128+#if HAVE_V4L2REQUEST
129+ &hwcontext_fns_v4l2request,
130+#endif
128131 #if HAVE_VAAPI
129132 &hwcontext_fns_vaapi,
130133 #endif
video/hwdec.h+1−0
@@ -121,6 +121,7 @@ extern const struct hwcontext_fns hwcontext_fns_cuda; · 120 unmodified lines
121121 extern const struct hwcontext_fns hwcontext_fns_d3d11;
122122 extern const struct hwcontext_fns hwcontext_fns_drmprime;
123123 extern const struct hwcontext_fns hwcontext_fns_dxva2;
124+extern const struct hwcontext_fns hwcontext_fns_v4l2request;
124125 extern const struct hwcontext_fns hwcontext_fns_vaapi;
125126 extern const struct hwcontext_fns hwcontext_fns_vdpau;
126127
video/out/gpu/hwdec.c+6−0
@@ -38,6 +38,8 @@ extern const struct ra_hwdec_driver ra_hwdec_drmprime; · 37 unmodified lines
3838 extern const struct ra_hwdec_driver ra_hwdec_drmprime_overlay;
3939 extern const struct ra_hwdec_driver ra_hwdec_aimagereader;
4040 extern const struct ra_hwdec_driver ra_hwdec_vulkan;
41+extern const struct ra_hwdec_driver ra_hwdec_v4l2request;
42+extern const struct ra_hwdec_driver ra_hwdec_v4l2request_overlay;
4143
4244 const struct ra_hwdec_driver *const ra_hwdec_drivers[] = {
4345 #if HAVE_VAAPI
@@ -73,6 +75,10 @@ const struct ra_hwdec_driver *const ra_hwdec_drivers[] = { · 29 unmodified lines
7375 &ra_hwdec_drmprime,
7476 &ra_hwdec_drmprime_overlay,
7577 #endif
78+#if HAVE_V4L2REQUEST
79+ &ra_hwdec_v4l2request,
80+ &ra_hwdec_v4l2request_overlay,
81+#endif
7682 #if HAVE_ANDROID_MEDIA_NDK
7783 &ra_hwdec_aimagereader,
7884 #endif
video/out/hwdec/hwdec_drmprime.c+94−31
@@ -77,7 +77,7 @@ static const char *forked_pix_fmt_names[] = { · 76 unmodified lines
7777 "rpi4_10",
7878 };
7979
80−static int init(struct ra_hwdec *hw)
80+static int pre_init(struct ra_hwdec *hw)
8181 {
8282 struct priv_owner *p = hw->priv;
8383
@@ -92,36 +92,12 @@ static int init(struct ra_hwdec *hw) · 8 unmodified lines
9292 return -1;
9393 }
9494
95− /*
96− * The drm_params resource is not provided when using X11 or Wayland, but
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);
95+ return 0;
96+}
11697
117− int ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
118− AV_HWDEVICE_TYPE_DRM,
119− device_path, NULL, 0);
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− }
98+static int post_init(struct ra_hwdec *hw)
99+{
100+ struct priv_owner *p = hw->priv;
125101
126102 /*
127103 * 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
154130 return 0;
155131 }
156132
133+static 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
176+static 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+
157202 static void mapper_unmap(struct ra_hwdec_mapper *mapper)
158203 {
159204 struct priv_owner *p_owner = mapper->owner->priv;
@@ -308,7 +353,7 @@ const struct ra_hwdec_driver ra_hwdec_drmprime = { · 148 unmodified lines
308353 .priv_size = sizeof(struct priv_owner),
309354 .imgfmts = {IMGFMT_DRMPRIME, 0},
310355 .device_type = AV_HWDEVICE_TYPE_DRM,
311− .init = init,
356+ .init = init_drmprime,
312357 .uninit = uninit,
313358 .mapper = &(const struct ra_hwdec_mapper_driver){
314359 .priv_size = sizeof(struct dmabuf_interop_priv),
@@ -318,3 +363,21 @@ const struct ra_hwdec_driver ra_hwdec_drmprime = { · 3 unmodified lines
318363 .unmap = mapper_unmap,
319364 },
320365 };
366+
367+#if HAVE_V4L2REQUEST
368+const 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
246246 }
247247 }
248248
249−static int init(struct ra_hwdec *hw)
249+static int pre_init(struct ra_hwdec *hw)
250250 {
251251 struct priv *p = hw->priv;
252252 int draw_plane, drmprime_video_plane;
@@ -267,15 +267,15 @@ static int init(struct ra_hwdec *hw) · 14 unmodified lines
267267 drm_params->connector_id, draw_plane, drmprime_video_plane);
268268 if (!p->ctx) {
269269 mp_err(p->log, "Failed to retrieve DRM atomic context.\n");
270− goto err;
270+ return -1;
271271 }
272272 if (!p->ctx->drmprime_video_plane) {
273273 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;
275275 }
276276 } else {
277277 mp_verbose(p->log, "Failed to retrieve DRM fd from native display.\n");
278− goto err;
278+ return -1;
279279 }
280280
281281 drmModeCrtcPtr crtc;
@@ -289,7 +289,7 @@ static int init(struct ra_hwdec *hw) · 7 unmodified lines
289289 uint64_t has_prime;
290290 if (drmGetCap(p->ctx->fd, DRM_CAP_PRIME, &has_prime) < 0) {
291291 MP_ERR(hw, "Card does not support prime handles.\n");
292− goto err;
292+ return -1;
293293 }
294294
295295 if (has_prime) {
@@ -298,19 +298,67 @@ static int init(struct ra_hwdec *hw) · 2 unmodified lines
298298
299299 disable_video_plane(hw);
300300
301+ return 0;
302+}
303+
304+static 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+
301312 p->hwctx = (struct mp_hwdec_ctx) {
302313 .driver_name = hw->driver->name,
303314 .hw_imgfmt = IMGFMT_DRMPRIME,
304315 };
305316
306317 char *device = drmGetDeviceNameFromFd2(p->ctx->fd);
307− int ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
308− AV_HWDEVICE_TYPE_DRM, device, NULL, 0);
318+ ret = av_hwdevice_ctx_create(&p->hwctx.av_device_ref,
319+ AV_HWDEVICE_TYPE_DRM, device, NULL, 0);
309320
310321 if (device)
311322 free(device);
312323
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+
333+err:
334+ uninit(hw);
335+ return ret;
336+}
337+
338+#if HAVE_V4L2REQUEST
339+static 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) {
314362 MP_VERBOSE(hw, "Failed to create hwdevice_ctx: %s\n", av_err2str(ret));
315363 goto err;
316364 }
@@ -321,15 +369,28 @@ static int init(struct ra_hwdec *hw) · 4 unmodified lines
321369
322370 err:
323371 uninit(hw);
324− return -1;
372+ return ret;
325373 }
374+#endif
326375
327376 const struct ra_hwdec_driver ra_hwdec_drmprime_overlay = {
328377 .name = "drmprime-overlay",
329378 .priv_size = sizeof(struct priv),
330379 .imgfmts = {IMGFMT_DRMPRIME, 0},
331380 .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
387+const 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,
333393 .overlay_frame = overlay_frame,
334394 .uninit = uninit,
335395 };
396+#endif
video/out/vo_dmabuf_wayland.c+3−0
@@ -52,6 +52,7 @@ enum hwdec_type { · 51 unmodified lines
5252 HWDEC_NONE,
5353 HWDEC_VAAPI,
5454 HWDEC_DRMPRIME,
55+ HWDEC_V4L2REQUEST,
5556 };
5657
5758 struct buffer {
@@ -843,6 +844,8 @@ static int preinit(struct vo *vo) · 785 unmodified lines
843844 p->hwdec_type = HWDEC_VAAPI;
844845 } else if (strcmp(hw->driver->name, "drmprime") == 0) {
845846 p->hwdec_type = HWDEC_DRMPRIME;
847+ } else if (strcmp(hw->driver->name, "v4l2request") == 0) {
848+ p->hwdec_type = HWDEC_V4L2REQUEST;
846849 }
847850 }
848851
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+
22+static 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+
31+const 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