FFmpeg
kmsgrab.c
Go to the documentation of this file.
1 /*
2  * KMS/DRM input device
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <fcntl.h>
22 #include <unistd.h>
23 
24 #include <drm.h>
25 #include <drm_fourcc.h>
26 #include <drm_mode.h>
27 #include <xf86drm.h>
28 #include <xf86drmMode.h>
29 
30 // Required for compatibility when building against libdrm < 2.4.83.
31 #ifndef DRM_FORMAT_MOD_INVALID
32 #define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
33 #endif
34 
35 #include "libavutil/hwcontext.h"
37 #include "libavutil/internal.h"
38 #include "libavutil/mathematics.h"
39 #include "libavutil/opt.h"
40 #include "libavutil/pixfmt.h"
41 #include "libavutil/pixdesc.h"
42 #include "libavutil/time.h"
43 
44 #include "libavformat/avformat.h"
45 #include "libavformat/demux.h"
46 #include "libavformat/internal.h"
47 
48 typedef struct KMSGrabContext {
49  const AVClass *class;
50 
55 
58 
59  uint32_t plane_id;
60  uint32_t drm_format;
61  unsigned int width;
62  unsigned int height;
63 
64  int64_t frame_delay;
65  int64_t frame_last;
66 
67  const char *device_path;
70  int64_t source_plane;
71  int64_t source_crtc;
74 
75 static void kmsgrab_free_desc(void *opaque, uint8_t *data)
76 {
78  int i;
79 
80  for (i = 0; i < desc->nb_objects; i++)
81  close(desc->objects[i].fd);
82 
83  av_free(desc);
84 }
85 
86 static void kmsgrab_free_frame(void *opaque, uint8_t *data)
87 {
89 
91 }
92 
93 static int kmsgrab_get_fb(AVFormatContext *avctx,
94  drmModePlane *plane,
96 {
97  KMSGrabContext *ctx = avctx->priv_data;
98  drmModeFB *fb = NULL;
99  int err, fd;
100 
101  fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id);
102  if (!fb) {
103  err = errno;
104  av_log(avctx, AV_LOG_ERROR, "Failed to get framebuffer "
105  "%"PRIu32": %s.\n", plane->fb_id, strerror(err));
106  err = AVERROR(err);
107  goto fail;
108  }
109  if (fb->width != ctx->width || fb->height != ctx->height) {
110  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
111  "dimensions changed: now %"PRIu32"x%"PRIu32".\n",
112  ctx->plane_id, fb->width, fb->height);
113  err = AVERROR(EIO);
114  goto fail;
115  }
116  if (!fb->handle) {
117  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer.\n");
118  err = AVERROR(EIO);
119  goto fail;
120  }
121 
122  err = drmPrimeHandleToFD(ctx->hwctx->fd, fb->handle, O_RDONLY, &fd);
123  if (err < 0) {
124  err = errno;
125  av_log(avctx, AV_LOG_ERROR, "Failed to get PRIME fd from "
126  "framebuffer handle: %s.\n", strerror(err));
127  err = AVERROR(err);
128  goto fail;
129  }
130 
132  .nb_objects = 1,
133  .objects[0] = {
134  .fd = fd,
135  .size = fb->height * fb->pitch,
136  .format_modifier = ctx->drm_format_modifier,
137  },
138  .nb_layers = 1,
139  .layers[0] = {
140  .format = ctx->drm_format,
141  .nb_planes = 1,
142  .planes[0] = {
143  .object_index = 0,
144  .offset = 0,
145  .pitch = fb->pitch,
146  },
147  },
148  };
149 
150  err = 0;
151 fail:
152  drmModeFreeFB(fb);
153  return err;
154 }
155 
156 #if HAVE_LIBDRM_GETFB2
157 static int kmsgrab_get_fb2(AVFormatContext *avctx,
158  drmModePlane *plane,
160 {
161  KMSGrabContext *ctx = avctx->priv_data;
162  drmModeFB2 *fb;
163  int err, i, nb_objects;
164  uint64_t modifier = ctx->drm_format_modifier;
165 
166  fb = drmModeGetFB2(ctx->hwctx->fd, plane->fb_id);
167  if (!fb) {
168  err = errno;
169  av_log(avctx, AV_LOG_ERROR, "Failed to get framebuffer "
170  "%"PRIu32": %s.\n", plane->fb_id, strerror(err));
171  return AVERROR(err);
172  }
173  if (fb->pixel_format != ctx->drm_format) {
174  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
175  "format changed: now %"PRIx32".\n",
176  ctx->plane_id, fb->pixel_format);
177  err = AVERROR(EIO);
178  goto fail;
179  }
180  if (fb->width != ctx->width || fb->height != ctx->height) {
181  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
182  "dimensions changed: now %"PRIu32"x%"PRIu32".\n",
183  ctx->plane_id, fb->width, fb->height);
184  err = AVERROR(EIO);
185  goto fail;
186  }
187  if (!fb->handles[0]) {
188  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer.\n");
189  err = AVERROR(EIO);
190  goto fail;
191  }
192 
193  if (fb->flags & DRM_MODE_FB_MODIFIERS)
194  modifier = fb->modifier;
195 
197  .nb_layers = 1,
198  .layers[0] = {
199  .format = ctx->drm_format,
200  },
201  };
202 
203  nb_objects = 0;
204  for (i = 0; i < 4 && fb->handles[i]; i++) {
205  size_t size;
206  int dup = 0, j, obj;
207 
208  size = fb->offsets[i] + fb->height * fb->pitches[i];
209 
210  for (j = 0; j < i; j++) {
211  if (fb->handles[i] == fb->handles[j]) {
212  dup = 1;
213  break;
214  }
215  }
216  if (dup) {
217  obj = desc->layers[0].planes[j].object_index;
218 
219  if (desc->objects[j].size < size)
220  desc->objects[j].size = size;
221 
222  desc->layers[0].planes[i] = (AVDRMPlaneDescriptor) {
223  .object_index = obj,
224  .offset = fb->offsets[i],
225  .pitch = fb->pitches[i],
226  };
227 
228  } else {
229  int fd;
230  err = drmPrimeHandleToFD(ctx->hwctx->fd, fb->handles[i],
231  O_RDONLY, &fd);
232  if (err < 0) {
233  err = errno;
234  av_log(avctx, AV_LOG_ERROR, "Failed to get PRIME fd from "
235  "framebuffer handle: %s.\n", strerror(err));
236  err = AVERROR(err);
237  goto fail;
238  }
239 
240  obj = nb_objects++;
241  desc->objects[obj] = (AVDRMObjectDescriptor) {
242  .fd = fd,
243  .size = size,
244  .format_modifier = modifier,
245  };
246  desc->layers[0].planes[i] = (AVDRMPlaneDescriptor) {
247  .object_index = obj,
248  .offset = fb->offsets[i],
249  .pitch = fb->pitches[i],
250  };
251  }
252  }
253  desc->nb_objects = nb_objects;
254  desc->layers[0].nb_planes = i;
255 
256  err = 0;
257 fail:
258  drmModeFreeFB2(fb);
259  return err;
260 }
261 #endif
262 
264 {
265  KMSGrabContext *ctx = avctx->priv_data;
266  drmModePlane *plane = NULL;
268  AVFrame *frame = NULL;
269  int64_t now;
270  int err;
271 
272  now = av_gettime_relative();
273  if (ctx->frame_last) {
274  int64_t delay;
275  while (1) {
276  delay = ctx->frame_last + ctx->frame_delay - now;
277  if (delay <= 0)
278  break;
279  av_usleep(delay);
280  now = av_gettime_relative();
281  }
282  }
283  ctx->frame_last = now;
284  now = av_gettime();
285 
286  plane = drmModeGetPlane(ctx->hwctx->fd, ctx->plane_id);
287  if (!plane) {
288  err = errno;
289  av_log(avctx, AV_LOG_ERROR, "Failed to get plane "
290  "%"PRIu32": %s.\n", ctx->plane_id, strerror(err));
291  err = AVERROR(err);
292  goto fail;
293  }
294  if (!plane->fb_id) {
295  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" no longer has "
296  "an associated framebuffer.\n", ctx->plane_id);
297  err = AVERROR(EIO);
298  goto fail;
299  }
300 
301  desc = av_mallocz(sizeof(*desc));
302  if (!desc) {
303  err = AVERROR(ENOMEM);
304  goto fail;
305  }
306 
307 #if HAVE_LIBDRM_GETFB2
308  if (ctx->fb2_available)
309  err = kmsgrab_get_fb2(avctx, plane, desc);
310  else
311 #endif
312  err = kmsgrab_get_fb(avctx, plane, desc);
313  if (err < 0)
314  goto fail;
315 
316  frame = av_frame_alloc();
317  if (!frame) {
318  err = AVERROR(ENOMEM);
319  goto fail;
320  }
321 
322  frame->hw_frames_ctx = av_buffer_ref(ctx->frames_ref);
323  if (!frame->hw_frames_ctx) {
324  err = AVERROR(ENOMEM);
325  goto fail;
326  }
327 
328  frame->buf[0] = av_buffer_create((uint8_t*)desc, sizeof(*desc),
329  &kmsgrab_free_desc, avctx, 0);
330  if (!frame->buf[0]) {
331  err = AVERROR(ENOMEM);
332  goto fail;
333  }
334 
335  frame->data[0] = (uint8_t*)desc;
336  frame->format = AV_PIX_FMT_DRM_PRIME;
337  frame->width = ctx->width;
338  frame->height = ctx->height;
339 
340  drmModeFreePlane(plane);
341  plane = NULL;
342  desc = NULL;
343 
344  pkt->buf = av_buffer_create((uint8_t*)frame, sizeof(*frame),
345  &kmsgrab_free_frame, avctx, 0);
346  if (!pkt->buf) {
347  err = AVERROR(ENOMEM);
348  goto fail;
349  }
350 
351  pkt->data = (uint8_t*)frame;
352  pkt->size = sizeof(*frame);
353  pkt->pts = now;
355 
356  return 0;
357 
358 fail:
359  drmModeFreePlane(plane);
360  av_freep(&desc);
362  return err;
363 }
364 
365 static const struct {
367  uint32_t drm_format;
368 } kmsgrab_formats[] = {
369  // Monochrome.
370 #ifdef DRM_FORMAT_R8
371  { AV_PIX_FMT_GRAY8, DRM_FORMAT_R8 },
372 #endif
373 #ifdef DRM_FORMAT_R16
374  { AV_PIX_FMT_GRAY16LE, DRM_FORMAT_R16 },
375  { AV_PIX_FMT_GRAY16BE, DRM_FORMAT_R16 | DRM_FORMAT_BIG_ENDIAN },
376 #endif
377  // <8-bit RGB.
378  { AV_PIX_FMT_BGR8, DRM_FORMAT_BGR233 },
379  { AV_PIX_FMT_RGB555LE, DRM_FORMAT_XRGB1555 },
380  { AV_PIX_FMT_RGB555BE, DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN },
381  { AV_PIX_FMT_BGR555LE, DRM_FORMAT_XBGR1555 },
382  { AV_PIX_FMT_BGR555BE, DRM_FORMAT_XBGR1555 | DRM_FORMAT_BIG_ENDIAN },
383  { AV_PIX_FMT_RGB565LE, DRM_FORMAT_RGB565 },
384  { AV_PIX_FMT_RGB565BE, DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN },
385  { AV_PIX_FMT_BGR565LE, DRM_FORMAT_BGR565 },
386  { AV_PIX_FMT_BGR565BE, DRM_FORMAT_BGR565 | DRM_FORMAT_BIG_ENDIAN },
387  // 8-bit RGB.
388  { AV_PIX_FMT_RGB24, DRM_FORMAT_RGB888 },
389  { AV_PIX_FMT_BGR24, DRM_FORMAT_BGR888 },
390  { AV_PIX_FMT_0RGB, DRM_FORMAT_BGRX8888 },
391  { AV_PIX_FMT_0BGR, DRM_FORMAT_RGBX8888 },
392  { AV_PIX_FMT_RGB0, DRM_FORMAT_XBGR8888 },
393  { AV_PIX_FMT_BGR0, DRM_FORMAT_XRGB8888 },
394  { AV_PIX_FMT_ARGB, DRM_FORMAT_BGRA8888 },
395  { AV_PIX_FMT_ABGR, DRM_FORMAT_RGBA8888 },
396  { AV_PIX_FMT_RGBA, DRM_FORMAT_ABGR8888 },
397  { AV_PIX_FMT_BGRA, DRM_FORMAT_ARGB8888 },
398  // 10-bit RGB.
399  { AV_PIX_FMT_X2RGB10LE, DRM_FORMAT_XRGB2101010 },
400  { AV_PIX_FMT_X2RGB10BE, DRM_FORMAT_XRGB2101010 | DRM_FORMAT_BIG_ENDIAN },
401  // 8-bit YUV 4:2:0.
402  { AV_PIX_FMT_NV12, DRM_FORMAT_NV12 },
403  // 8-bit YUV 4:2:2.
404  { AV_PIX_FMT_YUYV422, DRM_FORMAT_YUYV },
405  { AV_PIX_FMT_YVYU422, DRM_FORMAT_YVYU },
406  { AV_PIX_FMT_UYVY422, DRM_FORMAT_UYVY },
407 };
408 
410 {
411  KMSGrabContext *ctx = avctx->priv_data;
412  drmModePlaneRes *plane_res = NULL;
413  drmModePlane *plane = NULL;
414  drmModeFB *fb = NULL;
415 #if HAVE_LIBDRM_GETFB2
416  drmModeFB2 *fb2 = NULL;
417 #endif
418  AVStream *stream;
419  int err, i;
420 
421  err = av_hwdevice_ctx_create(&ctx->device_ref, AV_HWDEVICE_TYPE_DRM,
422  ctx->device_path, NULL, 0);
423  if (err < 0) {
424  av_log(avctx, AV_LOG_ERROR, "Failed to open DRM device.\n");
425  return err;
426  }
427  ctx->device = (AVHWDeviceContext*) ctx->device_ref->data;
428  ctx->hwctx = (AVDRMDeviceContext*)ctx->device->hwctx;
429 
430  err = drmSetClientCap(ctx->hwctx->fd,
431  DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
432  if (err < 0) {
433  av_log(avctx, AV_LOG_WARNING, "Failed to set universal planes "
434  "capability: primary planes will not be usable.\n");
435  }
436 
437  if (ctx->source_plane > 0) {
438  plane = drmModeGetPlane(ctx->hwctx->fd, ctx->source_plane);
439  if (!plane) {
440  err = errno;
441  av_log(avctx, AV_LOG_ERROR, "Failed to get plane %"PRId64": "
442  "%s.\n", ctx->source_plane, strerror(err));
443  err = AVERROR(err);
444  goto fail;
445  }
446 
447  if (plane->fb_id == 0) {
448  av_log(avctx, AV_LOG_ERROR, "Plane %"PRId64" does not have "
449  "an attached framebuffer.\n", ctx->source_plane);
450  err = AVERROR(EINVAL);
451  goto fail;
452  }
453  } else {
454  plane_res = drmModeGetPlaneResources(ctx->hwctx->fd);
455  if (!plane_res) {
456  err = errno;
457  av_log(avctx, AV_LOG_ERROR, "Failed to get plane "
458  "resources: %s.\n", strerror(err));
459  err = AVERROR(err);
460  goto fail;
461  }
462 
463  for (i = 0; i < plane_res->count_planes; i++) {
464  plane = drmModeGetPlane(ctx->hwctx->fd,
465  plane_res->planes[i]);
466  if (!plane) {
467  err = errno;
468  av_log(avctx, AV_LOG_VERBOSE, "Failed to get "
469  "plane %"PRIu32": %s.\n",
470  plane_res->planes[i], strerror(err));
471  continue;
472  }
473 
474  av_log(avctx, AV_LOG_DEBUG, "Plane %"PRIu32": "
475  "CRTC %"PRIu32" FB %"PRIu32".\n",
476  plane->plane_id, plane->crtc_id, plane->fb_id);
477 
478  if ((ctx->source_crtc > 0 &&
479  plane->crtc_id != ctx->source_crtc) ||
480  plane->fb_id == 0) {
481  // Either not connected to the target source CRTC
482  // or not active.
483  drmModeFreePlane(plane);
484  plane = NULL;
485  continue;
486  }
487 
488  break;
489  }
490 
491  if (i == plane_res->count_planes) {
492  if (ctx->source_crtc > 0) {
493  av_log(avctx, AV_LOG_ERROR, "No usable planes found on "
494  "CRTC %"PRId64".\n", ctx->source_crtc);
495  } else {
496  av_log(avctx, AV_LOG_ERROR, "No usable planes found.\n");
497  }
498  err = AVERROR(EINVAL);
499  goto fail;
500  }
501 
502  av_log(avctx, AV_LOG_INFO, "Using plane %"PRIu32" to "
503  "locate framebuffers.\n", plane->plane_id);
504  }
505 
506  ctx->plane_id = plane->plane_id;
507 
508 #if HAVE_LIBDRM_GETFB2
509  fb2 = drmModeGetFB2(ctx->hwctx->fd, plane->fb_id);
510  if (!fb2 && errno == ENOSYS) {
511  av_log(avctx, AV_LOG_INFO, "GETFB2 not supported, "
512  "will try to use GETFB instead.\n");
513  } else if (!fb2) {
514  err = errno;
515  av_log(avctx, AV_LOG_ERROR, "Failed to get "
516  "framebuffer %"PRIu32": %s.\n",
517  plane->fb_id, strerror(err));
518  err = AVERROR(err);
519  goto fail;
520  } else {
521  av_log(avctx, AV_LOG_INFO, "Template framebuffer is "
522  "%"PRIu32": %"PRIu32"x%"PRIu32" "
523  "format %"PRIx32" modifier %"PRIx64" flags %"PRIx32".\n",
524  fb2->fb_id, fb2->width, fb2->height,
525  fb2->pixel_format, fb2->modifier, fb2->flags);
526 
527  ctx->width = fb2->width;
528  ctx->height = fb2->height;
529 
530  if (!fb2->handles[0]) {
531  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer: "
532  "maybe you need some additional capabilities?\n");
533  err = AVERROR(EINVAL);
534  goto fail;
535  }
536 
537  for (i = 0; i < FF_ARRAY_ELEMS(kmsgrab_formats); i++) {
538  if (kmsgrab_formats[i].drm_format == fb2->pixel_format) {
539  if (ctx->format != AV_PIX_FMT_NONE &&
540  ctx->format != kmsgrab_formats[i].pixfmt) {
541  av_log(avctx, AV_LOG_ERROR, "Framebuffer pixel format "
542  "%"PRIx32" does not match expected format.\n",
543  fb2->pixel_format);
544  err = AVERROR(EINVAL);
545  goto fail;
546  }
547  ctx->drm_format = fb2->pixel_format;
548  ctx->format = kmsgrab_formats[i].pixfmt;
549  break;
550  }
551  }
552  if (i == FF_ARRAY_ELEMS(kmsgrab_formats)) {
553  av_log(avctx, AV_LOG_ERROR, "Framebuffer pixel format "
554  "%"PRIx32" is not a known supported format.\n",
555  fb2->pixel_format);
556  err = AVERROR(EINVAL);
557  goto fail;
558  }
559 
560  if (fb2->flags & DRM_MODE_FB_MODIFIERS) {
561  if (ctx->drm_format_modifier != DRM_FORMAT_MOD_INVALID &&
562  ctx->drm_format_modifier != fb2->modifier) {
563  av_log(avctx, AV_LOG_ERROR, "Framebuffer format modifier "
564  "%"PRIx64" does not match expected modifier.\n",
565  fb2->modifier);
566  err = AVERROR(EINVAL);
567  goto fail;
568  } else {
569  ctx->drm_format_modifier = fb2->modifier;
570  }
571  }
572  av_log(avctx, AV_LOG_VERBOSE, "Format is %s, from "
573  "DRM format %"PRIx32" modifier %"PRIx64".\n",
574  av_get_pix_fmt_name(ctx->format),
575  ctx->drm_format, ctx->drm_format_modifier);
576 
577  ctx->fb2_available = 1;
578  }
579 #endif
580 
581  if (!ctx->fb2_available) {
582  if (ctx->format == AV_PIX_FMT_NONE) {
583  // Backward compatibility: assume BGR0 if no format supplied.
584  ctx->format = AV_PIX_FMT_BGR0;
585  }
586  for (i = 0; i < FF_ARRAY_ELEMS(kmsgrab_formats); i++) {
587  if (kmsgrab_formats[i].pixfmt == ctx->format) {
588  ctx->drm_format = kmsgrab_formats[i].drm_format;
589  break;
590  }
591  }
592  if (i >= FF_ARRAY_ELEMS(kmsgrab_formats)) {
593  av_log(avctx, AV_LOG_ERROR, "Unsupported format %s.\n",
594  av_get_pix_fmt_name(ctx->format));
595  return AVERROR(EINVAL);
596  }
597 
598  fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id);
599  if (!fb) {
600  err = errno;
601  av_log(avctx, AV_LOG_ERROR, "Failed to get "
602  "framebuffer %"PRIu32": %s.\n",
603  plane->fb_id, strerror(err));
604  err = AVERROR(err);
605  goto fail;
606  }
607 
608  av_log(avctx, AV_LOG_INFO, "Template framebuffer is %"PRIu32": "
609  "%"PRIu32"x%"PRIu32" %"PRIu32"bpp %"PRIu32"b depth.\n",
610  fb->fb_id, fb->width, fb->height, fb->bpp, fb->depth);
611 
612  ctx->width = fb->width;
613  ctx->height = fb->height;
614 
615  if (!fb->handle) {
616  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer: "
617  "maybe you need some additional capabilities?\n");
618  err = AVERROR(EINVAL);
619  goto fail;
620  }
621  }
622 
623  stream = avformat_new_stream(avctx, NULL);
624  if (!stream) {
625  err = AVERROR(ENOMEM);
626  goto fail;
627  }
628 
631  stream->codecpar->width = ctx->width;
632  stream->codecpar->height = ctx->height;
634 
635  avpriv_set_pts_info(stream, 64, 1, 1000000);
636 
637  ctx->frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
638  if (!ctx->frames_ref) {
639  err = AVERROR(ENOMEM);
640  goto fail;
641  }
642  ctx->frames = (AVHWFramesContext*)ctx->frames_ref->data;
643 
644  ctx->frames->format = AV_PIX_FMT_DRM_PRIME;
645  ctx->frames->sw_format = ctx->format,
646  ctx->frames->width = ctx->width;
647  ctx->frames->height = ctx->height;
648 
649  err = av_hwframe_ctx_init(ctx->frames_ref);
650  if (err < 0) {
651  av_log(avctx, AV_LOG_ERROR, "Failed to initialise "
652  "hardware frames context: %d.\n", err);
653  goto fail;
654  }
655 
656  ctx->frame_delay = av_rescale_q(1, (AVRational) { ctx->framerate.den,
657  ctx->framerate.num }, AV_TIME_BASE_Q);
658 
659  err = 0;
660 fail:
661  drmModeFreePlaneResources(plane_res);
662  drmModeFreePlane(plane);
663  drmModeFreeFB(fb);
664 #if HAVE_LIBDRM_GETFB2
665  drmModeFreeFB2(fb2);
666 #endif
667  return err;
668 }
669 
671 {
672  KMSGrabContext *ctx = avctx->priv_data;
673 
674  av_buffer_unref(&ctx->frames_ref);
675  av_buffer_unref(&ctx->device_ref);
676 
677  return 0;
678 }
679 
680 #define OFFSET(x) offsetof(KMSGrabContext, x)
681 #define FLAGS AV_OPT_FLAG_DECODING_PARAM
682 static const AVOption options[] = {
683  { "device", "DRM device path",
684  OFFSET(device_path), AV_OPT_TYPE_STRING,
685  { .str = "/dev/dri/card0" }, 0, 0, FLAGS },
686  { "format", "Pixel format for framebuffer",
688  { .i64 = AV_PIX_FMT_NONE }, -1, INT32_MAX, FLAGS },
689  { "format_modifier", "DRM format modifier for framebuffer",
690  OFFSET(drm_format_modifier), AV_OPT_TYPE_INT64,
691  { .i64 = DRM_FORMAT_MOD_INVALID }, 0, INT64_MAX, FLAGS },
692  { "crtc_id", "CRTC ID to define capture source",
693  OFFSET(source_crtc), AV_OPT_TYPE_INT64,
694  { .i64 = 0 }, 0, UINT32_MAX, FLAGS },
695  { "plane_id", "Plane ID to define capture source",
696  OFFSET(source_plane), AV_OPT_TYPE_INT64,
697  { .i64 = 0 }, 0, UINT32_MAX, FLAGS },
698  { "framerate", "Framerate to capture at",
700  { .dbl = 30.0 }, 0, 1000, FLAGS },
701  { NULL },
702 };
703 
704 static const AVClass kmsgrab_class = {
705  .class_name = "kmsgrab indev",
706  .item_name = av_default_item_name,
707  .option = options,
708  .version = LIBAVUTIL_VERSION_INT,
710 };
711 
713  .p.name = "kmsgrab",
714  .p.long_name = NULL_IF_CONFIG_SMALL("KMS screen capture"),
715  .p.flags = AVFMT_NOFILE,
716  .p.priv_class = &kmsgrab_class,
717  .priv_data_size = sizeof(KMSGrabContext),
721 };
av_gettime_relative
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition: time.c:56
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
KMSGrabContext::frames_ref
AVBufferRef * frames_ref
Definition: kmsgrab.c:56
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:51
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:264
AVDRMPlaneDescriptor
DRM plane descriptor.
Definition: hwcontext_drm.h:74
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:160
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:322
KMSGrabContext::frame_last
int64_t frame_last
Definition: kmsgrab.c:65
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:375
pixdesc.h
KMSGrabContext::device_path
const char * device_path
Definition: kmsgrab.c:67
av_hwframe_ctx_alloc
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:248
AVPacket::data
uint8_t * data
Definition: packet.h:522
AV_PIX_FMT_DRM_PRIME
@ AV_PIX_FMT_DRM_PRIME
DRM-managed buffers exposed through PRIME buffer sharing.
Definition: pixfmt.h:351
KMSGrabContext::plane_id
uint32_t plane_id
Definition: kmsgrab.c:59
AVOption
AVOption.
Definition: opt.h:346
data
const char data[16]
Definition: mxf.c:148
KMSGrabContext::width
unsigned int width
Definition: kmsgrab.c:61
kmsgrab_get_fb
static int kmsgrab_get_fb(AVFormatContext *avctx, drmModePlane *plane, AVDRMFrameDescriptor *desc)
Definition: kmsgrab.c:93
KMSGrabContext::frame_delay
int64_t frame_delay
Definition: kmsgrab.c:64
KMSGrabContext::height
unsigned int height
Definition: kmsgrab.c:62
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:76
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:102
mathematics.h
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
AVDRMFrameDescriptor
DRM frame descriptor.
Definition: hwcontext_drm.h:133
AV_OPT_TYPE_RATIONAL
@ AV_OPT_TYPE_RATIONAL
Definition: opt.h:240
KMSGrabContext::frames
AVHWFramesContext * frames
Definition: kmsgrab.c:57
AV_PIX_FMT_RGB555BE
@ AV_PIX_FMT_RGB555BE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
Definition: pixfmt.h:114
kmsgrab_read_close
static av_cold int kmsgrab_read_close(AVFormatContext *avctx)
Definition: kmsgrab.c:670
AV_PIX_FMT_GRAY16BE
@ AV_PIX_FMT_GRAY16BE
Y , 16bpp, big-endian.
Definition: pixfmt.h:104
avpriv_set_pts_info
void avpriv_set_pts_info(AVStream *st, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: avformat.c:853
fail
#define fail()
Definition: checkasm.h:179
read_close
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:143
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:148
AV_PIX_FMT_BGR8
@ AV_PIX_FMT_BGR8
packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
Definition: pixfmt.h:90
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
AVDRMObjectDescriptor
DRM object descriptor.
Definition: hwcontext_drm.h:48
read_packet
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_read_callback.c:41
kmsgrab_read_packet
static int kmsgrab_read_packet(AVFormatContext *avctx, AVPacket *pkt)
Definition: kmsgrab.c:263
format
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate. The lists are not just lists
AVInputFormat::name
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:553
AVCodecParameters::width
int width
Video only.
Definition: codec_par.h:134
DRM_FORMAT_MOD_INVALID
#define DRM_FORMAT_MOD_INVALID
Definition: kmsgrab.c:32
AV_OPT_TYPE_INT64
@ AV_OPT_TYPE_INT64
Definition: opt.h:236
KMSGrabContext::drm_format_modifier
int64_t drm_format_modifier
Definition: kmsgrab.c:69
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
av_usleep
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
AV_CODEC_ID_WRAPPED_AVFRAME
@ AV_CODEC_ID_WRAPPED_AVFRAME
Passthrough codec, AVFrames wrapped in AVPacket.
Definition: codec_id.h:600
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
KMSGrabContext::device_ref
AVBufferRef * device_ref
Definition: kmsgrab.c:51
AVFormatContext
Format I/O context.
Definition: avformat.h:1255
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:766
AVPacket::buf
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition: packet.h:505
framerate
float framerate
Definition: av1_levels.c:29
AV_PIX_FMT_RGB565LE
@ AV_PIX_FMT_RGB565LE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
Definition: pixfmt.h:113
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
read_header
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:550
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
KMSGrabContext::framerate
AVRational framerate
Definition: kmsgrab.c:72
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:74
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AV_PIX_FMT_BGR565LE
@ AV_PIX_FMT_BGR565LE
packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
Definition: pixfmt.h:118
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
AV_PIX_FMT_BGR0
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:265
time.h
kmsgrab_formats
static const struct @234 kmsgrab_formats[]
AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
@ AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
Definition: log.h:41
KMSGrabContext
Definition: kmsgrab.c:48
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
AV_PIX_FMT_BGR555BE
@ AV_PIX_FMT_BGR555BE
packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined
Definition: pixfmt.h:119
KMSGrabContext::source_crtc
int64_t source_crtc
Definition: kmsgrab.c:71
AV_PIX_FMT_ABGR
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:101
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
AV_PIX_FMT_X2RGB10LE
@ AV_PIX_FMT_X2RGB10LE
packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined
Definition: pixfmt.h:384
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:75
AVPacket::size
int size
Definition: packet.h:523
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:106
ff_kmsgrab_demuxer
const FFInputFormat ff_kmsgrab_demuxer
Definition: kmsgrab.c:712
size
int size
Definition: twinvq_data.h:10344
KMSGrabContext::drm_format
uint32_t drm_format
Definition: kmsgrab.c:60
OFFSET
#define OFFSET(x)
Definition: kmsgrab.c:680
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:468
KMSGrabContext::format
enum AVPixelFormat format
Definition: kmsgrab.c:68
FFInputFormat::p
AVInputFormat p
The public AVInputFormat.
Definition: demux.h:41
KMSGrabContext::hwctx
AVDRMDeviceContext * hwctx
Definition: kmsgrab.c:53
AV_PIX_FMT_BGR565BE
@ AV_PIX_FMT_BGR565BE
packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
Definition: pixfmt.h:117
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:528
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:263
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
AV_PIX_FMT_ARGB
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:99
KMSGrabContext::fb2_available
int fb2_available
Definition: kmsgrab.c:54
kmsgrab_read_header
static av_cold int kmsgrab_read_header(AVFormatContext *avctx)
Definition: kmsgrab.c:409
AV_PIX_FMT_RGB555LE
@ AV_PIX_FMT_RGB555LE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
Definition: pixfmt.h:115
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:515
kmsgrab_free_frame
static void kmsgrab_free_frame(void *opaque, uint8_t *data)
Definition: kmsgrab.c:86
internal.h
AVCodecParameters::height
int height
Definition: codec_par.h:135
fb
#define fb(width, name)
Definition: cbs_av1.c:585
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:254
AV_PIX_FMT_X2RGB10BE
@ AV_PIX_FMT_X2RGB10BE
packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined
Definition: pixfmt.h:385
hwcontext_drm.h
demux.h
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:115
AV_PIX_FMT_YVYU422
@ AV_PIX_FMT_YVYU422
packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb
Definition: pixfmt.h:207
AVStream
Stream structure.
Definition: avformat.h:743
pixfmt
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:366
pixfmt.h
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:264
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:96
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:71
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
av_hwdevice_ctx_create
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
Definition: hwcontext.c:600
avformat.h
drm_format
uint32_t drm_format
Definition: kmsgrab.c:367
AV_PIX_FMT_UYVY422
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:88
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
options
static const AVOption options[]
Definition: kmsgrab.c:682
AV_OPT_TYPE_PIXEL_FMT
@ AV_OPT_TYPE_PIXEL_FMT
Definition: opt.h:246
AV_PIX_FMT_RGB565BE
@ AV_PIX_FMT_RGB565BE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
Definition: pixfmt.h:112
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
desc
const char * desc
Definition: libsvtav1.c:75
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
AV_PIX_FMT_GRAY16LE
@ AV_PIX_FMT_GRAY16LE
Y , 16bpp, little-endian.
Definition: pixfmt.h:105
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
AVCodecParameters::format
int format
Definition: codec_par.h:92
AV_PIX_FMT_BGR555LE
@ AV_PIX_FMT_BGR555LE
packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined
Definition: pixfmt.h:120
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
kmsgrab_free_desc
static void kmsgrab_free_desc(void *opaque, uint8_t *data)
Definition: kmsgrab.c:75
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:55
AVPacket
This structure stores compressed data.
Definition: packet.h:499
KMSGrabContext::device
AVHWDeviceContext * device
Definition: kmsgrab.c:52
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
FFInputFormat
Definition: demux.h:37
hwcontext.h
AV_PIX_FMT_0RGB
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:262
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
kmsgrab_class
static const AVClass kmsgrab_class
Definition: kmsgrab.c:704
KMSGrabContext::source_plane
int64_t source_plane
Definition: kmsgrab.c:70
AVDRMDeviceContext
DRM device.
Definition: hwcontext_drm.h:157
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:239
AV_PKT_FLAG_TRUSTED
#define AV_PKT_FLAG_TRUSTED
The packet comes from a trusted source.
Definition: packet.h:591
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1283
FLAGS
#define FLAGS
Definition: kmsgrab.c:681
AV_HWDEVICE_TYPE_DRM
@ AV_HWDEVICE_TYPE_DRM
Definition: hwcontext.h:36
av_get_pix_fmt_name
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2882