22 # include <va/va_x11.h>
25 # include <va/va_drm.h>
29 # include <va/va_drmcommon.h>
30 # include <drm_fourcc.h>
89 #define MAP(va, rt, av) { \
91 VA_RT_FORMAT_ ## rt, \
101 MAP(NV12, YUV420, NV12),
102 MAP(YV12, YUV420, YUV420P),
103 MAP(IYUV, YUV420, YUV420P),
105 #ifdef VA_FOURCC_YV16
106 MAP(YV16, YUV422, YUV422P),
108 MAP(422
H, YUV422, YUV422P),
109 MAP(UYVY, YUV422, UYVY422),
110 MAP(YUY2, YUV422, YUYV422),
111 MAP(Y800, YUV400, GRAY8),
112 #ifdef VA_FOURCC_P010
113 MAP(P010, YUV420_10BPP, P010),
115 MAP(BGRA, RGB32, BGRA),
116 MAP(BGRX, RGB32, BGR0),
118 MAP(RGBX, RGB32, RGB0),
119 #ifdef VA_FOURCC_ABGR
120 MAP(ABGR, RGB32, ABGR),
121 MAP(XBGR, RGB32, 0BGR),
123 MAP(ARGB, RGB32, ARGB),
124 MAP(XRGB, RGB32, 0RGB),
139 VAImageFormat **image_format)
155 const void *hwconfig,
161 VASurfaceAttrib *attr_list =
NULL;
165 int err, i, j, attr_count, pix_fmt_count;
172 if (vas != VA_STATUS_SUCCESS) {
174 "%d (%s).\n", vas, vaErrorStr(vas));
179 attr_list =
av_malloc(attr_count *
sizeof(*attr_list));
186 attr_list, &attr_count);
187 if (vas != VA_STATUS_SUCCESS) {
189 "%d (%s).\n", vas, vaErrorStr(vas));
195 for (i = 0; i < attr_count; i++) {
196 switch (attr_list[i].
type) {
197 case VASurfaceAttribPixelFormat:
198 fourcc = attr_list[i].value.value.i;
206 case VASurfaceAttribMinWidth:
207 constraints->
min_width = attr_list[i].value.value.i;
209 case VASurfaceAttribMinHeight:
210 constraints->
min_height = attr_list[i].value.value.i;
212 case VASurfaceAttribMaxWidth:
213 constraints->
max_width = attr_list[i].value.value.i;
215 case VASurfaceAttribMaxHeight:
216 constraints->
max_height = attr_list[i].value.value.i;
220 if (pix_fmt_count == 0) {
232 for (i = j = 0; i < attr_count; i++) {
233 if (attr_list[i].
type != VASurfaceAttribPixelFormat)
235 fourcc = attr_list[i].value.value.i;
271 static const struct {
277 "Intel i965 (Quick Sync)",
288 "Splitted-Desktop Systems VDPAU backend for VA-API",
297 VAImageFormat *image_list =
NULL;
299 const char *vendor_string;
300 int err, i, image_count;
304 image_count = vaMaxNumImageFormats(hwctx->
display);
305 if (image_count <= 0) {
309 image_list =
av_malloc(image_count *
sizeof(*image_list));
314 vas = vaQueryImageFormats(hwctx->
display, image_list, &image_count);
315 if (vas != VA_STATUS_SUCCESS) {
326 for (i = 0; i < image_count; i++) {
327 fourcc = image_list[i].fourcc;
343 "quirks set by user.\n");
346 vendor_string = vaQueryVendorString(hwctx->
display);
350 if (strstr(vendor_string,
353 "driver \"%s\".\n", vendor_string,
362 "assuming standard behaviour.\n", vendor_string);
386 VASurfaceID surface_id;
389 surface_id = (VASurfaceID)(uintptr_t)
data;
391 vas = vaDestroySurfaces(hwctx->
display, &surface_id, 1);
392 if (vas != VA_STATUS_SUCCESS) {
394 "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
404 VASurfaceID surface_id;
416 if (vas != VA_STATUS_SUCCESS) {
418 "%d (%s).\n", vas, vaErrorStr(vas));
427 vaDestroySurfaces(hwctx->
display, &surface_id, 1);
447 VAImageFormat *expected_format;
449 VASurfaceID test_surface_id;
471 int need_pixel_format = 1;
473 if (ctx->
attributes[i].type == VASurfaceAttribMemoryType)
474 need_memory_type = 0;
475 if (ctx->
attributes[i].type == VASurfaceAttribPixelFormat)
476 need_pixel_format = 0;
490 if (need_memory_type) {
492 .type = VASurfaceAttribMemoryType,
493 .flags = VA_SURFACE_ATTRIB_SETTABLE,
494 .value.type = VAGenericValueTypeInteger,
495 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA,
498 if (need_pixel_format) {
500 .type = VASurfaceAttribPixelFormat,
501 .flags = VA_SURFACE_ATTRIB_SETTABLE,
502 .value.type = VAGenericValueTypeInteger,
548 "user-configured buffer pool.\n");
556 "internal buffer pool.\n");
561 test_surface_id = (VASurfaceID)(uintptr_t)test_surface->
data;
568 vas = vaDeriveImage(hwctx->
display, test_surface_id, &test_image);
569 if (vas == VA_STATUS_SUCCESS) {
570 if (expected_format->fourcc == test_image.format.fourcc) {
575 "derived image format %08x does not match "
576 "expected format %08x.\n",
577 expected_format->fourcc, test_image.format.fourcc);
579 vaDestroyImage(hwctx->
display, test_image.image_id);
582 "deriving image does not work: "
583 "%d (%s).\n", vas, vaErrorStr(vas));
587 "image format is not supported.\n");
637 pix_fmts[0] = preferred_format;
657 VASurfaceID surface_id;
660 surface_id = (VASurfaceID)(uintptr_t)hwmap->
source->
data[3];
664 if (vas != VA_STATUS_SUCCESS) {
666 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
671 vas = vaPutImage(hwctx->
display, surface_id, map->
image.image_id,
674 if (vas != VA_STATUS_SUCCESS) {
676 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
680 vas = vaDestroyImage(hwctx->
display, map->
image.image_id);
681 if (vas != VA_STATUS_SUCCESS) {
683 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
694 VASurfaceID surface_id;
695 VAImageFormat *image_format;
698 void *address =
NULL;
701 surface_id = (VASurfaceID)(uintptr_t)src->
data[3];
710 if (dst->
format != hwfc->
sw_format && (flags & AV_HWFRAME_MAP_DIRECT)) {
725 map->
image.image_id = VA_INVALID_ID;
727 vas = vaSyncSurface(hwctx->
display, surface_id);
728 if (vas != VA_STATUS_SUCCESS) {
730 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
744 vas = vaDeriveImage(hwctx->
display, surface_id, &map->
image);
745 if (vas != VA_STATUS_SUCCESS) {
747 "surface %#x: %d (%s).\n",
748 surface_id, vas, vaErrorStr(vas));
752 if (map->
image.format.fourcc != image_format->fourcc) {
754 "is in wrong format: expected %#08x, got %#08x.\n",
755 surface_id, image_format->fourcc, map->
image.format.fourcc);
761 vas = vaCreateImage(hwctx->
display, image_format,
763 if (vas != VA_STATUS_SUCCESS) {
765 "surface %#x: %d (%s).\n",
766 surface_id, vas, vaErrorStr(vas));
771 vas = vaGetImage(hwctx->
display, surface_id, 0, 0,
773 if (vas != VA_STATUS_SUCCESS) {
775 "surface %#x: %d (%s).\n",
776 surface_id, vas, vaErrorStr(vas));
783 vas = vaMapBuffer(hwctx->
display, map->
image.buf, &address);
784 if (vas != VA_STATUS_SUCCESS) {
786 "%#x: %d (%s).\n", surface_id, vas, vaErrorStr(vas));
799 for (i = 0; i < map->
image.num_planes; i++) {
804 #ifdef VA_FOURCC_YV16
805 map->
image.format.fourcc == VA_FOURCC_YV16 ||
807 map->
image.format.fourcc == VA_FOURCC_YV12) {
818 if (map->
image.image_id != VA_INVALID_ID)
911 #define DRM_MAP(va, layers, ...) { \
916 static const struct {
918 int nb_layer_formats;
920 } vaapi_drm_format_map[] = {
922 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88),
924 DRM_MAP(NV12, 1, DRM_FORMAT_NV12),
925 #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16)
926 DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
928 DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888),
929 DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888),
930 DRM_MAP(
RGBA, 1, DRM_FORMAT_ABGR8888),
931 DRM_MAP(RGBX, 1, DRM_FORMAT_XBGR8888),
932 #ifdef VA_FOURCC_ABGR
933 DRM_MAP(ABGR, 1, DRM_FORMAT_RGBA8888),
934 DRM_MAP(XBGR, 1, DRM_FORMAT_RGBX8888),
936 DRM_MAP(ARGB, 1, DRM_FORMAT_BGRA8888),
937 DRM_MAP(XRGB, 1, DRM_FORMAT_BGRX8888),
946 VASurfaceID surface_id = (VASurfaceID)(uintptr_t)hwmap->
priv;
950 vaDestroySurfaces(dst_dev->
display, &surface_id, 1);
960 VASurfaceID surface_id;
962 uint32_t va_fourcc, va_rt_format;
965 unsigned long buffer_handle;
966 VASurfaceAttribExternalBuffers buffer_desc;
967 VASurfaceAttrib attrs[2] = {
969 .type = VASurfaceAttribMemoryType,
970 .flags = VA_SURFACE_ATTRIB_SETTABLE,
971 .value.type = VAGenericValueTypeInteger,
972 .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
975 .type = VASurfaceAttribExternalBufferDescriptor,
976 .flags = VA_SURFACE_ATTRIB_SETTABLE,
977 .value.type = VAGenericValueTypePointer,
978 .value.value.p = &buffer_desc,
984 if (
desc->nb_objects != 1) {
986 "made from a single DRM object.\n");
992 if (
desc->nb_layers != vaapi_drm_format_map[i].nb_layer_formats)
994 for (j = 0; j <
desc->nb_layers; j++) {
995 if (
desc->layers[j].format !=
996 vaapi_drm_format_map[i].layer_formats[j])
999 if (j !=
desc->nb_layers)
1001 va_fourcc = vaapi_drm_format_map[i].va_fourcc;
1011 "%08x.\n",
desc->objects[0].fd, va_fourcc);
1018 buffer_handle =
desc->objects[0].fd;
1019 buffer_desc.pixel_format = va_fourcc;
1020 buffer_desc.width = src_fc->width;
1021 buffer_desc.height = src_fc->height;
1022 buffer_desc.data_size =
desc->objects[0].size;
1023 buffer_desc.buffers = &buffer_handle;
1024 buffer_desc.num_buffers = 1;
1025 buffer_desc.flags = 0;
1028 for (i = 0; i <
desc->nb_layers; i++) {
1029 for (j = 0; j <
desc->layers[i].nb_planes; j++) {
1030 buffer_desc.pitches[k] =
desc->layers[i].planes[j].pitch;
1031 buffer_desc.offsets[k] =
desc->layers[i].planes[j].offset;
1035 buffer_desc.num_planes = k;
1037 vas = vaCreateSurfaces(dst_dev->display, va_rt_format,
1041 if (vas != VA_STATUS_SUCCESS) {
1043 "object: %d (%s).\n", vas, vaErrorStr(vas));
1049 &vaapi_unmap_from_drm,
1050 (
void*)(uintptr_t)surface_id);
1054 dst->width =
src->width;
1055 dst->height =
src->height;
1056 dst->data[3] = (
uint8_t*)(uintptr_t)surface_id;
1059 "surface %#x.\n",
desc->objects[0].fd, surface_id);
1093 return vaapi_map_from_drm(hwfc, dst, src, flags);
1106 return vaapi_map_to_drm(hwfc, dst, src, flags);
1122 if (priv->x11_display)
1123 XCloseDisplay(priv->x11_display);
1133 static void vaapi_device_log_error(
void *context,
const char *
message)
1140 static void vaapi_device_log_info(
void *context,
const char *
message)
1156 vaSetErrorCallback(display, &vaapi_device_log_error, ctx);
1157 vaSetInfoCallback (display, &vaapi_device_log_info, ctx);
1162 vas = vaInitialize(display, &major, &minor);
1163 if (vas != VA_STATUS_SUCCESS) {
1165 "connection: %d (%s).\n", vas, vaErrorStr(vas));
1169 "version %d.%d\n", major, minor);
1178 VADisplay display =
NULL;
1190 if (!display && !(device && device[0] ==
'/')) {
1192 priv->x11_display = XOpenDisplay(device);
1193 if (!priv->x11_display) {
1195 "%s.\n", XDisplayName(device));
1197 display = vaGetDisplay(priv->x11_display);
1200 "from X11 display %s.\n", XDisplayName(device));
1205 "X11 display %s.\n", XDisplayName(device));
1215 const char *path = device ? device :
"/dev/dri/renderD128";
1216 priv->
drm_fd = open(path, O_RDWR);
1221 display = vaGetDisplayDRM(priv->
drm_fd);
1224 "from DRM device %s.\n", path);
1229 "DRM device %s.\n", path);
1236 "device: %s.\n", device ? device :
"");
1252 if (src_hwctx->
fd < 0) {
1254 "device to derive a VA display from.\n");
1268 display = vaGetDisplayDRM(src_hwctx->
fd);
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
VAAPI-specific data associated with a frame pool.
static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc)
This structure describes decoded (raw) audio or video data.
The driver does not destroy parameter buffers when they are used by vaRenderPicture().
ptrdiff_t const GLvoid * data
static void vaapi_device_free(AVHWDeviceContext *ctx)
static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pixelformat)
Memory handling functions.
VASurfaceAttrib * attributes
Set by the user to apply surface attributes to all surfaces in the frame pool.
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
static FFServerConfig config
int width
The allocated dimensions of the frames in this pool.
static int vaapi_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
int max_width
The maximum size of frames in this hw_frames_ctx.
int nb_objects
Number of DRM objects making up this frame.
API-specific header for AV_HWDEVICE_TYPE_VAAPI.
The mapping must be readable.
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
static int vaapi_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static int vaapi_device_init(AVHWDeviceContext *hwdev)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
AVBufferPool * pool_internal
The driver does not support the VASurfaceAttribMemoryType attribute, so the surface allocation code w...
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
static void vaapi_buffer_free(void *opaque, uint8_t *data)
static int vaapi_device_connect(AVHWDeviceContext *ctx, VADisplay display)
static void vaapi_frames_uninit(AVHWFramesContext *hwfc)
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
The maximum number of layers/planes in a DRM frame.
static int vaapi_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *src_ctx, int flags)
static int vaapi_map_frame(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
int fd
DRM PRIME fd for the object.
The quirks field has been set by the user and should not be detected automatically by av_hwdevice_ctx...
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
The mapping must be direct.
VAAPI hardware pipeline configuration details.
void(* free)(struct AVHWDeviceContext *ctx)
This field may be set by the caller before calling av_hwdevice_ctx_init().
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
simple assert() macros that are a bit more flexible than ISO C assert().
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.
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
VASurfaceAttrib * attributes
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
const char * match_string
int initial_pool_size
Initial size of the frame pool.
static int vaapi_map_to_memory(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
AVFrame * source
A reference to the original source of the mapping.
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
enum AVPixelFormat pix_fmt
static int vaapi_transfer_get_formats(AVHWFramesContext *hwfc, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
AVDRMObjectDescriptor objects[AV_DRM_MAX_PLANES]
Array of objects making up the frame.
static int vaapi_map_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
AVBufferPool * av_buffer_pool_init2(int size, void *opaque, AVBufferRef *(*alloc)(void *opaque, int size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
static int vaapi_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src)
static void vaapi_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap)
#define FF_ARRAY_ELEMS(a)
VADisplay display
The VADisplay handle, to be filled by the user.
VAAPISurfaceFormat * formats
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
int min_width
The minimum size of frames in this hw_frames_ctx.
void * priv
Hardware-specific private data associated with the mapping.
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
static const struct @247 vaapi_format_map[]
const char * friendly_name
uint8_t * data
The data buffer.
static int vaapi_map_from(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags)
static int vaapi_frames_init(AVHWFramesContext *hwfc)
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
unsigned int driver_quirks
Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), with reference to a table of known...
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
DRM-managed buffers exposed through PRIME buffer sharing.
This struct describes a set or pool of "hardware" frames (i.e.
refcounted data buffer API
enum AVPixelFormat * valid_hw_formats
A list of possible values for format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
const VDPAUPixFmtMap * map
static int vaapi_get_image_format(AVHWDeviceContext *hwdev, enum AVPixelFormat pix_fmt, VAImageFormat **image_format)
API-specific header for AV_HWDEVICE_TYPE_DRM.
AVHWFramesInternal * internal
Private data used internally by libavutil.
static enum AVPixelFormat pix_fmts[]
static void vaapi_device_uninit(AVHWDeviceContext *hwdev)
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
void * user_opaque
Arbitrary user data, to be used e.g.
static int vaapi_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
A reference to a data buffer.
common internal and external API header
static int ref[MAX_W *MAX_W]
int fd
File descriptor of DRM device.
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
static int vaapi_frames_get_constraints(AVHWDeviceContext *hwdev, const void *hwconfig, AVHWFramesConstraints *constraints)
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
AVHWFrameTransferDirection
static AVBufferRef * vaapi_pool_alloc(void *opaque, int size)
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
The mapping must be writeable.
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
VAAPI connection details.
VAConfigID config_id
ID of a VAAPI pipeline configuration.
const HWContextType ff_hwcontext_type_vaapi
VASurfaceID * surface_ids
The surfaces IDs of all surfaces in the pool after creation.
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
#define av_malloc_array(a, b)
#define FFSWAP(type, a, b)
AVHWDeviceInternal * internal
Private data used internally by libavutil.
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.
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
AVPixelFormat
Pixel format.
The driver does not support surface attributes at all.
static const struct @248 vaapi_driver_quirks_table[]
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.