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/internal.h"
46 
47 typedef struct KMSGrabContext {
48  const AVClass *class;
49 
54 
57 
58  uint32_t plane_id;
59  uint32_t drm_format;
60  unsigned int width;
61  unsigned int height;
62 
63  int64_t frame_delay;
64  int64_t frame_last;
65 
66  const char *device_path;
69  int64_t source_plane;
70  int64_t source_crtc;
73 
74 static void kmsgrab_free_desc(void *opaque, uint8_t *data)
75 {
77  int i;
78 
79  for (i = 0; i < desc->nb_objects; i++)
80  close(desc->objects[i].fd);
81 
82  av_free(desc);
83 }
84 
85 static void kmsgrab_free_frame(void *opaque, uint8_t *data)
86 {
88 
90 }
91 
92 static int kmsgrab_get_fb(AVFormatContext *avctx,
93  drmModePlane *plane,
95 {
96  KMSGrabContext *ctx = avctx->priv_data;
97  drmModeFB *fb = NULL;
98  int err, fd;
99 
100  fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id);
101  if (!fb) {
102  err = errno;
103  av_log(avctx, AV_LOG_ERROR, "Failed to get framebuffer "
104  "%"PRIu32": %s.\n", plane->fb_id, strerror(err));
105  err = AVERROR(err);
106  goto fail;
107  }
108  if (fb->width != ctx->width || fb->height != ctx->height) {
109  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
110  "dimensions changed: now %"PRIu32"x%"PRIu32".\n",
111  ctx->plane_id, fb->width, fb->height);
112  err = AVERROR(EIO);
113  goto fail;
114  }
115  if (!fb->handle) {
116  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer.\n");
117  err = AVERROR(EIO);
118  goto fail;
119  }
120 
121  err = drmPrimeHandleToFD(ctx->hwctx->fd, fb->handle, O_RDONLY, &fd);
122  if (err < 0) {
123  err = errno;
124  av_log(avctx, AV_LOG_ERROR, "Failed to get PRIME fd from "
125  "framebuffer handle: %s.\n", strerror(err));
126  err = AVERROR(err);
127  goto fail;
128  }
129 
131  .nb_objects = 1,
132  .objects[0] = {
133  .fd = fd,
134  .size = fb->height * fb->pitch,
135  .format_modifier = ctx->drm_format_modifier,
136  },
137  .nb_layers = 1,
138  .layers[0] = {
139  .format = ctx->drm_format,
140  .nb_planes = 1,
141  .planes[0] = {
142  .object_index = 0,
143  .offset = 0,
144  .pitch = fb->pitch,
145  },
146  },
147  };
148 
149  err = 0;
150 fail:
151  drmModeFreeFB(fb);
152  return err;
153 }
154 
155 #if HAVE_LIBDRM_GETFB2
156 static int kmsgrab_get_fb2(AVFormatContext *avctx,
157  drmModePlane *plane,
159 {
160  KMSGrabContext *ctx = avctx->priv_data;
161  drmModeFB2 *fb;
162  int err, i, nb_objects;
163  uint64_t modifier = ctx->drm_format_modifier;
164 
165  fb = drmModeGetFB2(ctx->hwctx->fd, plane->fb_id);
166  if (!fb) {
167  err = errno;
168  av_log(avctx, AV_LOG_ERROR, "Failed to get framebuffer "
169  "%"PRIu32": %s.\n", plane->fb_id, strerror(err));
170  return AVERROR(err);
171  }
172  if (fb->pixel_format != ctx->drm_format) {
173  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
174  "format changed: now %"PRIx32".\n",
175  ctx->plane_id, fb->pixel_format);
176  err = AVERROR(EIO);
177  goto fail;
178  }
179  if (fb->width != ctx->width || fb->height != ctx->height) {
180  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
181  "dimensions changed: now %"PRIu32"x%"PRIu32".\n",
182  ctx->plane_id, fb->width, fb->height);
183  err = AVERROR(EIO);
184  goto fail;
185  }
186  if (!fb->handles[0]) {
187  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer.\n");
188  err = AVERROR(EIO);
189  goto fail;
190  }
191 
192  if (fb->flags & DRM_MODE_FB_MODIFIERS)
193  modifier = fb->modifier;
194 
196  .nb_layers = 1,
197  .layers[0] = {
198  .format = ctx->drm_format,
199  },
200  };
201 
202  nb_objects = 0;
203  for (i = 0; i < 4 && fb->handles[i]; i++) {
204  size_t size;
205  int dup = 0, j, obj;
206 
207  size = fb->offsets[i] + fb->height * fb->pitches[i];
208 
209  for (j = 0; j < i; j++) {
210  if (fb->handles[i] == fb->handles[j]) {
211  dup = 1;
212  break;
213  }
214  }
215  if (dup) {
216  obj = desc->layers[0].planes[j].object_index;
217 
218  if (desc->objects[j].size < size)
219  desc->objects[j].size = size;
220 
221  desc->layers[0].planes[i] = (AVDRMPlaneDescriptor) {
222  .object_index = obj,
223  .offset = fb->offsets[i],
224  .pitch = fb->pitches[i],
225  };
226 
227  } else {
228  int fd;
229  err = drmPrimeHandleToFD(ctx->hwctx->fd, fb->handles[i],
230  O_RDONLY, &fd);
231  if (err < 0) {
232  err = errno;
233  av_log(avctx, AV_LOG_ERROR, "Failed to get PRIME fd from "
234  "framebuffer handle: %s.\n", strerror(err));
235  err = AVERROR(err);
236  goto fail;
237  }
238 
239  obj = nb_objects++;
240  desc->objects[obj] = (AVDRMObjectDescriptor) {
241  .fd = fd,
242  .size = size,
243  .format_modifier = modifier,
244  };
245  desc->layers[0].planes[i] = (AVDRMPlaneDescriptor) {
246  .object_index = obj,
247  .offset = fb->offsets[i],
248  .pitch = fb->pitches[i],
249  };
250  }
251  }
252  desc->nb_objects = nb_objects;
253  desc->layers[0].nb_planes = i;
254 
255  err = 0;
256 fail:
257  drmModeFreeFB2(fb);
258  return err;
259 }
260 #endif
261 
263 {
264  KMSGrabContext *ctx = avctx->priv_data;
265  drmModePlane *plane = NULL;
267  AVFrame *frame = NULL;
268  int64_t now;
269  int err;
270 
271  now = av_gettime_relative();
272  if (ctx->frame_last) {
273  int64_t delay;
274  while (1) {
275  delay = ctx->frame_last + ctx->frame_delay - now;
276  if (delay <= 0)
277  break;
278  av_usleep(delay);
279  now = av_gettime_relative();
280  }
281  }
282  ctx->frame_last = now;
283  now = av_gettime();
284 
285  plane = drmModeGetPlane(ctx->hwctx->fd, ctx->plane_id);
286  if (!plane) {
287  err = errno;
288  av_log(avctx, AV_LOG_ERROR, "Failed to get plane "
289  "%"PRIu32": %s.\n", ctx->plane_id, strerror(err));
290  err = AVERROR(err);
291  goto fail;
292  }
293  if (!plane->fb_id) {
294  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" no longer has "
295  "an associated framebuffer.\n", ctx->plane_id);
296  err = AVERROR(EIO);
297  goto fail;
298  }
299 
300  desc = av_mallocz(sizeof(*desc));
301  if (!desc) {
302  err = AVERROR(ENOMEM);
303  goto fail;
304  }
305 
306 #if HAVE_LIBDRM_GETFB2
307  if (ctx->fb2_available)
308  err = kmsgrab_get_fb2(avctx, plane, desc);
309  else
310 #endif
311  err = kmsgrab_get_fb(avctx, plane, desc);
312  if (err < 0)
313  goto fail;
314 
315  frame = av_frame_alloc();
316  if (!frame) {
317  err = AVERROR(ENOMEM);
318  goto fail;
319  }
320 
321  frame->hw_frames_ctx = av_buffer_ref(ctx->frames_ref);
322  if (!frame->hw_frames_ctx) {
323  err = AVERROR(ENOMEM);
324  goto fail;
325  }
326 
327  frame->buf[0] = av_buffer_create((uint8_t*)desc, sizeof(*desc),
328  &kmsgrab_free_desc, avctx, 0);
329  if (!frame->buf[0]) {
330  err = AVERROR(ENOMEM);
331  goto fail;
332  }
333 
334  frame->data[0] = (uint8_t*)desc;
336  frame->width = ctx->width;
337  frame->height = ctx->height;
338 
339  drmModeFreePlane(plane);
340  plane = NULL;
341  desc = NULL;
342 
343  pkt->buf = av_buffer_create((uint8_t*)frame, sizeof(*frame),
344  &kmsgrab_free_frame, avctx, 0);
345  if (!pkt->buf) {
346  err = AVERROR(ENOMEM);
347  goto fail;
348  }
349 
350  pkt->data = (uint8_t*)frame;
351  pkt->size = sizeof(*frame);
352  pkt->pts = now;
354 
355  return 0;
356 
357 fail:
358  drmModeFreePlane(plane);
359  av_freep(&desc);
361  return err;
362 }
363 
364 static const struct {
366  uint32_t drm_format;
367 } kmsgrab_formats[] = {
368  // Monochrome.
369 #ifdef DRM_FORMAT_R8
370  { AV_PIX_FMT_GRAY8, DRM_FORMAT_R8 },
371 #endif
372 #ifdef DRM_FORMAT_R16
373  { AV_PIX_FMT_GRAY16LE, DRM_FORMAT_R16 },
374  { AV_PIX_FMT_GRAY16BE, DRM_FORMAT_R16 | DRM_FORMAT_BIG_ENDIAN },
375 #endif
376  // <8-bit RGB.
377  { AV_PIX_FMT_BGR8, DRM_FORMAT_BGR233 },
378  { AV_PIX_FMT_RGB555LE, DRM_FORMAT_XRGB1555 },
379  { AV_PIX_FMT_RGB555BE, DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN },
380  { AV_PIX_FMT_BGR555LE, DRM_FORMAT_XBGR1555 },
381  { AV_PIX_FMT_BGR555BE, DRM_FORMAT_XBGR1555 | DRM_FORMAT_BIG_ENDIAN },
382  { AV_PIX_FMT_RGB565LE, DRM_FORMAT_RGB565 },
383  { AV_PIX_FMT_RGB565BE, DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN },
384  { AV_PIX_FMT_BGR565LE, DRM_FORMAT_BGR565 },
385  { AV_PIX_FMT_BGR565BE, DRM_FORMAT_BGR565 | DRM_FORMAT_BIG_ENDIAN },
386  // 8-bit RGB.
387  { AV_PIX_FMT_RGB24, DRM_FORMAT_RGB888 },
388  { AV_PIX_FMT_BGR24, DRM_FORMAT_BGR888 },
389  { AV_PIX_FMT_0RGB, DRM_FORMAT_BGRX8888 },
390  { AV_PIX_FMT_0BGR, DRM_FORMAT_RGBX8888 },
391  { AV_PIX_FMT_RGB0, DRM_FORMAT_XBGR8888 },
392  { AV_PIX_FMT_BGR0, DRM_FORMAT_XRGB8888 },
393  { AV_PIX_FMT_ARGB, DRM_FORMAT_BGRA8888 },
394  { AV_PIX_FMT_ABGR, DRM_FORMAT_RGBA8888 },
395  { AV_PIX_FMT_RGBA, DRM_FORMAT_ABGR8888 },
396  { AV_PIX_FMT_BGRA, DRM_FORMAT_ARGB8888 },
397  // 10-bit RGB.
398  { AV_PIX_FMT_X2RGB10LE, DRM_FORMAT_XRGB2101010 },
399  { AV_PIX_FMT_X2RGB10BE, DRM_FORMAT_XRGB2101010 | DRM_FORMAT_BIG_ENDIAN },
400  // 8-bit YUV 4:2:0.
401  { AV_PIX_FMT_NV12, DRM_FORMAT_NV12 },
402  // 8-bit YUV 4:2:2.
403  { AV_PIX_FMT_YUYV422, DRM_FORMAT_YUYV },
404  { AV_PIX_FMT_YVYU422, DRM_FORMAT_YVYU },
405  { AV_PIX_FMT_UYVY422, DRM_FORMAT_UYVY },
406 };
407 
409 {
410  KMSGrabContext *ctx = avctx->priv_data;
411  drmModePlaneRes *plane_res = NULL;
412  drmModePlane *plane = NULL;
413  drmModeFB *fb = NULL;
414 #if HAVE_LIBDRM_GETFB2
415  drmModeFB2 *fb2 = NULL;
416 #endif
417  AVStream *stream;
418  int err, i;
419 
420  err = av_hwdevice_ctx_create(&ctx->device_ref, AV_HWDEVICE_TYPE_DRM,
421  ctx->device_path, NULL, 0);
422  if (err < 0) {
423  av_log(avctx, AV_LOG_ERROR, "Failed to open DRM device.\n");
424  return err;
425  }
426  ctx->device = (AVHWDeviceContext*) ctx->device_ref->data;
427  ctx->hwctx = (AVDRMDeviceContext*)ctx->device->hwctx;
428 
429  err = drmSetClientCap(ctx->hwctx->fd,
430  DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
431  if (err < 0) {
432  av_log(avctx, AV_LOG_WARNING, "Failed to set universal planes "
433  "capability: primary planes will not be usable.\n");
434  }
435 
436  if (ctx->source_plane > 0) {
437  plane = drmModeGetPlane(ctx->hwctx->fd, ctx->source_plane);
438  if (!plane) {
439  err = errno;
440  av_log(avctx, AV_LOG_ERROR, "Failed to get plane %"PRId64": "
441  "%s.\n", ctx->source_plane, strerror(err));
442  err = AVERROR(err);
443  goto fail;
444  }
445 
446  if (plane->fb_id == 0) {
447  av_log(avctx, AV_LOG_ERROR, "Plane %"PRId64" does not have "
448  "an attached framebuffer.\n", ctx->source_plane);
449  err = AVERROR(EINVAL);
450  goto fail;
451  }
452  } else {
453  plane_res = drmModeGetPlaneResources(ctx->hwctx->fd);
454  if (!plane_res) {
455  err = errno;
456  av_log(avctx, AV_LOG_ERROR, "Failed to get plane "
457  "resources: %s.\n", strerror(err));
458  err = AVERROR(err);
459  goto fail;
460  }
461 
462  for (i = 0; i < plane_res->count_planes; i++) {
463  plane = drmModeGetPlane(ctx->hwctx->fd,
464  plane_res->planes[i]);
465  if (!plane) {
466  err = errno;
467  av_log(avctx, AV_LOG_VERBOSE, "Failed to get "
468  "plane %"PRIu32": %s.\n",
469  plane_res->planes[i], strerror(err));
470  continue;
471  }
472 
473  av_log(avctx, AV_LOG_DEBUG, "Plane %"PRIu32": "
474  "CRTC %"PRIu32" FB %"PRIu32".\n",
475  plane->plane_id, plane->crtc_id, plane->fb_id);
476 
477  if ((ctx->source_crtc > 0 &&
478  plane->crtc_id != ctx->source_crtc) ||
479  plane->fb_id == 0) {
480  // Either not connected to the target source CRTC
481  // or not active.
482  drmModeFreePlane(plane);
483  plane = NULL;
484  continue;
485  }
486 
487  break;
488  }
489 
490  if (i == plane_res->count_planes) {
491  if (ctx->source_crtc > 0) {
492  av_log(avctx, AV_LOG_ERROR, "No usable planes found on "
493  "CRTC %"PRId64".\n", ctx->source_crtc);
494  } else {
495  av_log(avctx, AV_LOG_ERROR, "No usable planes found.\n");
496  }
497  err = AVERROR(EINVAL);
498  goto fail;
499  }
500 
501  av_log(avctx, AV_LOG_INFO, "Using plane %"PRIu32" to "
502  "locate framebuffers.\n", plane->plane_id);
503  }
504 
505  ctx->plane_id = plane->plane_id;
506 
507 #if HAVE_LIBDRM_GETFB2
508  fb2 = drmModeGetFB2(ctx->hwctx->fd, plane->fb_id);
509  if (!fb2 && errno == ENOSYS) {
510  av_log(avctx, AV_LOG_INFO, "GETFB2 not supported, "
511  "will try to use GETFB instead.\n");
512  } else if (!fb2) {
513  err = errno;
514  av_log(avctx, AV_LOG_ERROR, "Failed to get "
515  "framebuffer %"PRIu32": %s.\n",
516  plane->fb_id, strerror(err));
517  err = AVERROR(err);
518  goto fail;
519  } else {
520  av_log(avctx, AV_LOG_INFO, "Template framebuffer is "
521  "%"PRIu32": %"PRIu32"x%"PRIu32" "
522  "format %"PRIx32" modifier %"PRIx64" flags %"PRIx32".\n",
523  fb2->fb_id, fb2->width, fb2->height,
524  fb2->pixel_format, fb2->modifier, fb2->flags);
525 
526  ctx->width = fb2->width;
527  ctx->height = fb2->height;
528 
529  if (!fb2->handles[0]) {
530  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer: "
531  "maybe you need some additional capabilities?\n");
532  err = AVERROR(EINVAL);
533  goto fail;
534  }
535 
536  for (i = 0; i < FF_ARRAY_ELEMS(kmsgrab_formats); i++) {
537  if (kmsgrab_formats[i].drm_format == fb2->pixel_format) {
538  if (ctx->format != AV_PIX_FMT_NONE &&
539  ctx->format != kmsgrab_formats[i].pixfmt) {
540  av_log(avctx, AV_LOG_ERROR, "Framebuffer pixel format "
541  "%"PRIx32" does not match expected format.\n",
542  fb2->pixel_format);
543  err = AVERROR(EINVAL);
544  goto fail;
545  }
546  ctx->drm_format = fb2->pixel_format;
547  ctx->format = kmsgrab_formats[i].pixfmt;
548  break;
549  }
550  }
551  if (i == FF_ARRAY_ELEMS(kmsgrab_formats)) {
552  av_log(avctx, AV_LOG_ERROR, "Framebuffer pixel format "
553  "%"PRIx32" is not a known supported format.\n",
554  fb2->pixel_format);
555  err = AVERROR(EINVAL);
556  goto fail;
557  }
558 
559  if (fb2->flags & DRM_MODE_FB_MODIFIERS) {
560  if (ctx->drm_format_modifier != DRM_FORMAT_MOD_INVALID &&
561  ctx->drm_format_modifier != fb2->modifier) {
562  av_log(avctx, AV_LOG_ERROR, "Framebuffer format modifier "
563  "%"PRIx64" does not match expected modifier.\n",
564  fb2->modifier);
565  err = AVERROR(EINVAL);
566  goto fail;
567  } else {
568  ctx->drm_format_modifier = fb2->modifier;
569  }
570  }
571  av_log(avctx, AV_LOG_VERBOSE, "Format is %s, from "
572  "DRM format %"PRIx32" modifier %"PRIx64".\n",
573  av_get_pix_fmt_name(ctx->format),
574  ctx->drm_format, ctx->drm_format_modifier);
575 
576  ctx->fb2_available = 1;
577  }
578 #endif
579 
580  if (!ctx->fb2_available) {
581  if (ctx->format == AV_PIX_FMT_NONE) {
582  // Backward compatibility: assume BGR0 if no format supplied.
583  ctx->format = AV_PIX_FMT_BGR0;
584  }
585  for (i = 0; i < FF_ARRAY_ELEMS(kmsgrab_formats); i++) {
586  if (kmsgrab_formats[i].pixfmt == ctx->format) {
587  ctx->drm_format = kmsgrab_formats[i].drm_format;
588  break;
589  }
590  }
591  if (i >= FF_ARRAY_ELEMS(kmsgrab_formats)) {
592  av_log(avctx, AV_LOG_ERROR, "Unsupported format %s.\n",
593  av_get_pix_fmt_name(ctx->format));
594  return AVERROR(EINVAL);
595  }
596 
597  fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id);
598  if (!fb) {
599  err = errno;
600  av_log(avctx, AV_LOG_ERROR, "Failed to get "
601  "framebuffer %"PRIu32": %s.\n",
602  plane->fb_id, strerror(err));
603  err = AVERROR(err);
604  goto fail;
605  }
606 
607  av_log(avctx, AV_LOG_INFO, "Template framebuffer is %"PRIu32": "
608  "%"PRIu32"x%"PRIu32" %"PRIu32"bpp %"PRIu32"b depth.\n",
609  fb->fb_id, fb->width, fb->height, fb->bpp, fb->depth);
610 
611  ctx->width = fb->width;
612  ctx->height = fb->height;
613 
614  if (!fb->handle) {
615  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer: "
616  "maybe you need some additional capabilities?\n");
617  err = AVERROR(EINVAL);
618  goto fail;
619  }
620  }
621 
622  stream = avformat_new_stream(avctx, NULL);
623  if (!stream) {
624  err = AVERROR(ENOMEM);
625  goto fail;
626  }
627 
630  stream->codecpar->width = ctx->width;
631  stream->codecpar->height = ctx->height;
633 
634  avpriv_set_pts_info(stream, 64, 1, 1000000);
635 
636  ctx->frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
637  if (!ctx->frames_ref) {
638  err = AVERROR(ENOMEM);
639  goto fail;
640  }
641  ctx->frames = (AVHWFramesContext*)ctx->frames_ref->data;
642 
643  ctx->frames->format = AV_PIX_FMT_DRM_PRIME;
644  ctx->frames->sw_format = ctx->format,
645  ctx->frames->width = ctx->width;
646  ctx->frames->height = ctx->height;
647 
648  err = av_hwframe_ctx_init(ctx->frames_ref);
649  if (err < 0) {
650  av_log(avctx, AV_LOG_ERROR, "Failed to initialise "
651  "hardware frames context: %d.\n", err);
652  goto fail;
653  }
654 
655  ctx->frame_delay = av_rescale_q(1, (AVRational) { ctx->framerate.den,
656  ctx->framerate.num }, AV_TIME_BASE_Q);
657 
658  err = 0;
659 fail:
660  drmModeFreePlaneResources(plane_res);
661  drmModeFreePlane(plane);
662  drmModeFreeFB(fb);
663 #if HAVE_LIBDRM_GETFB2
664  drmModeFreeFB2(fb2);
665 #endif
666  return err;
667 }
668 
670 {
671  KMSGrabContext *ctx = avctx->priv_data;
672 
673  av_buffer_unref(&ctx->frames_ref);
674  av_buffer_unref(&ctx->device_ref);
675 
676  return 0;
677 }
678 
679 #define OFFSET(x) offsetof(KMSGrabContext, x)
680 #define FLAGS AV_OPT_FLAG_DECODING_PARAM
681 static const AVOption options[] = {
682  { "device", "DRM device path",
683  OFFSET(device_path), AV_OPT_TYPE_STRING,
684  { .str = "/dev/dri/card0" }, 0, 0, FLAGS },
685  { "format", "Pixel format for framebuffer",
687  { .i64 = AV_PIX_FMT_NONE }, -1, INT32_MAX, FLAGS },
688  { "format_modifier", "DRM format modifier for framebuffer",
689  OFFSET(drm_format_modifier), AV_OPT_TYPE_INT64,
690  { .i64 = DRM_FORMAT_MOD_INVALID }, 0, INT64_MAX, FLAGS },
691  { "crtc_id", "CRTC ID to define capture source",
692  OFFSET(source_crtc), AV_OPT_TYPE_INT64,
693  { .i64 = 0 }, 0, UINT32_MAX, FLAGS },
694  { "plane_id", "Plane ID to define capture source",
695  OFFSET(source_plane), AV_OPT_TYPE_INT64,
696  { .i64 = 0 }, 0, UINT32_MAX, FLAGS },
697  { "framerate", "Framerate to capture at",
699  { .dbl = 30.0 }, 0, 1000, FLAGS },
700  { NULL },
701 };
702 
703 static const AVClass kmsgrab_class = {
704  .class_name = "kmsgrab indev",
705  .item_name = av_default_item_name,
706  .option = options,
707  .version = LIBAVUTIL_VERSION_INT,
709 };
710 
712  .name = "kmsgrab",
713  .long_name = NULL_IF_CONFIG_SMALL("KMS screen capture"),
714  .priv_data_size = sizeof(KMSGrabContext),
718  .flags = AVFMT_NOFILE,
719  .priv_class = &kmsgrab_class,
720 };
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:64
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:55
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:100
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:334
KMSGrabContext::frame_last
int64_t frame_last
Definition: kmsgrab.c:64
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
pixdesc.h
AVFrame::width
int width
Definition: frame.h:412
KMSGrabContext::device_path
const char * device_path
Definition: kmsgrab.c:66
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:491
AV_PIX_FMT_DRM_PRIME
@ AV_PIX_FMT_DRM_PRIME
DRM-managed buffers exposed through PRIME buffer sharing.
Definition: pixfmt.h:348
KMSGrabContext::plane_id
uint32_t plane_id
Definition: kmsgrab.c:58
AVOption
AVOption.
Definition: opt.h:251
data
const char data[16]
Definition: mxf.c:148
KMSGrabContext::width
unsigned int width
Definition: kmsgrab.c:60
kmsgrab_get_fb
static int kmsgrab_get_fb(AVFormatContext *avctx, drmModePlane *plane, AVDRMFrameDescriptor *desc)
Definition: kmsgrab.c:92
KMSGrabContext::frame_delay
int64_t frame_delay
Definition: kmsgrab.c:63
KMSGrabContext::height
unsigned int height
Definition: kmsgrab.c:61
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:69
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
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:230
AVFrame::buf
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:590
KMSGrabContext::frames
AVHWFramesContext * frames
Definition: kmsgrab.c:56
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:107
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:361
kmsgrab_read_close
static av_cold int kmsgrab_read_close(AVFormatContext *avctx)
Definition: kmsgrab.c:669
AV_PIX_FMT_GRAY16BE
@ AV_PIX_FMT_GRAY16BE
Y , 16bpp, big-endian.
Definition: pixfmt.h:97
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:761
fail
#define fail()
Definition: checkasm.h:138
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:61
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:88
AV_PIX_FMT_BGR8
@ AV_PIX_FMT_BGR8
packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
Definition: pixfmt.h:83
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
AVInputFormat
Definition: avformat.h:549
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:262
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:554
kmsgrab_formats
static const struct @219 kmsgrab_formats[]
AVCodecParameters::width
int width
Video only.
Definition: codec_par.h:121
DRM_FORMAT_MOD_INVALID
#define DRM_FORMAT_MOD_INVALID
Definition: kmsgrab.c:32
AV_OPT_TYPE_INT64
@ AV_OPT_TYPE_INT64
Definition: opt.h:226
KMSGrabContext::drm_format_modifier
int64_t drm_format_modifier
Definition: kmsgrab.c:68
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:601
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
frame
static AVFrame * frame
Definition: demux_decode.c:54
KMSGrabContext::device_ref
AVBufferRef * device_ref
Definition: kmsgrab.c:50
AVFormatContext
Format I/O context.
Definition: avformat.h:1115
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:864
AVPacket::buf
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition: packet.h:474
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:106
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:71
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:67
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:111
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:258
time.h
AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
@ AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
Definition: log.h:41
KMSGrabContext
Definition: kmsgrab.c:47
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:74
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:112
KMSGrabContext::source_crtc
int64_t source_crtc
Definition: kmsgrab.c:70
AV_PIX_FMT_ABGR
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:94
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:381
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
AVPacket::size
int size
Definition: packet.h:492
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 AVInputFormat ff_kmsgrab_demuxer
Definition: kmsgrab.c:711
size
int size
Definition: twinvq_data.h:10344
KMSGrabContext::drm_format
uint32_t drm_format
Definition: kmsgrab.c:59
OFFSET
#define OFFSET(x)
Definition: kmsgrab.c:679
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:469
KMSGrabContext::format
enum AVPixelFormat format
Definition: kmsgrab.c:67
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:427
KMSGrabContext::hwctx
AVDRMDeviceContext * hwctx
Definition: kmsgrab.c:52
AV_PIX_FMT_BGR565BE
@ AV_PIX_FMT_BGR565BE
packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
Definition: pixfmt.h:110
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:497
AV_PIX_FMT_RGB0
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:256
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:92
KMSGrabContext::fb2_available
int fb2_available
Definition: kmsgrab.c:53
kmsgrab_read_header
static av_cold int kmsgrab_read_header(AVFormatContext *avctx)
Definition: kmsgrab.c:408
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:108
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:484
kmsgrab_free_frame
static void kmsgrab_free_frame(void *opaque, uint8_t *data)
Definition: kmsgrab.c:85
internal.h
AVCodecParameters::height
int height
Definition: codec_par.h:122
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:382
hwcontext_drm.h
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
AV_PIX_FMT_YVYU422
@ AV_PIX_FMT_YVYU422
packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb
Definition: pixfmt.h:200
AVStream
Stream structure.
Definition: avformat.h:841
pixfmt
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:365
pixfmt.h
AV_PIX_FMT_0BGR
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:257
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:89
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
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:615
avformat.h
drm_format
uint32_t drm_format
Definition: kmsgrab.c:366
AV_PIX_FMT_UYVY422
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:81
AVFrame::hw_frames_ctx
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
Definition: frame.h:752
AVFrame::height
int height
Definition: frame.h:412
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
options
static const AVOption options[]
Definition: kmsgrab.c:681
AV_OPT_TYPE_PIXEL_FMT
@ AV_OPT_TYPE_PIXEL_FMT
Definition: opt.h:236
AV_PIX_FMT_RGB565BE
@ AV_PIX_FMT_RGB565BE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
Definition: pixfmt.h:105
av_gettime
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
desc
const char * desc
Definition: libsvtav1.c:83
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:98
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
AVCodecParameters::format
int format
Definition: codec_par.h:79
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:113
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:74
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:468
KMSGrabContext::device
AVHWDeviceContext * device
Definition: kmsgrab.c:51
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
hwcontext.h
AV_PIX_FMT_0RGB
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:255
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
kmsgrab_class
static const AVClass kmsgrab_class
Definition: kmsgrab.c:703
KMSGrabContext::source_plane
int64_t source_plane
Definition: kmsgrab.c:69
AVDRMDeviceContext
DRM device.
Definition: hwcontext_drm.h:157
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
AV_PKT_FLAG_TRUSTED
#define AV_PKT_FLAG_TRUSTED
The packet comes from a trusted source.
Definition: packet.h:560
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1143
FLAGS
#define FLAGS
Definition: kmsgrab.c:680
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:2884