From 78b8436a9c4bffd0b79157af30bece76b5de523c Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Sat, 9 Mar 2019 19:05:21 +0100 Subject: [PATCH 1/5] introduce new structures to reference with descriptive names - const struct codec (.name, .type) - refer 'codec_type' enum values to their lexical names - define a V4L2 buffer type structure (.name, .type) - refer 'v4l2_buf_type' enum values to their lexical names Signed-off-by: Ralf Zerres --- src/v4l2.c | 115 ++++++++++++++++++++++++++++++++++++++++++++--------- src/v4l2.h | 17 ++++++++ 2 files changed, 113 insertions(+), 19 deletions(-) diff --git a/src/v4l2.c b/src/v4l2.c index d5000ac..1de6ecd 100644 --- a/src/v4l2.c +++ b/src/v4l2.c @@ -32,6 +32,76 @@ #include "utils.h" #include "v4l2.h" +const struct codec codec[] = { + { + .name = "MPEG-2", + .type = CODEC_TYPE_MPEG2, + }, + { + .name = "H.264", + .type = CODEC_TYPE_H264, + }, + { + .name = "H.265", + .type = CODEC_TYPE_H265, + }, +}; + +const struct buffer_type buffer_type[] = { + { + .name = "Video Capture Buffer", + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE + }, + { + .name = "Video Output Buffer", + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT + }, + { + .name = "Video Overlay Buffer", + .type = V4L2_BUF_TYPE_VIDEO_OVERLAY + }, + { + .name = "VBI Capture Buffer", + .type = V4L2_BUF_TYPE_VBI_CAPTURE + }, + { + .name = "VBI Output Buffer", + .type = V4L2_BUF_TYPE_VBI_OUTPUT + }, + { + .name = "Sliced VBI Capture Buffer", + .type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE + }, + { + .name = "Sliced VBI Output Buffer", + .type = V4L2_BUF_TYPE_SLICED_VBI_OUTPUT + }, + { + .name = "Video Output Overlay Buffer", + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY + }, + { + .name = "Video Multi-Plane Capture Buffer", + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE + }, + { + .name = "Video Multi-Plane Output Buffer", + .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE + }, + { + .name = "SDR Capture Buffer", + .type = V4L2_BUF_TYPE_SDR_CAPTURE + }, + { + .name = "SDR Output Buffer", + .type = V4L2_BUF_TYPE_SDR_OUTPUT + }, + { + .name = "Meta Capture Buffer", + .type = V4L2_BUF_TYPE_META_CAPTURE + } +}; + static bool v4l2_type_is_output(unsigned int type) { switch (type) { @@ -146,8 +216,8 @@ int v4l2_try_format(int video_fd, unsigned int type, unsigned int width, rc = ioctl(video_fd, VIDIOC_TRY_FMT, &format); if (rc < 0) { - request_log("Unable to try format for type %d: %s\n", type, - strerror(errno)); + request_log("Unable to try format for %s (type %d): %s (%d)\n", + buffer_type[type].name, type, strerror(errno), errno); return -1; } @@ -164,8 +234,8 @@ int v4l2_set_format(int video_fd, unsigned int type, unsigned int pixelformat, rc = ioctl(video_fd, VIDIOC_S_FMT, &format); if (rc < 0) { - request_log("Unable to set format for type %d: %s\n", type, - strerror(errno)); + request_log("Unable to set format for %s (type %d): %s (%d)\n", + buffer_type[type].name, type, strerror(errno), errno); return -1; } @@ -186,8 +256,8 @@ int v4l2_get_format(int video_fd, unsigned int type, unsigned int *width, rc = ioctl(video_fd, VIDIOC_G_FMT, &format); if (rc < 0) { - request_log("Unable to get format for type %d: %s\n", type, - strerror(errno)); + request_log("Unable to get format for %s (type %d): %s (%d)\n", + buffer_type[type].name, type, strerror(errno), errno); return -1; } @@ -248,15 +318,15 @@ int v4l2_create_buffers(int video_fd, unsigned int type, rc = ioctl(video_fd, VIDIOC_G_FMT, &buffers.format); if (rc < 0) { - request_log("Unable to get format for type %d: %s\n", type, - strerror(errno)); + request_log("Unable to get format for %s (type %d): %s (%d)\n", + buffer_type[type].name, type, strerror(errno), errno); return -1; } rc = ioctl(video_fd, VIDIOC_CREATE_BUFS, &buffers); if (rc < 0) { - request_log("Unable to create buffer for type %d: %s\n", type, - strerror(errno)); + request_log("Unable to create %s (type %d): %s (%d)\n", + buffer_type[type].name, type, strerror(errno), errno); return -1; } @@ -286,7 +356,8 @@ int v4l2_query_buffer(int video_fd, unsigned int type, unsigned int index, rc = ioctl(video_fd, VIDIOC_QUERYBUF, &buffer); if (rc < 0) { - request_log("Unable to query buffer: %s\n", strerror(errno)); + request_log("Unable to query %s (type %d): %s (%d)\n", + buffer_type[type].name, type, strerror(errno), errno); return -1; } @@ -322,7 +393,8 @@ int v4l2_request_buffers(int video_fd, unsigned int type, rc = ioctl(video_fd, VIDIOC_REQBUFS, &buffers); if (rc < 0) { - request_log("Unable to request buffers: %s\n", strerror(errno)); + request_log("Unable to request %s (type %d): %s (%d)\n", + buffer_type[type].name, type, strerror(errno), errno); return -1; } @@ -363,7 +435,8 @@ int v4l2_queue_buffer(int video_fd, int request_fd, unsigned int type, rc = ioctl(video_fd, VIDIOC_QBUF, &buffer); if (rc < 0) { - request_log("Unable to queue buffer: %s\n", strerror(errno)); + request_log("Unable to queue %s (type %d): %s (%d)\n", + buffer_type[type].name, type, strerror(errno), errno); return -1; } @@ -393,7 +466,8 @@ int v4l2_dequeue_buffer(int video_fd, int request_fd, unsigned int type, rc = ioctl(video_fd, VIDIOC_DQBUF, &buffer); if (rc < 0) { - request_log("Unable to dequeue buffer: %s\n", strerror(errno)); + request_log("Unable to dequeue %s (type %d): %s (%d)\n", + buffer_type[type].name, type, strerror(errno), errno); return -1; } @@ -417,8 +491,8 @@ int v4l2_export_buffer(int video_fd, unsigned int type, unsigned int index, rc = ioctl(video_fd, VIDIOC_EXPBUF, &exportbuffer); if (rc < 0) { - request_log("Unable to export buffer: %s\n", - strerror(errno)); + request_log("Unable to export %s (type %d): %s (%d)\n", + buffer_type[type].name, type, strerror(errno), errno); return -1; } @@ -452,7 +526,8 @@ int v4l2_set_control(int video_fd, int request_fd, unsigned int id, void *data, rc = ioctl(video_fd, VIDIOC_S_EXT_CTRLS, &controls); if (rc < 0) { - request_log("Unable to set control: %s\n", strerror(errno)); + request_log("Unable to set control: %s (%d)\n", + strerror(errno), errno); return -1; } @@ -467,8 +542,10 @@ int v4l2_set_stream(int video_fd, unsigned int type, bool enable) rc = ioctl(video_fd, enable ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &buf_type); if (rc < 0) { - request_log("Unable to %sable stream: %s\n", - enable ? "en" : "dis", strerror(errno)); + request_log("Unable to %sable stream %s (type %d): %s (%d)\n", + enable ? "en" : "dis", + buffer_type[type].name, type, + strerror(errno)); return -1; } diff --git a/src/v4l2.h b/src/v4l2.h index 73e9a42..a96ce19 100644 --- a/src/v4l2.h +++ b/src/v4l2.h @@ -26,9 +26,26 @@ #define _V4L2_H_ #include +#include #define SOURCE_SIZE_MAX (1024 * 1024) +enum codec_type { + CODEC_TYPE_MPEG2, + CODEC_TYPE_H264, + CODEC_TYPE_H265, +}; + +extern const struct codec { + char *name; + enum codec_type type; +} codec[]; + +extern const struct buffer_type { + char *name; + enum v4l2_buf_type type; +} buffer_type[]; + unsigned int v4l2_type_video_output(bool mplane); unsigned int v4l2_type_video_capture(bool mplane); int v4l2_query_capabilities(int video_fd, unsigned int *capabilities); From e0f0630abafc4e6ce778d4ec576a19675dc46d78 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Mon, 15 Apr 2019 01:17:52 +0200 Subject: [PATCH 2/5] buildsystem autotools: update dependencies - include libudev checks - include ACLOCAL_AMFLAGS (-I m4) - include AC_CONFIG_MACRO_DIRS([m4]) Signed-off-by: Ralf Zerres --- Makefile.am | 1 + configure.ac | 4 +++- src/Makefile.am | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index b66db66..e84264b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,6 +21,7 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SUBDIRS = src +ACLOCAL_AMFLAGS = -I m4 MAINTAINERCLEANFILES = aclocal.m4 \ compile \ diff --git a/configure.ac b/configure.ac index c5d9e4b..47fddc4 100644 --- a/configure.ac +++ b/configure.ac @@ -25,6 +25,7 @@ AC_INIT([libva-v4l2-request], [1.0.0], [paul.kocialkowski@bootlin.com]) AM_INIT_AUTOMAKE([dist-bzip2 subdir-objects foreign]) AC_CONFIG_SRCDIR([src/request.c]) +AC_CONFIG_MACRO_DIRS([m4]) AC_ENABLE_SHARED AC_DISABLE_STATIC AC_LANG_C @@ -35,6 +36,7 @@ AM_PROG_AS PKG_CHECK_MODULES([LIBVA], [libva >= 1.1.0]) PKG_CHECK_MODULES([DRM], [libdrm >= 2.4.52]) +PKG_CHECK_MODULES([UDEV], [libudev >= 217]) #LIBS="$LIBS $DRM_LIBS" #CFLAGS="$CFLAGS $DRM_CFLAGS $LIBVA_CFLAGS" @@ -49,5 +51,5 @@ AC_DEFINE_UNQUOTED([VA_DRIVER_INIT_FUNC], [$VA_DRIVER_INIT_FUNC], AC_CONFIG_HEADERS([src/autoconfig.h]) AC_CONFIG_FILES([Makefile src/Makefile]) - +AC_CONFIG_MACRO_DIRS([m4]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index 6448884..489ade2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -57,10 +57,10 @@ v4l2_request_drv_video_la_SOURCES = request.c \ h265.c \ h265.h -v4l2_request_drv_video_la_CFLAGS = -I../include $(DRM_CFLAGS) $(LIBVA_CFLAGS) +v4l2_request_drv_video_la_CFLAGS = -I../include $(DRM_CFLAGS) $(LIBVA_CFLAGS) $(UDEV_LIBS) v4l2_request_drv_video_la_LDFLAGS = -module -avoid-version -no-undefined \ -Wl,--no-undefined -v4l2_request_drv_video_la_LIBADD = $(DRM_LIBS) $(LIBVA_LIBS) +v4l2_request_drv_video_la_LIBADD = $(DRM_LIBS) $(LIBVA_LIBS) $(UDEV_LIBS) v4l2_request_drv_video_la_LTLIBRARIES = v4l2_request_drv_video.la v4l2_request_drv_video_ladir = /usr/lib/dri/ From 01ad1d4e05ee951b4519508c40ea6eba8d0ca557 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Mon, 15 Apr 2019 01:19:02 +0200 Subject: [PATCH 3/5] buildsystem meson: update dependencies, library handling - include library checks: libva, libdrm, libudev - set default_library -> shared - introduce shared library version - update configure_file to use mesonconfig.h.in this will create an autoconfig.h that only defines preprocessor definitions we need when using meson Signed-off-by: Ralf Zerres --- meson.build | 18 ++++++++++++++++-- src/config.h | 4 ++++ src/meson.build | 10 ++++++++-- src/mesonconfig.h.in | 4 ++++ src/request.c | 37 +++++++++++++++++++++++++++++++++---- 5 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 src/mesonconfig.h.in diff --git a/meson.build b/meson.build index e5163bc..000508c 100644 --- a/meson.build +++ b/meson.build @@ -22,12 +22,26 @@ project('libva-v4l2-request', 'c', version: '1.0.0', + default_library : 'shared', meson_version: '>= 0.43.0') +add_project_arguments('-DMESON_BUILD', language : 'c') + cc = meson.get_compiler('c') -libva_dep = dependency('libva', version : '>= 1.1.0') -libdrm_dep = dependency('libdrm', version : '>= 2.4.52') +libva_dep = dependency('libva', + method: 'pkg-config', + version: '>= 1.1.0', + required: true) + +libdrm_dep = dependency('libdrm', + method: 'pkg-config', + version : '>= 2.4.52', + required: true) + +libudev_dep = dependency('libudev', + method: 'pkg-config', + required: true) va_api_version_array = libva_dep.version().split('.') va_api_major_version = va_api_version_array[0] diff --git a/src/config.h b/src/config.h index b7b12e7..9a940da 100644 --- a/src/config.h +++ b/src/config.h @@ -32,6 +32,10 @@ #include "object_heap.h" #include "request.h" +#ifdef MESON_BUILD +#define __vaDriverInit "@version@" +#endif + #define CONFIG(data, id) \ ((struct object_config *)object_heap_lookup(&(data)->config_heap, id)) #define CONFIG_ID_OFFSET 0x01000000 diff --git a/src/meson.build b/src/meson.build index af117d3..4a6c1ff 100644 --- a/src/meson.build +++ b/src/meson.build @@ -24,6 +24,7 @@ autoconf_data = configuration_data() autoconf_data.set('VA_DRIVER_INIT_FUNC', va_driver_init_func) autoconf = configure_file( + input: 'mesonconfig.h.in', output: 'autoconfig.h', configuration: autoconf_data) @@ -78,13 +79,18 @@ cflags = [ deps = [ libva_dep, - libdrm_dep + libdrm_dep, + libudev_dep ] -v4l2_request_drv_video = shared_module('v4l2_request_drv_video', +libtype = get_option('default_library') + +#v4l2_request_drv_video = shared_module('v4l2_request_drv_video', +v4l2_request_drv_video = library('v4l2_request_drv_video', name_prefix: '', install: true, install_dir: '/usr/lib/dri/', + soversion: '1.0.0', c_args: cflags, sources: [ sources, headers, autoconf ], include_directories: includes, diff --git a/src/mesonconfig.h.in b/src/mesonconfig.h.in new file mode 100644 index 0000000..99f92ed --- /dev/null +++ b/src/mesonconfig.h.in @@ -0,0 +1,4 @@ +/* meson configure_file */ + +/* Driver init function */ +#mesondefine VA_DRIVER_INIT_FUNC diff --git a/src/request.c b/src/request.c index b54c0f5..2bfa8d4 100644 --- a/src/request.c +++ b/src/request.c @@ -60,15 +60,18 @@ VA_DRIVER_INIT_FUNC(VADriverContextP context); VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP context) { struct request_data *driver_data; + struct driver *driver = NULL; + struct decoder *decoder = NULL; struct VADriverVTable *vtable = context->vtable; VAStatus status; - unsigned int capabilities; - unsigned int capabilities_required; + __u32 capabilities; + __u32 capabilities_required; int video_fd = -1; int media_fd = -1; char *video_path; char *media_path; int rc; + int id = 0; context->version_major = VA_MAJOR_VERSION; context->version_minor = VA_MINOR_VERSION; @@ -146,6 +149,34 @@ VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP context) object_heap_init(&driver_data->image_heap, sizeof(struct object_image), IMAGE_ID_OFFSET); + /* initilize structures and pointer */ + driver_init(driver); + decoder = driver->decoder[0]; + + /* environment settings */ + decoder->media_path = getenv("LIBVA_V4L2_REQUEST_MEDIA_PATH"); + + if (decoder->media_path == NULL) { + subsystem = "media"; + request_log("Scanning for suitable v4l2 driver (subsystem: %s)...\n", + subsystem); + rc = udev_scan_subsystem(driver, subsystem); + } + else { + request_log("Scanning v4l2 topology (media_path: %s)...\n", + decoder->media_path); + rc = media_scan_topology(driver, id); + } + + if (rc < 0) { + request_log("No suitable v4l2 decoder found\n"); + status = VA_STATUS_ERROR_INVALID_CONFIG; + goto error; + } + + driver_print(driver); + + /* video_path = getenv("LIBVA_V4L2_REQUEST_VIDEO_PATH"); if (video_path == NULL) video_path = "/dev/video0"; @@ -183,8 +214,6 @@ VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP context) goto complete; error: - status = VA_STATUS_ERROR_OPERATION_FAILED; - if (video_fd >= 0) close(video_fd); From 21cd2f33e06fe4bd89d91243dae0dde0fc7b0c9d Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Mon, 15 Apr 2019 01:24:37 +0200 Subject: [PATCH 4/5] introduce autoprobing for decoder driver Without the patch, the user needs to provide working environment variables that define the video_path and media_path (via: LIBVA-V4L2_REQUEST_MEDIA_PATH and LIBVA_V4L2_REQUEST_VIDEO_PATH). This patch will introduce needed infrastructure to autoscan suitable devices. - introduce libudev support: scan the class 'media' for available v4l2 devices - introduce media topology scan: parse entities and interfaces that do provide video-decoding functionality (MEDIA_IOC_G_TOPOLOGY) - introduce decoder 'vector': store v4l2 entities that offer needed decoder capabilities - probe streaming capability for given decoder entity - if multiple capable drivers are present (offering decoding and streaming), use the first one - respect precedence of given environment variables (with validity check) Signed-off-by: Ralf Zerres --- meson.build | 2 +- src/media.c | 294 ++++++++++++++++++++++++++++++++++++++++++ src/media.h | 5 + src/picture.c | 2 + src/request.c | 128 ++++++++++++------- src/request.h | 14 +- src/utils.c | 348 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils.h | 51 ++++++++ 8 files changed, 793 insertions(+), 51 deletions(-) diff --git a/meson.build b/meson.build index 000508c..dfd8fb9 100644 --- a/meson.build +++ b/meson.build @@ -32,7 +32,7 @@ cc = meson.get_compiler('c') libva_dep = dependency('libva', method: 'pkg-config', version: '>= 1.1.0', - required: true) + required: true) libdrm_dep = dependency('libdrm', method: 'pkg-config', diff --git a/src/media.c b/src/media.c index e3a1bcc..debecaa 100644 --- a/src/media.c +++ b/src/media.c @@ -22,16 +22,305 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#define _GNU_SOURCE #include +#include +#include +#include #include #include #include #include +#include +#include #include +#include #include "media.h" #include "utils.h" +#include "v4l2.h" + +enum media_gobj_type { + MEDIA_GRAPH_ENTITY, + MEDIA_GRAPH_PAD, + MEDIA_GRAPH_LINK, + MEDIA_GRAPH_INTF_DEVNODE, +}; + +static inline void *media_get_uptr(__u64 arg) +{ + return (void *)(uintptr_t)arg; +} + +static inline const char *media_interface_type(uint32_t intf_type) +{ + switch (intf_type) { + case MEDIA_INTF_T_DVB_FE: + return "frontend"; + case MEDIA_INTF_T_DVB_DEMUX: + return "demux"; + case MEDIA_INTF_T_DVB_DVR: + return "DVR"; + case MEDIA_INTF_T_DVB_CA: + return "CA"; + case MEDIA_INTF_T_DVB_NET: + return "dvbnet"; + + case MEDIA_INTF_T_V4L_VIDEO: + return "video"; + case MEDIA_INTF_T_V4L_VBI: + return "vbi"; + case MEDIA_INTF_T_V4L_RADIO: + return "radio"; + case MEDIA_INTF_T_V4L_SUBDEV: + return "v4l2-subdev"; + case MEDIA_INTF_T_V4L_SWRADIO: + return "swradio"; + + case MEDIA_INTF_T_ALSA_PCM_CAPTURE: + return "pcm-capture"; + case MEDIA_INTF_T_ALSA_PCM_PLAYBACK: + return "pcm-playback"; + case MEDIA_INTF_T_ALSA_CONTROL: + return "alsa-control"; + case MEDIA_INTF_T_ALSA_COMPRESS: + return "compress"; + case MEDIA_INTF_T_ALSA_RAWMIDI: + return "rawmidi"; + case MEDIA_INTF_T_ALSA_HWDEP: + return "hwdep"; + case MEDIA_INTF_T_ALSA_SEQUENCER: + return "sequencer"; + case MEDIA_INTF_T_ALSA_TIMER: + return "ALSA timer"; + default: + return "unknown_intf"; + } +} + +/* +static inline uint32_t media_localid(uint32_t id) +{ + return id & 0xffffff; +} +*/ + +int media_scan_topology(struct driver *driver, int id, const char *path) +{ + /* https://www.kernel.org/doc/html/v5.0/media/uapi/mediactl/media-ioc-g-topology.html */ + struct media_v2_topology *topology = NULL; + struct media_device_info *device = NULL; + struct decoder *decoder = NULL; + int media_fd = -1; + int video_fd = -1; + int i = 0; + int j = 0; + int rc = -1; + bool is_decoder = false; + __u64 topology_version; + unsigned int capabilities; + unsigned int capabilities_required; + + + decoder = driver->decoder[id]; + request_log("Scan topology for media-device %s ...\n", + path); + + media_fd = open(path, O_RDWR | O_NONBLOCK, 0); + if (media_fd < 0) { + request_log("Unable to open media node: %s (%d)\n", + strerror(errno), errno); + return rc; + } + + device = calloc(1, sizeof(struct media_device_info)); + rc = ioctl(media_fd, MEDIA_IOC_DEVICE_INFO, device); + if (rc < 0) { + request_log(" error: media device info can't be initialized!\n"); + return rc; + } + + request_log(" driver: %s (model: %s, bus: %s, api-version: %d, driver-version: %d)\n", + device->driver, + device->model, + device->bus_info, + device->media_version, + device->driver_version); + + /* + * Initialize topology structure + * a) zero the topology structure + * b) ioctl to get amount of elements + */ + topology = calloc(1, sizeof(struct media_v2_topology)); + + rc = ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, topology); + if (rc < 0) { + request_log(" error: topology can't be initialized!\n"); + return rc; + } + + topology_version = topology->topology_version; + request_log(" topology: version %lld (entries: %d, interfaces: %d, pads: %d, links: %d\n", + topology->topology_version, + topology->num_entities, + topology->num_interfaces, + topology->num_pads, + topology->num_links); + + /* + * Update topology structures + * a) set pointers to media structures we are interested in (mem-allocation) + * b) ioctl to update structure element values + */ + do { + if(topology->num_entities > 0) + topology->ptr_entities = (__u64)calloc(topology->num_entities, + sizeof(struct media_v2_entity)); + if (topology->num_entities && !topology->ptr_entities) + goto error; + + if(topology->num_interfaces > 0) + topology->ptr_interfaces = (__u64)calloc(topology->num_interfaces, + sizeof(struct media_v2_interface)); + if (topology->num_interfaces && !topology->ptr_interfaces) + goto error; + + /* not interested in other structures */ + topology->ptr_pads = 0; + topology->ptr_links = 0; + + /* 2nd call: get updated topology structure elements */ + rc = ioctl(media_fd, MEDIA_IOC_G_TOPOLOGY, topology); + if (rc < 0) { + if (topology->topology_version != topology_version) { + request_log(" Topology changed from version %lld to %lld. Trying again.\n", + topology_version, + topology->topology_version); + free((void *)topology->ptr_entities); + free((void *)topology->ptr_interfaces); + topology_version = topology->topology_version; + continue; + } + request_log(" Topology %lld update error!\n", + topology_version); + goto error; + } + } while (rc < 0); + + /* + * Pick up all available video decoder entities, that support + * function 'MEDIA_ENT_F_PROC_VIDEO_DECODER': + * -> decompresing a compressd video stream into uncompressed video frames + * -> has one sink + * -> at least one source + */ + struct media_v2_entity *entities = media_get_uptr(topology->ptr_entities); + for(i=0; i < topology->num_entities; i++) { + struct media_v2_entity *entity = &entities[i]; + if (entity->function == MEDIA_ENT_F_PROC_VIDEO_DECODER) { + is_decoder = true; + decoder->id = entity->id; + asprintf(&decoder->name, "%s", entity->name); + request_log(" entity: %s\n", entity->name); + } + } + + /* + * Pick interface + * -> type: 'MEDIA_INTF_T_V4L_VIDEO' + * -> device: typically /dev/video? + */ + if (is_decoder) { + struct media_v2_interface *interfaces = media_get_uptr(topology->ptr_interfaces); + for (j=0; j < topology->num_interfaces; j++) { + struct media_v2_interface *interface = &interfaces[j]; + struct media_v2_intf_devnode *devnode = &interface->devnode; + char *video_path; + + if (interface->intf_type == MEDIA_INTF_T_V4L_VIDEO) { + /* TODO: cedurs proc doesn't assing devnode->minor + * Testing: hardcode to /dev/video5 (81, 10) + */ + if (devnode->minor == -1) + devnode->minor = 10; + /* + request_log(" devnode: major->%d, minor->%d\n", + devnode->major, + devnode->minor); + */ + + + video_path = udev_get_devpath(devnode); + asprintf(&decoder->video_path, "%s", video_path); + + request_log(" interface: type %s, device %s\n", + media_interface_type(interface->intf_type), + video_path); + + /* check capabilities */ + video_fd = open(decoder->video_path, O_RDWR | O_NONBLOCK); + if (video_fd < 0) + goto error; + + rc = v4l2_query_capabilities(video_fd, &capabilities); + if (rc < 0) { + goto error; + } + + capabilities_required = V4L2_CAP_STREAMING; + + if ((capabilities & capabilities_required) != capabilities_required) { + request_log("Missing required driver capabilities\n"); + goto error; + } + else { + decoder->capabilities = capabilities; + request_log(" capabilities: mask %ld\n", + decoder->capabilities); + } + } + } + rc = 1; + } + + goto complete; + +error: + rc = -1; + +complete: + if (topology->ptr_entities) { + free((void *)topology->ptr_entities); + topology->ptr_entities = 0; + } + if (topology->ptr_interfaces) { + free((void *)topology->ptr_interfaces); + topology->ptr_interfaces = 0; + } + /* + if (topology->ptr_pads) + free((void *)topology->ptr_pads); + if (topology->ptr_links) + free((void *)topology->ptr_links); + */ + + //topology->ptr_pads = 0; + //topology->ptr_links = 0; + + if (device) + free((void *)device); + + if (media_fd >= 0) + close(media_fd); + + if (video_fd >= 0) + close(video_fd); + + return rc; +} + int media_request_alloc(int media_fd) { @@ -97,3 +386,8 @@ int media_request_wait_completion(int request_fd) return 0; } + +static inline __u32 media_type(__u32 id) +{ + return id >> 24; +} diff --git a/src/media.h b/src/media.h index 2d0436f..edc5844 100644 --- a/src/media.h +++ b/src/media.h @@ -25,9 +25,14 @@ #ifndef _MEDIA_H_ #define _MEDIA_H_ +#include + +struct driver; + int media_request_alloc(int media_fd); int media_request_reinit(int request_fd); int media_request_queue(int request_fd); int media_request_wait_completion(int request_fd); +int media_scan_topology(struct driver *driver, int id, const char *path); #endif diff --git a/src/picture.c b/src/picture.c index aa86265..e78fffb 100644 --- a/src/picture.c +++ b/src/picture.c @@ -48,7 +48,9 @@ #include "utils.h" #include "v4l2.h" +#ifndef MESON_BUILD #include "autoconfig.h" +#endif static VAStatus codec_store_buffer(struct request_data *driver_data, VAProfile profile, diff --git a/src/request.c b/src/request.c index 2bfa8d4..b328293 100644 --- a/src/request.c +++ b/src/request.c @@ -1,7 +1,6 @@ /* - * Copyright (C) 2007 Intel Corporation - * Copyright (C) 2016 Florent Revest - * Copyright (C) 2018 Paul Kocialkowski + * Copyright (c) 2016 Florent Revest, + * 2007 Intel Corporation. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -24,6 +23,7 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#define _GNU_SOURCE #include "buffer.h" #include "config.h" #include "context.h" @@ -57,21 +57,51 @@ VAStatus __attribute__((visibility("default"))) VA_DRIVER_INIT_FUNC(VADriverContextP context); +/* + * may we can substitue this function when deducing the + * driver-name from topology + +static int v4l2_callback(struct device *dev, void *p) +{ + struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); + + // test if we have initialized drivers + if (v4l2_dev == NULL) + return 0; + + return 0; +} + +int v4l2_iterate(void *p) +{ + struct device_driver *drv; + int rc; + + // Find 'cedrus' driver. + drv = driver_find("cedrus", &pci_bus_type); + + // iterate over all ivtv device instances + rc = driver_for_each_device(drv, NULL, p, v4l2_callback); + //if ( rc = 0 ) + request_log("cedrus driver: %s\n", drv->name); + put_driver(drv); + + return rc; +} +*/ + VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP context) { struct request_data *driver_data; - struct driver *driver = NULL; - struct decoder *decoder = NULL; + struct driver *driver; + struct decoder *decoder; struct VADriverVTable *vtable = context->vtable; VAStatus status; - __u32 capabilities; - __u32 capabilities_required; int video_fd = -1; int media_fd = -1; - char *video_path; + char *subsystem; char *media_path; int rc; - int id = 0; context->version_major = VA_MAJOR_VERSION; context->version_minor = VA_MINOR_VERSION; @@ -150,13 +180,15 @@ VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP context) IMAGE_ID_OFFSET); /* initilize structures and pointer */ + request_log("Initializing driver structure...\n"); + driver = calloc(1, sizeof(struct driver)); driver_init(driver); - decoder = driver->decoder[0]; - - /* environment settings */ - decoder->media_path = getenv("LIBVA_V4L2_REQUEST_MEDIA_PATH"); - if (decoder->media_path == NULL) { + decoder = calloc(1, sizeof(struct decoder)); + + /* environment settings */ + media_path = getenv("LIBVA_V4L2_REQUEST_MEDIA_PATH"); + if (media_path == NULL) { subsystem = "media"; request_log("Scanning for suitable v4l2 driver (subsystem: %s)...\n", subsystem); @@ -164,46 +196,51 @@ VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP context) } else { request_log("Scanning v4l2 topology (media_path: %s)...\n", - decoder->media_path); - rc = media_scan_topology(driver, id); + media_path); + + // update media_path in driver structure + driver_set(driver, 0, decoder); + asprintf(&decoder->media_path, "%s", media_path); + + rc = media_scan_topology(driver, 0, media_path); + if (rc < 0) { + request_log("media_path '%s' doesn't offer v4l2 video-decoder.\n", + media_path); + driver_delete(driver, 0); + } + else if (rc == 1) { + request_log(" media_path '%s' offers v4l2 video-decoder.\n", + media_path); + } } - if (rc < 0) { - request_log("No suitable v4l2 decoder found\n"); + /* result structure with suitable video decoder entities */ + if (driver_get_num_decoders(driver) > 0) { + driver_print_all(driver); + /* + * assign first available decoder elements + * to the corresponding config elements + */ + decoder = driver_get(driver, 0); + request_log("Decoders: %i (Select: '%s', media_path: %s, video_path: %s, capabilities: %ld)\n", + driver->num_decoders, + decoder->name, + decoder->media_path, + decoder->video_path, + decoder->capabilities); + } + else { + request_log("No suitable v4l2 decoder found.\n"); status = VA_STATUS_ERROR_INVALID_CONFIG; goto error; } - driver_print(driver); - /* - video_path = getenv("LIBVA_V4L2_REQUEST_VIDEO_PATH"); - if (video_path == NULL) - video_path = "/dev/video0"; - - video_fd = open(video_path, O_RDWR | O_NONBLOCK); + video_fd = open(decoder->video_path, O_RDWR | O_NONBLOCK); if (video_fd < 0) return VA_STATUS_ERROR_OPERATION_FAILED; - rc = v4l2_query_capabilities(video_fd, &capabilities); - if (rc < 0) { - status = VA_STATUS_ERROR_OPERATION_FAILED; - goto error; - } - - capabilities_required = V4L2_CAP_STREAMING; - - if ((capabilities & capabilities_required) != capabilities_required) { - request_log("Missing required driver capabilities\n"); - status = VA_STATUS_ERROR_OPERATION_FAILED; - goto error; - } - - media_path = getenv("LIBVA_V4L2_REQUEST_MEDIA_PATH"); - if (media_path == NULL) - media_path = "/dev/media0"; - - media_fd = open(media_path, O_RDWR | O_NONBLOCK); + media_fd = open(decoder->media_path, O_RDWR | O_NONBLOCK); if (media_fd < 0) return VA_STATUS_ERROR_OPERATION_FAILED; @@ -211,6 +248,9 @@ VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP context) driver_data->media_fd = media_fd; status = VA_STATUS_SUCCESS; + + driver_free(driver); + goto complete; error: diff --git a/src/request.h b/src/request.h index 1fb593b..95211bc 100644 --- a/src/request.h +++ b/src/request.h @@ -1,7 +1,6 @@ /* - * Copyright (C) 2007 Intel Corporation - * Copyright (C) 2016 Florent Revest - * Copyright (C) 2018 Paul Kocialkowski + * Copyright (c) 2016 Florent Revest, + * 2007 Intel Corporation. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -29,13 +28,16 @@ #include -#include "context.h" -#include "object_heap.h" -#include "video.h" #include #include +#include "context.h" +#include "media.h" +#include "object_heap.h" +#include "video.h" +#include "utils.h" + #define V4L2_REQUEST_STR_VENDOR "v4l2-request" #define V4L2_REQUEST_MAX_PROFILES 11 diff --git a/src/utils.c b/src/utils.c index d37eeee..aa6cea8 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2016 Florent Revest * Copyright (C) 2018 Paul Kocialkowski + * Copyright (C) 2019 Ralf Zerres * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -23,13 +24,228 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#define _GNU_SOURCE +#include +#include #include #include #include +#include +#include + +#include +#include #include "request.h" +#include "media.h" #include "utils.h" +int driver_add(struct driver *driver, struct decoder *decoder) +{ + int rc = -1; + + /* make sure there's room to expand into */ + if (driver->capacity == driver->num_decoders) { + rc = driver_extend(driver); + if (rc < 0) + return rc; + } + + /* add the decoder and increment element counter */ + driver->decoder[driver->num_decoders++] = decoder; + + return decoder->id; +} + +void driver_delete(struct driver *driver, int id) +{ + if (id < 0 || id >= driver->num_decoders) + return; + + driver->decoder[id] = NULL; + + for (int i = id; i < driver->capacity - 1; i++) { + driver->decoder[i] = driver->decoder[i + 1]; + driver->decoder[i + 1] = NULL; + } + + driver->num_decoders--; + + driver_reduce(driver); +} + +int driver_extend(struct driver *driver) +{ + //struct decoder *decoder; + int new_capacity = driver->capacity + 1; // decoder increment = 1 + int decoder_index = new_capacity - 1; + + if (decoder_index < driver->capacity) { + /* pointer to hold new pointer to 'struct decoder' */ + void **new_decoder; + + /* + * extend driver->capacity to hold another 'struct decoder' + * and resize the allocated memory accordingly + */ + request_log("driver_extend(): prepare new decoder entity '%i'\n", decoder_index); + new_decoder = realloc(driver->decoder, + sizeof(struct decoder) * new_capacity); + if (new_decoder == NULL) + return -1; + + driver->capacity = new_capacity; + driver->decoder = new_decoder; + } + + //decoder = calloc(1, sizeof(struct decoder)); + return 0; +} + +void driver_free(struct driver *driver) +{ + int i; + + for (i = 0; i < driver->num_decoders; i++) + free(driver->decoder[i]); + + free(driver->decoder); + driver->decoder = NULL; +} + +struct decoder *driver_get(struct driver *driver, int id) +{ + if (id > driver->num_decoders || id < 0) { + printf("Id %d out of bounds for driver of %d entities\n", id, driver->num_decoders); + return NULL; + } + + return driver->decoder[id]; +} + +__u32 driver_get_capabilities(struct driver *driver, int id) +{ + struct decoder *decoder; + + if (id >= driver->num_decoders || id < 0) { + request_log("Id '%d' out of bounds. Only handle %d decoders yet.\n", + id, driver->num_decoders); + return -1; + } + + decoder = (struct decoder *) driver->decoder[id]; + + return decoder->capabilities; +} + +int driver_get_first_id(struct driver *driver) +{ + struct decoder *decoder; + + decoder = (struct decoder *) driver->decoder[0]; + + return decoder->id; +} + +int driver_get_last_id(struct driver *driver) +{ + struct decoder *decoder; + + decoder = (struct decoder *)driver->decoder[driver->num_decoders]; + + return decoder->id; +} + +int driver_get_num_decoders(struct driver *driver) +{ + return driver->num_decoders; +} + +void driver_init(struct driver *driver) +{ + driver->num_decoders = 0; + driver->capacity = 1; + + // allocate memory for first decoder array + driver->decoder = calloc(driver->capacity, sizeof(struct decoder)); +} + +void driver_print(struct driver *driver, int id) +{ + if (id >= driver->num_decoders || id < 0) { + request_log("Id '%d' out of bounds. Only handle %d decoders yet.\n", + id, driver->num_decoders); + } + + struct decoder *decoder = driver_get(driver, id); + request_log(" decoder[%i]: %s (id: %i, media_path: %s, video_path: %s, capabilities: %ld)\n", + id, + decoder->name, + decoder->id, + decoder->media_path, + decoder->video_path, + decoder->capabilities); +} + +void driver_print_all(struct driver *driver) +{ + request_log("Driver: num_decoders: %d, capacity: %d\n", + driver->num_decoders, + driver->capacity); + for (int i = 0; i < driver_get_num_decoders(driver); i++) { + struct decoder *decoder = driver_get(driver, i); + request_log("decoder[%i]: %s (id: %i, media_path: %s, video_path: %s, capabilities: %ld)\n", + i, + decoder->name, + decoder->id, + decoder->media_path, + decoder->video_path, + decoder->capabilities); + } +} + +void driver_reduce(struct driver *driver) +{ + if (driver->num_decoders > 0 && + driver->num_decoders == driver->capacity -1) { + /* + * reduce driver->capacity + * and resize the allocated memory accordingly + */ + driver->capacity--; + driver->decoder = realloc(driver->decoder, sizeof(struct decoder) * driver->capacity); + } +} + +void driver_set(struct driver *driver, int id, void *decoder) +{ + /* zero fill the driver up to the desired id */ + while (id >= driver->num_decoders) { + driver_add(driver, decoder); + } + + /* memcopy the given source structure at the desired id */ + driver->decoder[id] = decoder; +} + +__u32 driver_set_capabilities(struct driver *driver, int id, unsigned int capabilities) +{ + struct decoder *decoder; + + if (id >= driver->num_decoders || id < 0) { + request_log("Id '%d' out of bounds. Only handle %d decoders yet.\n", + id, driver->num_decoders); + return -1; + } + + decoder = (struct decoder *) driver->decoder[id]; + + /* memcopy the given source structure at the desired id */ + decoder->capabilities = capabilities; + + return 0; +} + void request_log(const char *format, ...) { va_list arguments; @@ -40,3 +256,135 @@ void request_log(const char *format, ...) vfprintf(stderr, format, arguments); va_end(arguments); } + +char *udev_get_devpath(struct media_v2_intf_devnode *devnode) +{ + struct udev *udev; + struct udev_device *device; + dev_t devnum; + const char *ptr_devname; + char *devname = NULL; + int rs; + + udev = udev_new(); + if (!udev) { + request_log("Can’t create udev object.\n"); + return NULL; + } + + devnum = makedev(devnode->major, devnode->minor); + device = udev_device_new_from_devnum(udev, 'c', devnum); + if (device) { + ptr_devname = udev_device_get_devnode(device); + if (ptr_devname) { + rs = asprintf(&devname, "%s", ptr_devname); + if (rs < 0) + return NULL; + } + } + + udev_device_unref(device); + + return devname; +} + +int udev_scan_subsystem(struct driver *driver, char *subsystem) +{ + struct udev *udev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_device *dev; + struct decoder *decoder; + int rc = -1; + int i = 0; + int y = 0; + + /* Create the udev object */ + udev = udev_new(); + if (!udev) { + printf("Can’t create udev\n"); + return -1; + } + + /* Create a list of sys devices for given subsystem */ + enumerate = udev_enumerate_new(udev); + rc = udev_enumerate_add_match_subsystem(enumerate, subsystem); + if (rc < 0) { + request_log("udev: can't filter sysbsystem %s.\n", + subsystem); + return rc; + } + rc = udev_enumerate_scan_devices(enumerate); + if (rc < 0) { + request_log("udev: can't scan devices.\n"); + return rc; + } + devices = udev_enumerate_get_list_entry(enumerate); + + /* For each item enumerated, print out its information. + udev_list_entry_foreach is a macro which expands to + a loop. The loop will be executed for each member in + devices, setting dev_list_entry to a list entry + which contains the device’s path in /sys. + */ + udev_list_entry_foreach(dev_list_entry, devices) { + const char *path; + const char *node_path; + const char *node_name; + + /* Get the filename of the /sys entry for the device + and create a udev_device object (dev) representing it + */ + path = udev_list_entry_get_name(dev_list_entry); + dev = udev_device_new_from_syspath(udev, path); + node_path = udev_device_get_devnode(dev); + node_name = udev_device_get_sysname(dev); + + /* From here, we can call get_sysattr_value() for each file + in the device’s /sys entry. The strings passed into these + functions (idProduct, idVendor, serial, etc.) correspond + directly to the files in the directory which represents + the device attributes. Strings returned from + udev_device_get_sysattr_value() are UTF-8 encoded. + */ + + /* initilize decoder pointer */ + decoder = calloc(1, sizeof(struct decoder)); + + if (strncmp(node_name, "media", 5) == 0) { + asprintf(&decoder->media_path, "%s", node_path); + udev_device_get_sysattr_value(dev, "model"); + request_log("udev node: [%i]\n", i); + + // update media_path in driver structure + driver_set(driver, y, decoder); + + /* use media topology to select capable video-decoders. */ + rc = media_scan_topology(driver, y, node_path); + if (rc <= 0) { + request_log("model '%s' doesn't offer streaming via v4l2 video-decoder.\n", + udev_device_get_sysattr_value(dev, "model")); + driver_delete(driver, y); + } + else if (rc == 1) { + request_log(" model '%s' offers streaming via v4l2 video-decoder.\n", + udev_device_get_sysattr_value(dev, "model")); + driver_print(driver, y++); + } + } + + i++; + udev_device_unref(dev); + } + + /* Free unnedded stuctures */ + if (driver) + free((void *)driver); + if (decoder) + free((void *)decoder); + + udev_enumerate_unref(enumerate); + udev_unref(udev); + + return rc; +} diff --git a/src/utils.h b/src/utils.h index e39141d..580cda5 100644 --- a/src/utils.h +++ b/src/utils.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2016 Florent Revest * Copyright (C) 2018 Paul Kocialkowski + * Copyright (C) 2019 Ralf Zerres * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -26,6 +27,56 @@ #ifndef _UTILS_H_ #define _UTILS_H_ +#include +#include + +//#include "media.h" + +#define DRIVER_LAST -1 +/* + * Structures + */ + +struct decoder { + int id; + char *name; + char *media_path; + char *video_path; + unsigned int capabilities; +}; + +struct driver { + int capacity; + void **decoder; + int num_decoders; +}; + +/* + * Functions + */ + +/* v4l2 driver */ +int driver_add(struct driver *driver, struct decoder *decoder); +void driver_delete(struct driver *driver, int id); +int driver_extend(struct driver *driver); +void driver_free(struct driver *driver); +struct decoder *driver_get(struct driver *driver, int id); +__u32 driver_get_capabilities(struct driver *driver, int id); +int driver_get_first_id(struct driver *driver); +int driver_get_last_id(struct driver *driver); +int driver_get_num_decoders(struct driver *driver); +void driver_init(struct driver *driver); +void driver_print(struct driver *driver, int id); +void driver_print_all(struct driver *driver); +void driver_reduce(struct driver *driver); +void driver_set(struct driver *driver, int id, void *decoder); +__u32 driver_set_capabilities(struct driver *driver, int id, unsigned int capabilities); + +/* v4l2 request */ void request_log(const char *format, ...); +/* udev handling */ +char *udev_get_devpath(struct media_v2_intf_devnode *devnode); +int udev_scan_subsystem(struct driver *driver, char *subsystem); + #endif From f3a0ea317abcc257cace5eb737fef7ca84813a75 Mon Sep 17 00:00:00 2001 From: Ralf Zerres Date: Mon, 15 Apr 2019 01:36:21 +0200 Subject: [PATCH 5/5] update transient include definitions Signed-off-by: Ralf Zerres --- src/config.c | 9 ++++++--- src/context.c | 4 ++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/config.c b/src/config.c index d769974..1852871 100644 --- a/src/config.c +++ b/src/config.c @@ -24,9 +24,6 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "config.h" -#include "request.h" - #include #include @@ -34,6 +31,8 @@ #include +#include "config.h" +#include "request.h" #include "utils.h" #include "v4l2.h" @@ -122,9 +121,11 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context, profiles[index++] = VAProfileMPEG2Main; } + /* found = v4l2_find_format(driver_data->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_PIX_FMT_H264_SLICE); + */ if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 5)) { profiles[index++] = VAProfileH264Main; profiles[index++] = VAProfileH264High; @@ -133,9 +134,11 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context, profiles[index++] = VAProfileH264StereoHigh; } + /* found = v4l2_find_format(driver_data->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_PIX_FMT_HEVC_SLICE); + */ if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 1)) profiles[index++] = VAProfileHEVCMain; diff --git a/src/context.c b/src/context.c index 38733a8..7946ba4 100644 --- a/src/context.c +++ b/src/context.c @@ -95,6 +95,7 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id, pixelformat = V4L2_PIX_FMT_MPEG2_SLICE; break; +#ifdef V4L2_PIX_FMT_H264_SLICE case VAProfileH264Main: case VAProfileH264High: case VAProfileH264ConstrainedBaseline: @@ -102,10 +103,13 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id, case VAProfileH264StereoHigh: pixelformat = V4L2_PIX_FMT_H264_SLICE; break; +#endif +#ifdef V4L2_PIX_FMT_HEVC_SLICE case VAProfileHEVCMain: pixelformat = V4L2_PIX_FMT_HEVC_SLICE; break; +#endif default: status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;