25 #include <drm_fourcc.h>
28 #include <xf86drmMode.h>
31 #ifndef DRM_FORMAT_MOD_INVALID
32 #define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
79 for (
i = 0;
i <
desc->nb_objects;
i++)
80 close(
desc->objects[
i].fd);
100 fb = drmModeGetFB(
ctx->hwctx->fd, plane->fb_id);
104 "%"PRIu32
": %s.\n", plane->fb_id, strerror(err));
108 if (
fb->width !=
ctx->width ||
fb->height !=
ctx->height) {
110 "dimensions changed: now %"PRIu32
"x%"PRIu32
".\n",
111 ctx->plane_id,
fb->width,
fb->height);
121 err = drmPrimeHandleToFD(
ctx->hwctx->fd,
fb->handle, O_RDONLY, &fd);
125 "framebuffer handle: %s.\n", strerror(err));
134 .size =
fb->height *
fb->pitch,
135 .format_modifier =
ctx->drm_format_modifier,
139 .format =
ctx->drm_format,
155 #if HAVE_LIBDRM_GETFB2
162 int err,
i, nb_objects;
163 uint64_t modifier =
ctx->drm_format_modifier;
165 fb = drmModeGetFB2(
ctx->hwctx->fd, plane->fb_id);
169 "%"PRIu32
": %s.\n", plane->fb_id, strerror(err));
172 if (
fb->pixel_format !=
ctx->drm_format) {
174 "format changed: now %"PRIx32
".\n",
175 ctx->plane_id,
fb->pixel_format);
179 if (
fb->width !=
ctx->width ||
fb->height !=
ctx->height) {
181 "dimensions changed: now %"PRIu32
"x%"PRIu32
".\n",
182 ctx->plane_id,
fb->width,
fb->height);
186 if (!
fb->handles[0]) {
192 if (
fb->flags & DRM_MODE_FB_MODIFIERS)
193 modifier =
fb->modifier;
198 .format =
ctx->drm_format,
203 for (
i = 0;
i < 4 &&
fb->handles[
i];
i++) {
209 for (j = 0; j <
i; j++) {
210 if (
fb->handles[
i] ==
fb->handles[j]) {
216 obj =
desc->layers[0].planes[j].object_index;
223 .offset =
fb->offsets[
i],
224 .pitch =
fb->pitches[
i],
229 err = drmPrimeHandleToFD(
ctx->hwctx->fd,
fb->handles[
i],
234 "framebuffer handle: %s.\n", strerror(err));
243 .format_modifier = modifier,
247 .offset =
fb->offsets[
i],
248 .pitch =
fb->pitches[
i],
252 desc->nb_objects = nb_objects;
253 desc->layers[0].nb_planes =
i;
265 drmModePlane *plane =
NULL;
272 if (
ctx->frame_last) {
275 delay =
ctx->frame_last +
ctx->frame_delay - now;
282 ctx->frame_last = now;
285 plane = drmModeGetPlane(
ctx->hwctx->fd,
ctx->plane_id);
289 "%"PRIu32
": %s.\n",
ctx->plane_id, strerror(err));
295 "an associated framebuffer.\n",
ctx->plane_id);
306 #if HAVE_LIBDRM_GETFB2
307 if (
ctx->fb2_available)
308 err = kmsgrab_get_fb2(avctx, plane,
desc);
339 drmModeFreePlane(plane);
358 drmModeFreePlane(plane);
364 static const struct {
372 #ifdef DRM_FORMAT_R16
411 drmModePlaneRes *plane_res =
NULL;
412 drmModePlane *plane =
NULL;
414 #if HAVE_LIBDRM_GETFB2
415 drmModeFB2 *fb2 =
NULL;
429 err = drmSetClientCap(
ctx->hwctx->fd,
430 DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
433 "capability: primary planes will not be usable.\n");
436 if (
ctx->source_plane > 0) {
437 plane = drmModeGetPlane(
ctx->hwctx->fd,
ctx->source_plane);
441 "%s.\n",
ctx->source_plane, strerror(err));
446 if (plane->fb_id == 0) {
448 "an attached framebuffer.\n",
ctx->source_plane);
453 plane_res = drmModeGetPlaneResources(
ctx->hwctx->fd);
457 "resources: %s.\n", strerror(err));
462 for (
i = 0;
i < plane_res->count_planes;
i++) {
463 plane = drmModeGetPlane(
ctx->hwctx->fd,
464 plane_res->planes[
i]);
468 "plane %"PRIu32
": %s.\n",
469 plane_res->planes[
i], strerror(err));
474 "CRTC %"PRIu32
" FB %"PRIu32
".\n",
475 plane->plane_id, plane->crtc_id, plane->fb_id);
477 if ((
ctx->source_crtc > 0 &&
478 plane->crtc_id !=
ctx->source_crtc) ||
482 drmModeFreePlane(plane);
490 if (
i == plane_res->count_planes) {
491 if (
ctx->source_crtc > 0) {
493 "CRTC %"PRId64
".\n",
ctx->source_crtc);
502 "locate framebuffers.\n", plane->plane_id);
505 ctx->plane_id = plane->plane_id;
507 #if HAVE_LIBDRM_GETFB2
508 fb2 = drmModeGetFB2(
ctx->hwctx->fd, plane->fb_id);
509 if (!fb2 && errno == ENOSYS) {
511 "will try to use GETFB instead.\n");
515 "framebuffer %"PRIu32
": %s.\n",
516 plane->fb_id, strerror(err));
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);
526 ctx->width = fb2->width;
527 ctx->height = fb2->height;
529 if (!fb2->handles[0]) {
531 "maybe you need some additional capabilities?\n");
541 "%"PRIx32
" does not match expected format.\n",
546 ctx->drm_format = fb2->pixel_format;
553 "%"PRIx32
" is not a known supported format.\n",
559 if (fb2->flags & DRM_MODE_FB_MODIFIERS) {
561 ctx->drm_format_modifier != fb2->modifier) {
563 "%"PRIx64
" does not match expected modifier.\n",
568 ctx->drm_format_modifier = fb2->modifier;
572 "DRM format %"PRIx32
" modifier %"PRIx64
".\n",
574 ctx->drm_format,
ctx->drm_format_modifier);
576 ctx->fb2_available = 1;
580 if (!
ctx->fb2_available) {
597 fb = drmModeGetFB(
ctx->hwctx->fd, plane->fb_id);
601 "framebuffer %"PRIu32
": %s.\n",
602 plane->fb_id, strerror(err));
608 "%"PRIu32
"x%"PRIu32
" %"PRIu32
"bpp %"PRIu32
"b depth.\n",
609 fb->fb_id,
fb->width,
fb->height,
fb->bpp,
fb->depth);
611 ctx->width =
fb->width;
612 ctx->height =
fb->height;
616 "maybe you need some additional capabilities?\n");
637 if (!
ctx->frames_ref) {
644 ctx->frames->sw_format =
ctx->format,
645 ctx->frames->width =
ctx->width;
646 ctx->frames->height =
ctx->height;
651 "hardware frames context: %d.\n", err);
660 drmModeFreePlaneResources(plane_res);
661 drmModeFreePlane(plane);
663 #if HAVE_LIBDRM_GETFB2
679 #define OFFSET(x) offsetof(KMSGrabContext, x)
680 #define FLAGS AV_OPT_FLAG_DECODING_PARAM
682 {
"device",
"DRM device path",
684 { .str =
"/dev/dri/card0" }, 0, 0,
FLAGS },
685 {
"format",
"Pixel format for framebuffer",
688 {
"format_modifier",
"DRM format modifier for framebuffer",
691 {
"crtc_id",
"CRTC ID to define capture source",
693 { .i64 = 0 }, 0, UINT32_MAX,
FLAGS },
694 {
"plane_id",
"Plane ID to define capture source",
696 { .i64 = 0 }, 0, UINT32_MAX,
FLAGS },
697 {
"framerate",
"Framerate to capture at",
699 { .dbl = 30.0 }, 0, 1000,
FLAGS },
static const char *const format[]
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
#define flags(name, subs,...)
static int read_header(FFV1Context *f)
@ AV_CODEC_ID_WRAPPED_AVFRAME
Passthrough codec, AVFrames wrapped in AVPacket.
#define AV_PKT_FLAG_TRUSTED
The packet comes from a trusted source.
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
AVBufferRef * av_buffer_create(uint8_t *data, buffer_size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
#define LIBAVUTIL_VERSION_INT
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.
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
API-specific header for AV_HWDEVICE_TYPE_DRM.
static const AVClass kmsgrab_class
static const AVOption options[]
static int kmsgrab_get_fb(AVFormatContext *avctx, drmModePlane *plane, AVDRMFrameDescriptor *desc)
static const struct @192 kmsgrab_formats[]
static av_cold int kmsgrab_read_header(AVFormatContext *avctx)
static av_cold int kmsgrab_read_close(AVFormatContext *avctx)
static int kmsgrab_read_packet(AVFormatContext *avctx, AVPacket *pkt)
enum AVPixelFormat pixfmt
AVInputFormat ff_kmsgrab_demuxer
static void kmsgrab_free_desc(void *opaque, uint8_t *data)
#define DRM_FORMAT_MOD_INVALID
static void kmsgrab_free_frame(void *opaque, uint8_t *data)
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static av_cold int read_close(AVFormatContext *ctx)
@ AV_CLASS_CATEGORY_DEVICE_VIDEO_INPUT
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.
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_GRAY16BE
Y , 16bpp, big-endian.
@ 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...
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
@ AV_PIX_FMT_BGR565BE
packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), big-endian
@ AV_PIX_FMT_BGR0
packed BGR 8:8:8, 32bpp, BGRXBGRX... X=unused/undefined
@ AV_PIX_FMT_ARGB
packed ARGB 8:8:8:8, 32bpp, ARGBARGB...
@ AV_PIX_FMT_RGB555BE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), big-endian , X=unused/undefined
@ AV_PIX_FMT_YVYU422
packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
@ AV_PIX_FMT_UYVY422
packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
@ AV_PIX_FMT_ABGR
packed ABGR 8:8:8:8, 32bpp, ABGRABGR...
@ AV_PIX_FMT_0BGR
packed BGR 8:8:8, 32bpp, XBGRXBGR... X=unused/undefined
@ AV_PIX_FMT_BGR8
packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
@ AV_PIX_FMT_DRM_PRIME
DRM-managed buffers exposed through PRIME buffer sharing.
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
@ AV_PIX_FMT_RGB565LE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), little-endian
@ AV_PIX_FMT_RGB555LE
packed RGB 5:5:5, 16bpp, (msb)1X 5R 5G 5B(lsb), little-endian, X=unused/undefined
@ AV_PIX_FMT_BGR555BE
packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), big-endian , X=unused/undefined
@ AV_PIX_FMT_X2RGB10LE
packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), little-endian, X=unused/undefined
@ AV_PIX_FMT_RGB0
packed RGB 8:8:8, 32bpp, RGBXRGBX... X=unused/undefined
@ AV_PIX_FMT_GRAY16LE
Y , 16bpp, little-endian.
@ AV_PIX_FMT_RGB565BE
packed RGB 5:6:5, 16bpp, (msb) 5R 6G 5B(lsb), big-endian
@ AV_PIX_FMT_BGR555LE
packed BGR 5:5:5, 16bpp, (msb)1X 5B 5G 5R(lsb), little-endian, X=unused/undefined
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
@ AV_PIX_FMT_0RGB
packed RGB 8:8:8, 32bpp, XRGBXRGB... X=unused/undefined
@ AV_PIX_FMT_BGR565LE
packed BGR 5:6:5, 16bpp, (msb) 5B 6G 5R(lsb), little-endian
@ AV_PIX_FMT_X2RGB10BE
packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
Describe the class of an AVClass context structure.
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
enum AVMediaType codec_type
General type of the encoded data.
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
void * priv_data
Format private data.
This structure describes decoded (raw) audio or video data.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
This struct describes a set or pool of "hardware" frames (i.e.
This structure stores compressed data.
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
int flags
A combination of AV_PKT_FLAG values.
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Rational number (pair of numerator and denominator).
AVCodecParameters * codecpar
Codec parameters associated with this stream.
int64_t drm_format_modifier
AVHWFramesContext * frames
AVHWDeviceContext * device
enum AVPixelFormat format
AVDRMDeviceContext * hwctx
int av_usleep(unsigned usec)
Sleep for a period of time.
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
int64_t av_gettime(void)
Get the current time in microseconds.