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 {
87  AVFrame *frame = (AVFrame*)data;
88 
89  av_frame_free(&frame);
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 
130  *desc = (AVDRMFrameDescriptor) {
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 
164  fb = drmModeGetFB2(ctx->hwctx->fd, plane->fb_id);
165  if (!fb) {
166  err = errno;
167  av_log(avctx, AV_LOG_ERROR, "Failed to get framebuffer "
168  "%"PRIu32": %s.\n", plane->fb_id, strerror(err));
169  return AVERROR(err);
170  }
171  if (fb->pixel_format != ctx->drm_format) {
172  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
173  "format changed: now %"PRIx32".\n",
174  ctx->plane_id, fb->pixel_format);
175  err = AVERROR(EIO);
176  goto fail;
177  }
178  if (fb->modifier != ctx->drm_format_modifier) {
179  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
180  "format modifier changed: now %"PRIx64".\n",
181  ctx->plane_id, fb->modifier);
182  err = AVERROR(EIO);
183  goto fail;
184  }
185  if (fb->width != ctx->width || fb->height != ctx->height) {
186  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
187  "dimensions changed: now %"PRIu32"x%"PRIu32".\n",
188  ctx->plane_id, fb->width, fb->height);
189  err = AVERROR(EIO);
190  goto fail;
191  }
192  if (!fb->handles[0]) {
193  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer.\n");
194  err = AVERROR(EIO);
195  goto fail;
196  }
197 
198  *desc = (AVDRMFrameDescriptor) {
199  .nb_layers = 1,
200  .layers[0] = {
201  .format = ctx->drm_format,
202  },
203  };
204 
205  nb_objects = 0;
206  for (i = 0; i < 4 && fb->handles[i]; i++) {
207  size_t size;
208  int dup = 0, j, obj;
209 
210  size = fb->offsets[i] + fb->height * fb->pitches[i];
211 
212  for (j = 0; j < i; j++) {
213  if (fb->handles[i] == fb->handles[j]) {
214  dup = 1;
215  break;
216  }
217  }
218  if (dup) {
219  obj = desc->layers[0].planes[j].object_index;
220 
221  if (desc->objects[j].size < size)
222  desc->objects[j].size = size;
223 
224  desc->layers[0].planes[i] = (AVDRMPlaneDescriptor) {
225  .object_index = obj,
226  .offset = fb->offsets[i],
227  .pitch = fb->pitches[i],
228  };
229 
230  } else {
231  int fd;
232  err = drmPrimeHandleToFD(ctx->hwctx->fd, fb->handles[i],
233  O_RDONLY, &fd);
234  if (err < 0) {
235  err = errno;
236  av_log(avctx, AV_LOG_ERROR, "Failed to get PRIME fd from "
237  "framebuffer handle: %s.\n", strerror(err));
238  err = AVERROR(err);
239  goto fail;
240  }
241 
242  obj = nb_objects++;
243  desc->objects[obj] = (AVDRMObjectDescriptor) {
244  .fd = fd,
245  .size = size,
246  .format_modifier = fb->modifier,
247  };
248  desc->layers[0].planes[i] = (AVDRMPlaneDescriptor) {
249  .object_index = obj,
250  .offset = fb->offsets[i],
251  .pitch = fb->pitches[i],
252  };
253  }
254  }
255  desc->nb_objects = nb_objects;
256  desc->layers[0].nb_planes = i;
257 
258  err = 0;
259 fail:
260  drmModeFreeFB2(fb);
261  return err;
262 }
263 #endif
264 
266 {
267  KMSGrabContext *ctx = avctx->priv_data;
268  drmModePlane *plane = NULL;
269  AVDRMFrameDescriptor *desc = NULL;
270  AVFrame *frame = NULL;
271  int64_t now;
272  int err;
273 
274  now = av_gettime();
275  if (ctx->frame_last) {
276  int64_t delay;
277  while (1) {
278  delay = ctx->frame_last + ctx->frame_delay - now;
279  if (delay <= 0)
280  break;
281  av_usleep(delay);
282  now = av_gettime();
283  }
284  }
285  ctx->frame_last = now;
286 
287  plane = drmModeGetPlane(ctx->hwctx->fd, ctx->plane_id);
288  if (!plane) {
289  err = errno;
290  av_log(avctx, AV_LOG_ERROR, "Failed to get plane "
291  "%"PRIu32": %s.\n", ctx->plane_id, strerror(err));
292  err = AVERROR(err);
293  goto fail;
294  }
295  if (!plane->fb_id) {
296  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" no longer has "
297  "an associated framebuffer.\n", ctx->plane_id);
298  err = AVERROR(EIO);
299  goto fail;
300  }
301 
302  desc = av_mallocz(sizeof(*desc));
303  if (!desc) {
304  err = AVERROR(ENOMEM);
305  goto fail;
306  }
307 
308 #if HAVE_LIBDRM_GETFB2
309  if (ctx->fb2_available)
310  err = kmsgrab_get_fb2(avctx, plane, desc);
311  else
312 #endif
313  err = kmsgrab_get_fb(avctx, plane, desc);
314  if (err < 0)
315  goto fail;
316 
317  frame = av_frame_alloc();
318  if (!frame) {
319  err = AVERROR(ENOMEM);
320  goto fail;
321  }
322 
323  frame->hw_frames_ctx = av_buffer_ref(ctx->frames_ref);
324  if (!frame->hw_frames_ctx) {
325  err = AVERROR(ENOMEM);
326  goto fail;
327  }
328 
329  frame->buf[0] = av_buffer_create((uint8_t*)desc, sizeof(*desc),
330  &kmsgrab_free_desc, avctx, 0);
331  if (!frame->buf[0]) {
332  err = AVERROR(ENOMEM);
333  goto fail;
334  }
335 
336  frame->data[0] = (uint8_t*)desc;
337  frame->format = AV_PIX_FMT_DRM_PRIME;
338  frame->width = ctx->width;
339  frame->height = ctx->height;
340 
341  drmModeFreePlane(plane);
342  plane = NULL;
343  desc = NULL;
344 
345  pkt->buf = av_buffer_create((uint8_t*)frame, sizeof(*frame),
346  &kmsgrab_free_frame, avctx, 0);
347  if (!pkt->buf) {
348  err = AVERROR(ENOMEM);
349  goto fail;
350  }
351 
352  pkt->data = (uint8_t*)frame;
353  pkt->size = sizeof(*frame);
354  pkt->pts = now;
355  pkt->flags |= AV_PKT_FLAG_TRUSTED;
356 
357  return 0;
358 
359 fail:
360  drmModeFreePlane(plane);
361  av_freep(&desc);
362  av_frame_free(&frame);
363  return err;
364 }
365 
366 static const struct {
368  uint32_t drm_format;
369 } kmsgrab_formats[] = {
370  // Monochrome.
371 #ifdef DRM_FORMAT_R8
372  { AV_PIX_FMT_GRAY8, DRM_FORMAT_R8 },
373 #endif
374 #ifdef DRM_FORMAT_R16
375  { AV_PIX_FMT_GRAY16LE, DRM_FORMAT_R16 },
376  { AV_PIX_FMT_GRAY16BE, DRM_FORMAT_R16 | DRM_FORMAT_BIG_ENDIAN },
377 #endif
378  // <8-bit RGB.
379  { AV_PIX_FMT_BGR8, DRM_FORMAT_BGR233 },
380  { AV_PIX_FMT_RGB555LE, DRM_FORMAT_XRGB1555 },
381  { AV_PIX_FMT_RGB555BE, DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN },
382  { AV_PIX_FMT_BGR555LE, DRM_FORMAT_XBGR1555 },
383  { AV_PIX_FMT_BGR555BE, DRM_FORMAT_XBGR1555 | DRM_FORMAT_BIG_ENDIAN },
384  { AV_PIX_FMT_RGB565LE, DRM_FORMAT_RGB565 },
385  { AV_PIX_FMT_RGB565BE, DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN },
386  { AV_PIX_FMT_BGR565LE, DRM_FORMAT_BGR565 },
387  { AV_PIX_FMT_BGR565BE, DRM_FORMAT_BGR565 | DRM_FORMAT_BIG_ENDIAN },
388  // 8-bit RGB.
389  { AV_PIX_FMT_RGB24, DRM_FORMAT_RGB888 },
390  { AV_PIX_FMT_BGR24, DRM_FORMAT_BGR888 },
391  { AV_PIX_FMT_0RGB, DRM_FORMAT_BGRX8888 },
392  { AV_PIX_FMT_0BGR, DRM_FORMAT_RGBX8888 },
393  { AV_PIX_FMT_RGB0, DRM_FORMAT_XBGR8888 },
394  { AV_PIX_FMT_BGR0, DRM_FORMAT_XRGB8888 },
395  { AV_PIX_FMT_ARGB, DRM_FORMAT_BGRA8888 },
396  { AV_PIX_FMT_ABGR, DRM_FORMAT_RGBA8888 },
397  { AV_PIX_FMT_RGBA, DRM_FORMAT_ABGR8888 },
398  { AV_PIX_FMT_BGRA, DRM_FORMAT_ARGB8888 },
399  // 10-bit RGB.
400  { AV_PIX_FMT_X2RGB10LE, DRM_FORMAT_XRGB2101010 },
401  { AV_PIX_FMT_X2RGB10BE, DRM_FORMAT_XRGB2101010 | DRM_FORMAT_BIG_ENDIAN },
402  // 8-bit YUV 4:2:0.
403  { AV_PIX_FMT_NV12, DRM_FORMAT_NV12 },
404  // 8-bit YUV 4:2:2.
405  { AV_PIX_FMT_YUYV422, DRM_FORMAT_YUYV },
406  { AV_PIX_FMT_YVYU422, DRM_FORMAT_YVYU },
407  { AV_PIX_FMT_UYVY422, DRM_FORMAT_UYVY },
408 };
409 
411 {
412  KMSGrabContext *ctx = avctx->priv_data;
413  drmModePlaneRes *plane_res = NULL;
414  drmModePlane *plane = NULL;
415  drmModeFB *fb = NULL;
416 #if HAVE_LIBDRM_GETFB2
417  drmModeFB2 *fb2 = NULL;
418 #endif
419  AVStream *stream;
420  int err, i;
421 
423  ctx->device_path, NULL, 0);
424  if (err < 0) {
425  av_log(avctx, AV_LOG_ERROR, "Failed to open DRM device.\n");
426  return err;
427  }
428  ctx->device = (AVHWDeviceContext*) ctx->device_ref->data;
429  ctx->hwctx = (AVDRMDeviceContext*)ctx->device->hwctx;
430 
431  err = drmSetClientCap(ctx->hwctx->fd,
432  DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
433  if (err < 0) {
434  av_log(avctx, AV_LOG_WARNING, "Failed to set universal planes "
435  "capability: primary planes will not be usable.\n");
436  }
437 
438  if (ctx->source_plane > 0) {
439  plane = drmModeGetPlane(ctx->hwctx->fd, ctx->source_plane);
440  if (!plane) {
441  err = errno;
442  av_log(avctx, AV_LOG_ERROR, "Failed to get plane %"PRId64": "
443  "%s.\n", ctx->source_plane, strerror(err));
444  err = AVERROR(err);
445  goto fail;
446  }
447 
448  if (plane->fb_id == 0) {
449  av_log(avctx, AV_LOG_ERROR, "Plane %"PRId64" does not have "
450  "an attached framebuffer.\n", ctx->source_plane);
451  err = AVERROR(EINVAL);
452  goto fail;
453  }
454  } else {
455  plane_res = drmModeGetPlaneResources(ctx->hwctx->fd);
456  if (!plane_res) {
457  err = errno;
458  av_log(avctx, AV_LOG_ERROR, "Failed to get plane "
459  "resources: %s.\n", strerror(err));
460  err = AVERROR(err);
461  goto fail;
462  }
463 
464  for (i = 0; i < plane_res->count_planes; i++) {
465  plane = drmModeGetPlane(ctx->hwctx->fd,
466  plane_res->planes[i]);
467  if (!plane) {
468  err = errno;
469  av_log(avctx, AV_LOG_VERBOSE, "Failed to get "
470  "plane %"PRIu32": %s.\n",
471  plane_res->planes[i], strerror(err));
472  continue;
473  }
474 
475  av_log(avctx, AV_LOG_DEBUG, "Plane %"PRIu32": "
476  "CRTC %"PRIu32" FB %"PRIu32".\n",
477  plane->plane_id, plane->crtc_id, plane->fb_id);
478 
479  if ((ctx->source_crtc > 0 &&
480  plane->crtc_id != ctx->source_crtc) ||
481  plane->fb_id == 0) {
482  // Either not connected to the target source CRTC
483  // or not active.
484  drmModeFreePlane(plane);
485  plane = NULL;
486  continue;
487  }
488 
489  break;
490  }
491 
492  if (i == plane_res->count_planes) {
493  if (ctx->source_crtc > 0) {
494  av_log(avctx, AV_LOG_ERROR, "No usable planes found on "
495  "CRTC %"PRId64".\n", ctx->source_crtc);
496  } else {
497  av_log(avctx, AV_LOG_ERROR, "No usable planes found.\n");
498  }
499  err = AVERROR(EINVAL);
500  goto fail;
501  }
502 
503  av_log(avctx, AV_LOG_INFO, "Using plane %"PRIu32" to "
504  "locate framebuffers.\n", plane->plane_id);
505  }
506 
507  ctx->plane_id = plane->plane_id;
508 
509 #if HAVE_LIBDRM_GETFB2
510  fb2 = drmModeGetFB2(ctx->hwctx->fd, plane->fb_id);
511  if (!fb2 && errno == ENOSYS) {
512  av_log(avctx, AV_LOG_INFO, "GETFB2 not supported, "
513  "will try to use GETFB instead.\n");
514  } else if (!fb2) {
515  err = errno;
516  av_log(avctx, AV_LOG_ERROR, "Failed to get "
517  "framebuffer %"PRIu32": %s.\n",
518  plane->fb_id, strerror(err));
519  err = AVERROR(err);
520  goto fail;
521  } else {
522  av_log(avctx, AV_LOG_INFO, "Template framebuffer is "
523  "%"PRIu32": %"PRIu32"x%"PRIu32" "
524  "format %"PRIx32" modifier %"PRIx64" flags %"PRIx32".\n",
525  fb2->fb_id, fb2->width, fb2->height,
526  fb2->pixel_format, fb2->modifier, fb2->flags);
527 
528  ctx->width = fb2->width;
529  ctx->height = fb2->height;
530 
531  if (!fb2->handles[0]) {
532  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer: "
533  "maybe you need some additional capabilities?\n");
534  err = AVERROR(EINVAL);
535  goto fail;
536  }
537 
538  for (i = 0; i < FF_ARRAY_ELEMS(kmsgrab_formats); i++) {
539  if (kmsgrab_formats[i].drm_format == fb2->pixel_format) {
540  if (ctx->format != AV_PIX_FMT_NONE &&
541  ctx->format != kmsgrab_formats[i].pixfmt) {
542  av_log(avctx, AV_LOG_ERROR, "Framebuffer pixel format "
543  "%"PRIx32" does not match expected format.\n",
544  fb2->pixel_format);
545  err = AVERROR(EINVAL);
546  goto fail;
547  }
548  ctx->drm_format = fb2->pixel_format;
549  ctx->format = kmsgrab_formats[i].pixfmt;
550  break;
551  }
552  }
553  if (i == FF_ARRAY_ELEMS(kmsgrab_formats)) {
554  av_log(avctx, AV_LOG_ERROR, "Framebuffer pixel format "
555  "%"PRIx32" is not a known supported format.\n",
556  fb2->pixel_format);
557  err = AVERROR(EINVAL);
558  goto fail;
559  }
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  av_log(avctx, AV_LOG_VERBOSE, "Format is %s, from "
571  "DRM format %"PRIx32" modifier %"PRIx64".\n",
573  ctx->drm_format, ctx->drm_format_modifier);
574 
575  ctx->fb2_available = 1;
576  }
577 #endif
578 
579  if (!ctx->fb2_available) {
580  if (ctx->format == AV_PIX_FMT_NONE) {
581  // Backward compatibility: assume BGR0 if no format supplied.
582  ctx->format = AV_PIX_FMT_BGR0;
583  }
584  for (i = 0; i < FF_ARRAY_ELEMS(kmsgrab_formats); i++) {
585  if (kmsgrab_formats[i].pixfmt == ctx->format) {
586  ctx->drm_format = kmsgrab_formats[i].drm_format;
587  break;
588  }
589  }
590  if (i >= FF_ARRAY_ELEMS(kmsgrab_formats)) {
591  av_log(avctx, AV_LOG_ERROR, "Unsupported format %s.\n",
593  return AVERROR(EINVAL);
594  }
595 
596  fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id);
597  if (!fb) {
598  err = errno;
599  av_log(avctx, AV_LOG_ERROR, "Failed to get "
600  "framebuffer %"PRIu32": %s.\n",
601  plane->fb_id, strerror(err));
602  err = AVERROR(err);
603  goto fail;
604  }
605 
606  av_log(avctx, AV_LOG_INFO, "Template framebuffer is %"PRIu32": "
607  "%"PRIu32"x%"PRIu32" %"PRIu32"bpp %"PRIu32"b depth.\n",
608  fb->fb_id, fb->width, fb->height, fb->bpp, fb->depth);
609 
610  ctx->width = fb->width;
611  ctx->height = fb->height;
612 
613  if (!fb->handle) {
614  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer: "
615  "maybe you need some additional capabilities?\n");
616  err = AVERROR(EINVAL);
617  goto fail;
618  }
619  }
620 
621  stream = avformat_new_stream(avctx, NULL);
622  if (!stream) {
623  err = AVERROR(ENOMEM);
624  goto fail;
625  }
626 
629  stream->codecpar->width = ctx->width;
630  stream->codecpar->height = ctx->height;
632 
633  avpriv_set_pts_info(stream, 64, 1, 1000000);
634 
636  if (!ctx->frames_ref) {
637  err = AVERROR(ENOMEM);
638  goto fail;
639  }
640  ctx->frames = (AVHWFramesContext*)ctx->frames_ref->data;
641 
643  ctx->frames->sw_format = ctx->format,
644  ctx->frames->width = ctx->width;
645  ctx->frames->height = ctx->height;
646 
647  err = av_hwframe_ctx_init(ctx->frames_ref);
648  if (err < 0) {
649  av_log(avctx, AV_LOG_ERROR, "Failed to initialise "
650  "hardware frames context: %d.\n", err);
651  goto fail;
652  }
653 
654  ctx->frame_delay = av_rescale_q(1, (AVRational) { ctx->framerate.den,
655  ctx->framerate.num }, AV_TIME_BASE_Q);
656 
657  err = 0;
658 fail:
659  drmModeFreePlaneResources(plane_res);
660  drmModeFreePlane(plane);
661  drmModeFreeFB(fb);
662 #if HAVE_LIBDRM_GETFB2
663  drmModeFreeFB2(fb2);
664 #endif
665  return err;
666 }
667 
669 {
670  KMSGrabContext *ctx = avctx->priv_data;
671 
674 
675  return 0;
676 }
677 
678 #define OFFSET(x) offsetof(KMSGrabContext, x)
679 #define FLAGS AV_OPT_FLAG_DECODING_PARAM
680 static const AVOption options[] = {
681  { "device", "DRM device path",
683  { .str = "/dev/dri/card0" }, 0, 0, FLAGS },
684  { "format", "Pixel format for framebuffer",
686  { .i64 = AV_PIX_FMT_NONE }, -1, INT32_MAX, FLAGS },
687  { "format_modifier", "DRM format modifier for framebuffer",
689  { .i64 = DRM_FORMAT_MOD_INVALID }, 0, INT64_MAX, FLAGS },
690  { "crtc_id", "CRTC ID to define capture source",
692  { .i64 = 0 }, 0, UINT32_MAX, FLAGS },
693  { "plane_id", "Plane ID to define capture source",
695  { .i64 = 0 }, 0, UINT32_MAX, FLAGS },
696  { "framerate", "Framerate to capture at",
698  { .dbl = 30.0 }, 0, 1000, FLAGS },
699  { NULL },
700 };
701 
702 static const AVClass kmsgrab_class = {
703  .class_name = "kmsgrab indev",
704  .item_name = av_default_item_name,
705  .option = options,
706  .version = LIBAVUTIL_VERSION_INT,
708 };
709 
711  .name = "kmsgrab",
712  .long_name = NULL_IF_CONFIG_SMALL("KMS screen capture"),
713  .priv_data_size = sizeof(KMSGrabContext),
717  .flags = AVFMT_NOFILE,
718  .priv_class = &kmsgrab_class,
719 };
static const AVClass kmsgrab_class
Definition: kmsgrab.c:702
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:61
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
Definition: pixfmt.h:81
int64_t source_crtc
Definition: kmsgrab.c:70
#define NULL
Definition: coverity.c:32
static const AVOption options[]
Definition: kmsgrab.c:680
int64_t frame_delay
Definition: kmsgrab.c:63
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:125
static void kmsgrab_free_desc(void *opaque, uint8_t *data)
Definition: kmsgrab.c:74
This structure describes decoded (raw) audio or video data.
Definition: frame.h:308
AVOption.
Definition: opt.h:248
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined ...
Definition: pixfmt.h:362
static int kmsgrab_get_fb(AVFormatContext *avctx, drmModePlane *plane, AVDRMFrameDescriptor *desc)
Definition: kmsgrab.c:92
const char * desc
Definition: libsvtav1.c:79
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
Definition: utils.c:4869
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:499
static const struct @197 kmsgrab_formats[]
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
int num
Numerator.
Definition: rational.h:59
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined ...
Definition: pixfmt.h:108
enum AVPixelFormat format
Definition: kmsgrab.c:67
int size
Definition: packet.h:364
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:229
packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
Definition: pixfmt.h:111
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:209
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
Definition: pixfmt.h:239
static AVPacket pkt
int nb_objects
Number of DRM objects making up this frame.
const char * device_path
Definition: kmsgrab.c:66
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
Definition: pixfmt.h:106
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:647
Format I/O context.
Definition: avformat.h:1351
DRM frame descriptor.
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:72
uint8_t
#define av_cold
Definition: attributes.h:88
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:190
int width
Video only.
Definition: codec_par.h:126
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
Definition: pixfmt.h:238
AVOptions.
uint32_t plane_id
Definition: kmsgrab.c:58
size_t size
Total size of the object.
Definition: hwcontext_drm.h:58
DRM plane descriptor.
Definition: hwcontext_drm.h:74
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4450
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
Definition: pixfmt.h:105
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
Definition: pixfmt.h:94
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:92
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:610
uint8_t * data
Definition: packet.h:363
static int kmsgrab_read_packet(AVFormatContext *avctx, AVPacket *pkt)
Definition: kmsgrab.c:265
AVDRMLayerDescriptor layers[AV_DRM_MAX_PLANES]
Array of layers in the frame.
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
ptrdiff_t size
Definition: opengl_enc.c:100
#define av_log(a,...)
int fd
DRM PRIME fd for the object.
Definition: hwcontext_drm.h:52
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
int nb_layers
Number of layers in the frame.
static av_cold int kmsgrab_read_close(AVFormatContext *avctx)
Definition: kmsgrab.c:668
int object_index
Index of the object containing this plane in the objects array of the enclosing frame descriptor...
Definition: hwcontext_drm.h:79
int width
Definition: frame.h:366
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:153
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition: packet.h:346
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
DRM object descriptor.
Definition: hwcontext_drm.h:48
#define OFFSET(x)
Definition: kmsgrab.c:678
int nb_planes
Number of planes in the layer.
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:29
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:333
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
Definition: pixfmt.h:92
#define fail()
Definition: checkasm.h:123
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:93
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:369
common internal API header
#define fb(width, name)
Definition: cbs_av1.c:548
AVDRMPlaneDescriptor planes[AV_DRM_MAX_PLANES]
Array of planes in this layer.
uint32_t drm_format
Definition: kmsgrab.c:59
AVRational framerate
Definition: kmsgrab.c:71
#define DRM_FORMAT_MOD_INVALID
Definition: kmsgrab.c:32
AVFormatContext * ctx
Definition: movenc.c:48
int fb2_available
Definition: kmsgrab.c:53
packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb
Definition: pixfmt.h:210
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
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES]
Array of objects making up the frame.
Passthrough codec, AVFrames wrapped in AVPacket.
Definition: codec_id.h:564
AVHWDeviceContext * device
Definition: kmsgrab.c:51
packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
Definition: pixfmt.h:110
packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined ...
Definition: pixfmt.h:361
#define FF_ARRAY_ELEMS(a)
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:527
int64_t av_gettime(void)
Get the current time in microseconds.
Definition: time.c:39
Stream structure.
Definition: avformat.h:876
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:381
packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
Definition: pixfmt.h:83
#define AV_LOG_INFO
Standard information.
Definition: log.h:205
int64_t source_plane
Definition: kmsgrab.c:69
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
unsigned int width
Definition: kmsgrab.c:60
uint8_t * data
The data buffer.
Definition: buffer.h:89
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:67
Describe the class of an AVClass context structure.
Definition: log.h:67
Y , 16bpp, big-endian.
Definition: pixfmt.h:97
Rational number (pair of numerator and denominator).
Definition: rational.h:58
DRM-managed buffers exposed through PRIME buffer sharing.
Definition: pixfmt.h:328
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
Definition: pixfmt.h:240
packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined ...
Definition: pixfmt.h:113
AVDRMDeviceContext * hwctx
Definition: kmsgrab.c:52
API-specific header for AV_HWDEVICE_TYPE_DRM.
#define AV_PKT_FLAG_TRUSTED
The packet comes from a trusted source.
Definition: packet.h:415
#define flags(name, subs,...)
Definition: cbs_av1.c:560
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
Definition: pixfmt.h:107
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:322
A reference to a data buffer.
Definition: buffer.h:81
Main libavformat public API header.
Y , 8bpp.
Definition: pixfmt.h:74
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:458
int fd
File descriptor of DRM device.
static void kmsgrab_free_frame(void *opaque, uint8_t *data)
Definition: kmsgrab.c:85
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:247
#define FLAGS
Definition: kmsgrab.c:679
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
unsigned int height
Definition: kmsgrab.c:61
int den
Denominator.
Definition: rational.h:60
static av_cold int kmsgrab_read_header(AVFormatContext *avctx)
Definition: kmsgrab.c:410
pixel format definitions
#define av_free(p)
AVHWFramesContext * frames
Definition: kmsgrab.c:56
int64_t drm_format_modifier
Definition: kmsgrab.c:68
void * priv_data
Format private data.
Definition: avformat.h:1379
Y , 16bpp, little-endian.
Definition: pixfmt.h:98
AVInputFormat ff_kmsgrab_demuxer
Definition: kmsgrab.c:710
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:367
AVBufferRef * device_ref
Definition: kmsgrab.c:50
packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined
Definition: pixfmt.h:112
int height
Definition: frame.h:366
#define av_freep(p)
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:650
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1023
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:2489
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
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
Definition: pixfmt.h:237
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:222
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
This structure stores compressed data.
Definition: packet.h:340
AVBufferRef * frames_ref
Definition: kmsgrab.c:55
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:356
int i
Definition: input.c:407
int64_t frame_last
Definition: kmsgrab.c:64