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/mem.h"
40 #include "libavutil/opt.h"
41 #include "libavutil/pixfmt.h"
42 #include "libavutil/pixdesc.h"
43 #include "libavutil/time.h"
44 
45 #include "libavformat/avformat.h"
46 #include "libavformat/demux.h"
47 #include "libavformat/internal.h"
48 
49 typedef struct KMSGrabContext {
50  const AVClass *class;
51 
56 
59 
60  uint32_t plane_id;
61  uint32_t drm_format;
62  unsigned int width;
63  unsigned int height;
64 
67 
68  const char *device_path;
75 
76 static void kmsgrab_free_desc(void *opaque, uint8_t *data)
77 {
79  int i;
80 
81  for (i = 0; i < desc->nb_objects; i++)
82  close(desc->objects[i].fd);
83 
84  av_free(desc);
85 }
86 
87 static void kmsgrab_free_frame(void *opaque, uint8_t *data)
88 {
90 
92 }
93 
94 static int kmsgrab_get_fb(AVFormatContext *avctx,
95  drmModePlane *plane,
97 {
98  KMSGrabContext *ctx = avctx->priv_data;
99  drmModeFB *fb = NULL;
100  int err, fd;
101 
102  fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id);
103  if (!fb) {
104  err = errno;
105  av_log(avctx, AV_LOG_ERROR, "Failed to get framebuffer "
106  "%"PRIu32": %s.\n", plane->fb_id, strerror(err));
107  err = AVERROR(err);
108  goto fail;
109  }
110  if (fb->width != ctx->width || fb->height != ctx->height) {
111  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
112  "dimensions changed: now %"PRIu32"x%"PRIu32".\n",
113  ctx->plane_id, fb->width, fb->height);
114  err = AVERROR(EIO);
115  goto fail;
116  }
117  if (!fb->handle) {
118  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer.\n");
119  err = AVERROR(EIO);
120  goto fail;
121  }
122 
123  err = drmPrimeHandleToFD(ctx->hwctx->fd, fb->handle, O_RDONLY, &fd);
124  if (err < 0) {
125  err = errno;
126  av_log(avctx, AV_LOG_ERROR, "Failed to get PRIME fd from "
127  "framebuffer handle: %s.\n", strerror(err));
128  err = AVERROR(err);
129  goto fail;
130  }
131 
133  .nb_objects = 1,
134  .objects[0] = {
135  .fd = fd,
136  .size = fb->height * fb->pitch,
137  .format_modifier = ctx->drm_format_modifier,
138  },
139  .nb_layers = 1,
140  .layers[0] = {
141  .format = ctx->drm_format,
142  .nb_planes = 1,
143  .planes[0] = {
144  .object_index = 0,
145  .offset = 0,
146  .pitch = fb->pitch,
147  },
148  },
149  };
150 
151  err = 0;
152 fail:
153  drmModeFreeFB(fb);
154  return err;
155 }
156 
157 #if HAVE_LIBDRM_GETFB2
158 static int kmsgrab_get_fb2(AVFormatContext *avctx,
159  drmModePlane *plane,
161 {
162  KMSGrabContext *ctx = avctx->priv_data;
163  drmModeFB2 *fb;
164  int err, i, nb_objects;
165  uint64_t modifier = ctx->drm_format_modifier;
166 
167  fb = drmModeGetFB2(ctx->hwctx->fd, plane->fb_id);
168  if (!fb) {
169  err = errno;
170  av_log(avctx, AV_LOG_ERROR, "Failed to get framebuffer "
171  "%"PRIu32": %s.\n", plane->fb_id, strerror(err));
172  return AVERROR(err);
173  }
174  if (fb->pixel_format != ctx->drm_format) {
175  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
176  "format changed: now %"PRIx32".\n",
177  ctx->plane_id, fb->pixel_format);
178  err = AVERROR(EIO);
179  goto fail;
180  }
181  if (fb->width != ctx->width || fb->height != ctx->height) {
182  av_log(avctx, AV_LOG_ERROR, "Plane %"PRIu32" framebuffer "
183  "dimensions changed: now %"PRIu32"x%"PRIu32".\n",
184  ctx->plane_id, fb->width, fb->height);
185  err = AVERROR(EIO);
186  goto fail;
187  }
188  if (!fb->handles[0]) {
189  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer.\n");
190  err = AVERROR(EIO);
191  goto fail;
192  }
193 
194  if (fb->flags & DRM_MODE_FB_MODIFIERS)
195  modifier = fb->modifier;
196 
198  .nb_layers = 1,
199  .layers[0] = {
200  .format = ctx->drm_format,
201  },
202  };
203 
204  nb_objects = 0;
205  for (i = 0; i < 4 && fb->handles[i]; i++) {
206  size_t size;
207  int dup = 0, j, obj;
208 
209  size = fb->offsets[i] + fb->height * fb->pitches[i];
210 
211  for (j = 0; j < i; j++) {
212  if (fb->handles[i] == fb->handles[j]) {
213  dup = 1;
214  break;
215  }
216  }
217  if (dup) {
218  obj = desc->layers[0].planes[j].object_index;
219 
220  if (desc->objects[j].size < size)
221  desc->objects[j].size = size;
222 
223  desc->layers[0].planes[i] = (AVDRMPlaneDescriptor) {
224  .object_index = obj,
225  .offset = fb->offsets[i],
226  .pitch = fb->pitches[i],
227  };
228 
229  } else {
230  int fd;
231  err = drmPrimeHandleToFD(ctx->hwctx->fd, fb->handles[i],
232  O_RDONLY, &fd);
233  if (err < 0) {
234  err = errno;
235  av_log(avctx, AV_LOG_ERROR, "Failed to get PRIME fd from "
236  "framebuffer handle: %s.\n", strerror(err));
237  err = AVERROR(err);
238  goto fail;
239  }
240 
241  obj = nb_objects++;
242  desc->objects[obj] = (AVDRMObjectDescriptor) {
243  .fd = fd,
244  .size = size,
245  .format_modifier = modifier,
246  };
247  desc->layers[0].planes[i] = (AVDRMPlaneDescriptor) {
248  .object_index = obj,
249  .offset = fb->offsets[i],
250  .pitch = fb->pitches[i],
251  };
252  }
253  }
254  desc->nb_objects = nb_objects;
255  desc->layers[0].nb_planes = i;
256 
257  err = 0;
258 fail:
259  drmModeFreeFB2(fb);
260  return err;
261 }
262 #endif
263 
265 {
266  KMSGrabContext *ctx = avctx->priv_data;
267  drmModePlane *plane = NULL;
269  AVFrame *frame = NULL;
270  int64_t now;
271  int err;
272 
273  now = av_gettime_relative();
274  if (ctx->frame_last) {
275  int64_t delay;
276  while (1) {
277  delay = ctx->frame_last + ctx->frame_delay - now;
278  if (delay <= 0)
279  break;
280  av_usleep(delay);
281  now = av_gettime_relative();
282  }
283  }
284  ctx->frame_last = now;
285  now = av_gettime();
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;
356 
357  return 0;
358 
359 fail:
360  drmModeFreePlane(plane);
361  av_freep(&desc);
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 
422  err = av_hwdevice_ctx_create(&ctx->device_ref, AV_HWDEVICE_TYPE_DRM,
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  }
560 
561  if (fb2->flags & DRM_MODE_FB_MODIFIERS) {
562  if (ctx->drm_format_modifier != DRM_FORMAT_MOD_INVALID &&
563  ctx->drm_format_modifier != fb2->modifier) {
564  av_log(avctx, AV_LOG_ERROR, "Framebuffer format modifier "
565  "%"PRIx64" does not match expected modifier.\n",
566  fb2->modifier);
567  err = AVERROR(EINVAL);
568  goto fail;
569  } else {
570  ctx->drm_format_modifier = fb2->modifier;
571  }
572  }
573  av_log(avctx, AV_LOG_VERBOSE, "Format is %s, from "
574  "DRM format %"PRIx32" modifier %"PRIx64".\n",
575  av_get_pix_fmt_name(ctx->format),
576  ctx->drm_format, ctx->drm_format_modifier);
577 
578  ctx->fb2_available = 1;
579  }
580 #endif
581 
582  if (!ctx->fb2_available) {
583  if (ctx->format == AV_PIX_FMT_NONE) {
584  // Backward compatibility: assume BGR0 if no format supplied.
585  ctx->format = AV_PIX_FMT_BGR0;
586  }
587  for (i = 0; i < FF_ARRAY_ELEMS(kmsgrab_formats); i++) {
588  if (kmsgrab_formats[i].pixfmt == ctx->format) {
589  ctx->drm_format = kmsgrab_formats[i].drm_format;
590  break;
591  }
592  }
593  if (i >= FF_ARRAY_ELEMS(kmsgrab_formats)) {
594  av_log(avctx, AV_LOG_ERROR, "Unsupported format %s.\n",
595  av_get_pix_fmt_name(ctx->format));
596  return AVERROR(EINVAL);
597  }
598 
599  fb = drmModeGetFB(ctx->hwctx->fd, plane->fb_id);
600  if (!fb) {
601  err = errno;
602  av_log(avctx, AV_LOG_ERROR, "Failed to get "
603  "framebuffer %"PRIu32": %s.\n",
604  plane->fb_id, strerror(err));
605  err = AVERROR(err);
606  goto fail;
607  }
608 
609  av_log(avctx, AV_LOG_INFO, "Template framebuffer is %"PRIu32": "
610  "%"PRIu32"x%"PRIu32" %"PRIu32"bpp %"PRIu32"b depth.\n",
611  fb->fb_id, fb->width, fb->height, fb->bpp, fb->depth);
612 
613  ctx->width = fb->width;
614  ctx->height = fb->height;
615 
616  if (!fb->handle) {
617  av_log(avctx, AV_LOG_ERROR, "No handle set on framebuffer: "
618  "maybe you need some additional capabilities?\n");
619  err = AVERROR(EINVAL);
620  goto fail;
621  }
622  }
623 
624  stream = avformat_new_stream(avctx, NULL);
625  if (!stream) {
626  err = AVERROR(ENOMEM);
627  goto fail;
628  }
629 
632  stream->codecpar->width = ctx->width;
633  stream->codecpar->height = ctx->height;
635 
636  avpriv_set_pts_info(stream, 64, 1, 1000000);
637 
638  ctx->frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
639  if (!ctx->frames_ref) {
640  err = AVERROR(ENOMEM);
641  goto fail;
642  }
643  ctx->frames = (AVHWFramesContext*)ctx->frames_ref->data;
644 
645  ctx->frames->format = AV_PIX_FMT_DRM_PRIME;
646  ctx->frames->sw_format = ctx->format,
647  ctx->frames->width = ctx->width;
648  ctx->frames->height = ctx->height;
649 
650  err = av_hwframe_ctx_init(ctx->frames_ref);
651  if (err < 0) {
652  av_log(avctx, AV_LOG_ERROR, "Failed to initialise "
653  "hardware frames context: %d.\n", err);
654  goto fail;
655  }
656 
657  ctx->frame_delay = av_rescale_q(1, (AVRational) { ctx->framerate.den,
658  ctx->framerate.num }, AV_TIME_BASE_Q);
659 
660  err = 0;
661 fail:
662  drmModeFreePlaneResources(plane_res);
663  drmModeFreePlane(plane);
664  drmModeFreeFB(fb);
665 #if HAVE_LIBDRM_GETFB2
666  drmModeFreeFB2(fb2);
667 #endif
668  return err;
669 }
670 
672 {
673  KMSGrabContext *ctx = avctx->priv_data;
674 
675  av_buffer_unref(&ctx->frames_ref);
676  av_buffer_unref(&ctx->device_ref);
677 
678  return 0;
679 }
680 
681 #define OFFSET(x) offsetof(KMSGrabContext, x)
682 #define FLAGS AV_OPT_FLAG_DECODING_PARAM
683 static const AVOption options[] = {
684  { "device", "DRM device path",
685  OFFSET(device_path), AV_OPT_TYPE_STRING,
686  { .str = "/dev/dri/card0" }, 0, 0, FLAGS },
687  { "format", "Pixel format for framebuffer",
689  { .i64 = AV_PIX_FMT_NONE }, -1, INT32_MAX, FLAGS },
690  { "format_modifier", "DRM format modifier for framebuffer",
691  OFFSET(drm_format_modifier), AV_OPT_TYPE_INT64,
692  { .i64 = DRM_FORMAT_MOD_INVALID }, 0, INT64_MAX, FLAGS },
693  { "crtc_id", "CRTC ID to define capture source",
694  OFFSET(source_crtc), AV_OPT_TYPE_INT64,
695  { .i64 = 0 }, 0, UINT32_MAX, FLAGS },
696  { "plane_id", "Plane ID to define capture source",
697  OFFSET(source_plane), AV_OPT_TYPE_INT64,
698  { .i64 = 0 }, 0, UINT32_MAX, FLAGS },
699  { "framerate", "Framerate to capture at",
701  { .dbl = 30.0 }, 0, 1000, FLAGS },
702  { NULL },
703 };
704 
705 static const AVClass kmsgrab_class = {
706  .class_name = "kmsgrab indev",
707  .item_name = av_default_item_name,
708  .option = options,
709  .version = LIBAVUTIL_VERSION_INT,
711 };
712 
714  .p.name = "kmsgrab",
715  .p.long_name = NULL_IF_CONFIG_SMALL("KMS screen capture"),
716  .p.flags = AVFMT_NOFILE,
717  .p.priv_class = &kmsgrab_class,
718  .priv_data_size = sizeof(KMSGrabContext),
722 };
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:215
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:57
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
int64_t
long long int64_t
Definition: coverity.c:34
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:162
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:66
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
pixdesc.h
KMSGrabContext::device_path
const char * device_path
Definition: kmsgrab.c:68
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:539
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:60
AVOption
AVOption.
Definition: opt.h:429
data
const char data[16]
Definition: mxf.c:149
KMSGrabContext::width
unsigned int width
Definition: kmsgrab.c:62
kmsgrab_get_fb
static int kmsgrab_get_fb(AVFormatContext *avctx, drmModePlane *plane, AVDRMFrameDescriptor *desc)
Definition: kmsgrab.c:94
KMSGrabContext::frame_delay
int64_t frame_delay
Definition: kmsgrab.c:65
KMSGrabContext::height
unsigned int height
Definition: kmsgrab.c:63
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:225
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
Underlying C type is AVRational.
Definition: opt.h:280
KMSGrabContext::frames
AVHWFramesContext * frames
Definition: kmsgrab.c:58
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_formats
static const struct @299 kmsgrab_formats[]
kmsgrab_read_close
static av_cold int kmsgrab_read_close(AVFormatContext *avctx)
Definition: kmsgrab.c:671
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:867
fail
#define fail()
Definition: checkasm.h:188
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:150
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:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
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:42
kmsgrab_read_packet
static int kmsgrab_read_packet(AVFormatContext *avctx, AVPacket *pkt)
Definition: kmsgrab.c:264
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
Underlying C type is int64_t.
Definition: opt.h:263
KMSGrabContext::drm_format_modifier
int64_t drm_format_modifier
Definition: kmsgrab.c:70
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:230
ctx
AVFormatContext * ctx
Definition: movenc.c:49
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:608
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:52
AVFormatContext
Format I/O context.
Definition: avformat.h:1300
internal.h
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:771
AVPacket::buf
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
Definition: packet.h:522
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:540
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
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:73
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
AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
@ AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
Definition: log.h:41
KMSGrabContext
Definition: kmsgrab.c:49
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:72
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:540
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:94
ff_kmsgrab_demuxer
const FFInputFormat ff_kmsgrab_demuxer
Definition: kmsgrab.c:713
size
int size
Definition: twinvq_data.h:10344
KMSGrabContext::drm_format
uint32_t drm_format
Definition: kmsgrab.c:61
OFFSET
#define OFFSET(x)
Definition: kmsgrab.c:681
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:69
FFInputFormat::p
AVInputFormat p
The public AVInputFormat.
Definition: demux.h:46
KMSGrabContext::hwctx
AVDRMDeviceContext * hwctx
Definition: kmsgrab.c:54
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:545
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:220
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:55
kmsgrab_read_header
static av_cold int kmsgrab_read_header(AVFormatContext *avctx)
Definition: kmsgrab.c:410
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:256
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:532
kmsgrab_free_frame
static void kmsgrab_free_frame(void *opaque, uint8_t *data)
Definition: kmsgrab.c:87
internal.h
AVCodecParameters::height
int height
Definition: codec_par.h:135
fb
#define fb(width, name)
Definition: cbs_av1.c:593
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:256
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:748
pixfmt
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:367
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:80
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:368
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:683
AV_OPT_TYPE_PIXEL_FMT
@ AV_OPT_TYPE_PIXEL_FMT
Underlying C type is enum AVPixelFormat.
Definition: opt.h:307
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:79
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
mem.h
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:76
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:516
KMSGrabContext::device
AVHWDeviceContext * device
Definition: kmsgrab.c:53
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
FFInputFormat
Definition: demux.h:42
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:705
KMSGrabContext::source_plane
int64_t source_plane
Definition: kmsgrab.c:71
AVDRMDeviceContext
DRM device.
Definition: hwcontext_drm.h:157
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
AV_PKT_FLAG_TRUSTED
#define AV_PKT_FLAG_TRUSTED
The packet comes from a trusted source.
Definition: packet.h:608
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1328
FLAGS
#define FLAGS
Definition: kmsgrab.c:682
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:3090