summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Kocialkowski <contact@paulk.fr>2018-09-07 16:43:13 +0200
committerPaul Kocialkowski <contact@paulk.fr>2018-09-07 16:43:13 +0200
commit7ff2543e64e1e1b689d6ad515a46643ea2926d84 (patch)
tree66169f9964ee7543c86c257c76eb908f45d3bea0 /src
parent25a8ac4d7eaee3d69361721db33a50b5c3119194 (diff)
downloadlibva-v4l2-request-7ff2543e64e1e1b689d6ad515a46643ea2926d84.tar.gz
libva-v4l2-request-7ff2543e64e1e1b689d6ad515a46643ea2926d84.tar.bz2
libva-v4l2-request-7ff2543e64e1e1b689d6ad515a46643ea2926d84.zip
Add support for the single-planar V4L2 APImaster
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c11
-rw-r--r--src/config.c6
-rw-r--r--src/context.c47
-rw-r--r--src/image.c36
-rw-r--r--src/picture.c15
-rw-r--r--src/request.c2
-rw-r--r--src/request.h1
-rw-r--r--src/surface.c73
-rw-r--r--src/v4l2.c157
-rw-r--r--src/v4l2.h2
-rw-r--r--src/video.c6
-rw-r--r--src/video.h3
12 files changed, 267 insertions, 92 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 641e286..6677187 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -197,9 +197,17 @@ VAStatus RequestAcquireBufferHandle(VADriverContextP context,
struct request_data *driver_data = context->pDriverData;
struct object_buffer *buffer_object;
struct object_surface *surface_object;
+ struct video_format *video_format;
+ unsigned int capture_type;
int export_fd;
int rc;
+ video_format = driver_data->video_format;
+ if (video_format == NULL)
+ return VA_STATUS_ERROR_OPERATION_FAILED;
+
+ capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
+
if (buffer_info->mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME ||
!video_format_is_linear(driver_data->video_format))
return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
@@ -218,8 +226,7 @@ VAStatus RequestAcquireBufferHandle(VADriverContextP context,
if (surface_object->destination_buffers_count > 1)
return VA_STATUS_ERROR_OPERATION_FAILED;
- rc = v4l2_export_buffer(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ rc = v4l2_export_buffer(driver_data->video_fd, capture_type,
surface_object->destination_index, O_RDONLY,
&export_fd, 1);
if (rc < 0)
diff --git a/src/config.c b/src/config.c
index fcbfe6b..c76240d 100644
--- a/src/config.c
+++ b/src/config.c
@@ -112,7 +112,7 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context,
bool found;
found = v4l2_find_format(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT,
V4L2_PIX_FMT_MPEG2_SLICE);
if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 2)) {
profiles[index++] = VAProfileMPEG2Simple;
@@ -120,7 +120,7 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context,
}
found = v4l2_find_format(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+ V4L2_BUF_TYPE_VIDEO_OUTPUT,
V4L2_PIX_FMT_H264_SLICE);
if (found && index < (V4L2_REQUEST_MAX_CONFIG_ATTRIBUTES - 5)) {
profiles[index++] = VAProfileH264Main;
@@ -131,7 +131,7 @@ VAStatus RequestQueryConfigProfiles(VADriverContextP context,
}
found = v4l2_find_format(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+ 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 c6ebf0c..943887f 100644
--- a/src/context.c
+++ b/src/context.c
@@ -50,18 +50,27 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
struct object_config *config_object;
struct object_surface *surface_object;
struct object_context *context_object = NULL;
+ struct video_format *video_format;
unsigned int length;
unsigned int offset;
void *source_data = MAP_FAILED;
VASurfaceID *ids = NULL;
VAContextID id;
VAStatus status;
+ unsigned int output_type, capture_type;
unsigned int pixelformat;
unsigned int index_base;
unsigned int index;
unsigned int i;
int rc;
+ video_format = driver_data->video_format;
+ if (video_format == NULL)
+ return VA_STATUS_ERROR_OPERATION_FAILED;
+
+ output_type = v4l2_type_video_output(video_format->v4l2_mplane);
+ capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
+
config_object = CONFIG(driver_data, config_id);
if (config_object == NULL) {
status = VA_STATUS_ERROR_INVALID_CONFIG;
@@ -99,16 +108,14 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
goto error;
}
- rc = v4l2_set_format(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, pixelformat,
+ rc = v4l2_set_format(driver_data->video_fd, output_type, pixelformat,
picture_width, picture_height);
if (rc < 0) {
status = VA_STATUS_ERROR_OPERATION_FAILED;
goto error;
}
- rc = v4l2_create_buffers(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+ rc = v4l2_create_buffers(driver_data->video_fd, output_type,
surfaces_count, &index_base);
if (rc < 0) {
status = VA_STATUS_ERROR_ALLOCATION_FAILED;
@@ -137,9 +144,8 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
goto error;
}
- rc = v4l2_query_buffer(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, index,
- &length, &offset, 1);
+ rc = v4l2_query_buffer(driver_data->video_fd, output_type,
+ index, &length, &offset, 1);
if (rc < 0) {
status = VA_STATUS_ERROR_ALLOCATION_FAILED;
goto error;
@@ -157,15 +163,13 @@ VAStatus RequestCreateContext(VADriverContextP context, VAConfigID config_id,
surface_object->source_size = length;
}
- rc = v4l2_set_stream(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, true);
+ rc = v4l2_set_stream(driver_data->video_fd, output_type, true);
if (rc < 0) {
status = VA_STATUS_ERROR_OPERATION_FAILED;
goto error;
}
- rc = v4l2_set_stream(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, true);
+ rc = v4l2_set_stream(driver_data->video_fd, capture_type, true);
if (rc < 0) {
status = VA_STATUS_ERROR_OPERATION_FAILED;
goto error;
@@ -203,20 +207,27 @@ VAStatus RequestDestroyContext(VADriverContextP context, VAContextID context_id)
{
struct request_data *driver_data = context->pDriverData;
struct object_context *context_object;
+ struct video_format *video_format;
+ unsigned int output_type, capture_type;
VAStatus status;
int rc;
+ video_format = driver_data->video_format;
+ if (video_format == NULL)
+ return VA_STATUS_ERROR_OPERATION_FAILED;
+
+ output_type = v4l2_type_video_output(video_format->v4l2_mplane);
+ capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
+
context_object = CONTEXT(driver_data, context_id);
if (context_object == NULL)
return VA_STATUS_ERROR_INVALID_CONTEXT;
- rc = v4l2_set_stream(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, false);
+ rc = v4l2_set_stream(driver_data->video_fd, output_type, false);
if (rc < 0)
return VA_STATUS_ERROR_OPERATION_FAILED;
- rc = v4l2_set_stream(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, false);
+ rc = v4l2_set_stream(driver_data->video_fd, capture_type, false);
if (rc < 0)
return VA_STATUS_ERROR_OPERATION_FAILED;
@@ -232,13 +243,11 @@ VAStatus RequestDestroyContext(VADriverContextP context, VAContextID context_id)
object_heap_free(&driver_data->context_heap,
(struct object_base *)context_object);
- rc = v4l2_request_buffers(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 0);
+ rc = v4l2_request_buffers(driver_data->video_fd, output_type, 0);
if (rc < 0)
return VA_STATUS_ERROR_OPERATION_FAILED;
- rc = v4l2_request_buffers(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 0);
+ rc = v4l2_request_buffers(driver_data->video_fd, capture_type, 0);
if (rc < 0)
return VA_STATUS_ERROR_OPERATION_FAILED;
diff --git a/src/image.c b/src/image.c
index 1beac88..476007b 100644
--- a/src/image.c
+++ b/src/image.c
@@ -43,7 +43,11 @@ VAStatus RequestCreateImage(VADriverContextP context, VAImageFormat *format,
unsigned int destination_sizes[VIDEO_MAX_PLANES];
unsigned int destination_bytesperlines[VIDEO_MAX_PLANES];
unsigned int destination_planes_count;
+ unsigned int planes_count;
+ unsigned int format_width, format_height;
unsigned int size;
+ unsigned int capture_type;
+ struct video_format *video_format;
struct object_image *image_object;
VABufferID buffer_id;
VAImageID id;
@@ -51,18 +55,39 @@ VAStatus RequestCreateImage(VADriverContextP context, VAImageFormat *format,
unsigned int i;
int rc;
- rc = v4l2_get_format(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, NULL, NULL,
+ video_format = driver_data->video_format;
+ if (video_format == NULL)
+ return VA_STATUS_ERROR_OPERATION_FAILED;
+
+ capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
+
+ /*
+ * FIXME: This should be replaced by per-pixelformat hadling to
+ * determine the logical plane offsets and sizes;
+ */
+ rc = v4l2_get_format(driver_data->video_fd, capture_type,
+ &format_width, &format_height,
destination_bytesperlines, destination_sizes,
- &destination_planes_count);
+ &planes_count);
if (rc < 0)
return VA_STATUS_ERROR_OPERATION_FAILED;
+ destination_planes_count = video_format->planes_count;
size = 0;
- for (i = 0; i < destination_planes_count; i++)
+ /* The size returned by V4L2 covers buffers, not logical planes. */
+ for (i = 0; i < planes_count; i++)
size += destination_sizes[i];
+ /* Here we calculate the sizes assuming NV12. */
+
+ destination_sizes[0] = destination_bytesperlines[0] * format_height;
+
+ for (i = 1; i < destination_planes_count; i++) {
+ destination_bytesperlines[i] = destination_bytesperlines[0];
+ destination_sizes[i] = destination_sizes[0] / 2;
+ }
+
id = object_heap_allocate(&driver_data->image_heap);
image_object = IMAGE(driver_data, id);
if (image_object == NULL)
@@ -155,10 +180,11 @@ VAStatus RequestDeriveImage(VADriverContextP context, VASurfaceID surface_id,
image->pitches[i], image->width,
i == 0 ? image->height :
image->height / 2);
- else
+ else {
memcpy(buffer_object->data + image->offsets[i],
surface_object->destination_data[i],
surface_object->destination_sizes[i]);
+ }
}
surface_object->status = VASurfaceReady;
diff --git a/src/picture.c b/src/picture.c
index f1ec1c3..3490820 100644
--- a/src/picture.c
+++ b/src/picture.c
@@ -267,10 +267,19 @@ VAStatus RequestEndPicture(VADriverContextP context, VAContextID context_id)
struct object_context *context_object;
struct object_config *config_object;
struct object_surface *surface_object;
+ struct video_format *video_format;
+ unsigned int output_type, capture_type;
int request_fd;
VAStatus status;
int rc;
+ video_format = driver_data->video_format;
+ if (video_format == NULL)
+ return VA_STATUS_ERROR_OPERATION_FAILED;
+
+ output_type = v4l2_type_video_output(video_format->v4l2_mplane);
+ capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
+
context_object = CONTEXT(driver_data, context_id);
if (context_object == NULL)
return VA_STATUS_ERROR_INVALID_CONTEXT;
@@ -298,15 +307,13 @@ VAStatus RequestEndPicture(VADriverContextP context, VAContextID context_id)
if (rc != VA_STATUS_SUCCESS)
return rc;
- rc = v4l2_queue_buffer(driver_data->video_fd, -1,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ rc = v4l2_queue_buffer(driver_data->video_fd, -1, capture_type,
surface_object->destination_index, 0,
surface_object->destination_buffers_count);
if (rc < 0)
return VA_STATUS_ERROR_OPERATION_FAILED;
- rc = v4l2_queue_buffer(driver_data->video_fd, request_fd,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+ rc = v4l2_queue_buffer(driver_data->video_fd, request_fd, output_type,
surface_object->source_index,
surface_object->slices_size, 1);
if (rc < 0)
diff --git a/src/request.c b/src/request.c
index 2c3ed7f..25d0ed3 100644
--- a/src/request.c
+++ b/src/request.c
@@ -159,7 +159,7 @@ VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP context)
goto error;
}
- capabilities_required = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+ capabilities_required = V4L2_CAP_STREAMING;
if ((capabilities & capabilities_required) != capabilities_required) {
request_log("Missing required driver capabilities\n");
diff --git a/src/request.h b/src/request.h
index 37c7d2f..8c6696b 100644
--- a/src/request.h
+++ b/src/request.h
@@ -30,6 +30,7 @@
#include "context.h"
#include "object_heap.h"
+#include "video.h"
#include <va/va.h>
#include <linux/videodev2.h>
diff --git a/src/surface.c b/src/surface.c
index a400ec6..ab06619 100644
--- a/src/surface.c
+++ b/src/surface.c
@@ -58,6 +58,8 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
unsigned int destination_sizes[VIDEO_MAX_PLANES];
unsigned int destination_bytesperlines[VIDEO_MAX_PLANES];
unsigned int destination_planes_count;
+ unsigned int format_width, format_height;
+ unsigned int capture_type;
unsigned int index_base;
unsigned int index;
unsigned int i, j;
@@ -69,13 +71,13 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
found = v4l2_find_format(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_PIX_FMT_SUNXI_TILED_NV12);
if (found)
video_format = video_format_find(V4L2_PIX_FMT_SUNXI_TILED_NV12);
found = v4l2_find_format(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_PIX_FMT_NV12);
if (found)
video_format = video_format_find(V4L2_PIX_FMT_NV12);
@@ -85,21 +87,22 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
driver_data->video_format = video_format;
- rc = v4l2_set_format(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
+
+ rc = v4l2_set_format(driver_data->video_fd, capture_type,
video_format->v4l2_format, width, height);
if (rc < 0)
return VA_STATUS_ERROR_OPERATION_FAILED;
- rc = v4l2_get_format(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, NULL, NULL,
- destination_bytesperlines, destination_sizes,
- &destination_planes_count);
+ rc = v4l2_get_format(driver_data->video_fd, capture_type, &format_width,
+ &format_height, destination_bytesperlines,
+ destination_sizes, NULL);
if (rc < 0)
return VA_STATUS_ERROR_OPERATION_FAILED;
- rc = v4l2_create_buffers(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ destination_planes_count = video_format->planes_count;
+
+ rc = v4l2_create_buffers(driver_data->video_fd, capture_type,
surfaces_count, &index_base);
if (rc < 0)
return VA_STATUS_ERROR_ALLOCATION_FAILED;
@@ -112,8 +115,7 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
if (surface_object == NULL)
return VA_STATUS_ERROR_ALLOCATION_FAILED;
- rc = v4l2_query_buffer(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ rc = v4l2_query_buffer(driver_data->video_fd, capture_type,
index,
surface_object->destination_map_lengths,
surface_object->destination_map_offsets,
@@ -133,7 +135,19 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
return VA_STATUS_ERROR_ALLOCATION_FAILED;
}
+ /*
+ * FIXME: Handle this per-pixelformat, trying to generalize it
+ * is not a reasonable approach. The final description should be
+ * in terms of (logical) planes.
+ */
+
if (video_format->v4l2_buffers_count == 1) {
+ destination_sizes[0] = destination_bytesperlines[0] *
+ format_height;
+
+ for (j = 1; j < destination_planes_count; j++)
+ destination_sizes[j] = destination_sizes[0] / 2;
+
for (j = 0; j < destination_planes_count; j++) {
surface_object->destination_offsets[j] =
j > 0 ? destination_sizes[j - 1] : 0;
@@ -143,7 +157,7 @@ VAStatus RequestCreateSurfaces2(VADriverContextP context, unsigned int format,
surface_object->destination_sizes[j] =
destination_sizes[j];
surface_object->destination_bytesperlines[j] =
- destination_bytesperlines[j];
+ destination_bytesperlines[0];
}
} else if (video_format->v4l2_buffers_count == destination_planes_count) {
for (j = 0; j < destination_planes_count; j++) {
@@ -233,9 +247,20 @@ VAStatus RequestSyncSurface(VADriverContextP context, VASurfaceID surface_id)
struct request_data *driver_data = context->pDriverData;
struct object_surface *surface_object;
VAStatus status;
+ struct video_format *video_format;
+ unsigned int output_type, capture_type;
int request_fd = -1;
int rc;
+ video_format = driver_data->video_format;
+ if (video_format == NULL) {
+ status = VA_STATUS_ERROR_OPERATION_FAILED;
+ goto error;
+ }
+
+ output_type = v4l2_type_video_output(video_format->v4l2_mplane);
+ capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
+
surface_object = SURFACE(driver_data, surface_id);
if (surface_object == NULL) {
status = VA_STATUS_ERROR_INVALID_SURFACE;
@@ -271,16 +296,14 @@ VAStatus RequestSyncSurface(VADriverContextP context, VASurfaceID surface_id)
goto error;
}
- rc = v4l2_dequeue_buffer(driver_data->video_fd, -1,
- V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+ rc = v4l2_dequeue_buffer(driver_data->video_fd, -1, output_type,
surface_object->source_index, 1);
if (rc < 0) {
status = VA_STATUS_ERROR_OPERATION_FAILED;
goto error;
}
- rc = v4l2_dequeue_buffer(driver_data->video_fd, -1,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ rc = v4l2_dequeue_buffer(driver_data->video_fd, -1, capture_type,
surface_object->destination_index,
surface_object->destination_buffers_count);
if (rc < 0) {
@@ -433,11 +456,16 @@ VAStatus RequestExportSurfaceHandle(VADriverContextP context,
int *export_fds = NULL;
unsigned int export_fds_count;
unsigned int planes_count;
+ unsigned int capture_type;
unsigned int size;
unsigned int i;
VAStatus status;
int rc;
+ video_format = driver_data->video_format;
+ if (video_format == NULL)
+ return VA_STATUS_ERROR_OPERATION_FAILED;
+
if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2)
return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
@@ -448,8 +476,9 @@ VAStatus RequestExportSurfaceHandle(VADriverContextP context,
export_fds_count = surface_object->destination_buffers_count;
export_fds = malloc(export_fds_count * sizeof(*export_fds));
- rc = v4l2_export_buffer(driver_data->video_fd,
- V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+ capture_type = v4l2_type_video_capture(video_format->v4l2_mplane);
+
+ rc = v4l2_export_buffer(driver_data->video_fd, capture_type,
surface_object->destination_index, O_RDONLY,
export_fds, export_fds_count);
if (rc < 0) {
@@ -459,12 +488,6 @@ VAStatus RequestExportSurfaceHandle(VADriverContextP context,
planes_count = surface_object->destination_planes_count;
- video_format = driver_data->video_format;
- if (video_format == NULL) {
- status = VA_STATUS_ERROR_OPERATION_FAILED;
- goto error;
- }
-
surface_descriptor->fourcc = VA_FOURCC_NV12;
surface_descriptor->width = surface_object->width;
surface_descriptor->height = surface_object->height;
diff --git a/src/v4l2.c b/src/v4l2.c
index 2560680..a76dadf 100644
--- a/src/v4l2.c
+++ b/src/v4l2.c
@@ -32,6 +32,42 @@
#include "utils.h"
#include "v4l2.h"
+static bool v4l2_type_is_output(unsigned int type)
+{
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool v4l2_type_is_mplane(unsigned int type)
+{
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+unsigned int v4l2_type_video_output(bool mplane)
+{
+ return mplane ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
+ V4L2_BUF_TYPE_VIDEO_OUTPUT;
+}
+
+unsigned int v4l2_type_video_capture(bool mplane)
+{
+ return mplane ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
+ V4L2_BUF_TYPE_VIDEO_CAPTURE;
+}
+
int v4l2_query_capabilities(int video_fd, unsigned int *capabilities)
{
struct v4l2_capability capability;
@@ -53,6 +89,30 @@ int v4l2_query_capabilities(int video_fd, unsigned int *capabilities)
return 0;
}
+static void v4l2_setup_format(struct v4l2_format *format, unsigned int type,
+ unsigned int width, unsigned int height,
+ unsigned int pixelformat)
+{
+ unsigned int sizeimage;
+
+ memset(format, 0, sizeof(*format));
+ format->type = type;
+
+ sizeimage = v4l2_type_is_output(type) ? SOURCE_SIZE_MAX : 0;
+
+ if (v4l2_type_is_mplane(type)) {
+ format->fmt.pix_mp.width = width;
+ format->fmt.pix_mp.height = height;
+ format->fmt.pix_mp.plane_fmt[0].sizeimage = sizeimage;
+ format->fmt.pix_mp.pixelformat = pixelformat;
+ } else {
+ format->fmt.pix.width = width;
+ format->fmt.pix.height = height;
+ format->fmt.pix.sizeimage = sizeimage;
+ format->fmt.pix.pixelformat = pixelformat;
+ }
+}
+
bool v4l2_find_format(int video_fd, unsigned int type, unsigned int pixelformat)
{
struct v4l2_fmtdesc fmtdesc;
@@ -76,19 +136,31 @@ bool v4l2_find_format(int video_fd, unsigned int type, unsigned int pixelformat)
return false;
}
+int v4l2_try_format(int video_fd, unsigned int type, unsigned int width,
+ unsigned int height, unsigned int pixelformat)
+{
+ struct v4l2_format format;
+ int rc;
+
+ v4l2_setup_format(&format, type, width, height, pixelformat);
+
+ 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));
+ return -1;
+ }
+
+ return 0;
+}
+
int v4l2_set_format(int video_fd, unsigned int type, unsigned int pixelformat,
unsigned int width, unsigned int height)
{
struct v4l2_format format;
int rc;
- memset(&format, 0, sizeof(format));
- format.type = type;
- format.fmt.pix_mp.width = width;
- format.fmt.pix_mp.height = height;
- format.fmt.pix_mp.plane_fmt[0].sizeimage =
- type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ? SOURCE_SIZE_MAX : 0;
- format.fmt.pix_mp.pixelformat = pixelformat;
+ v4l2_setup_format(&format, type, width, height, pixelformat);
rc = ioctl(video_fd, VIDIOC_S_FMT, &format);
if (rc < 0) {
@@ -119,29 +191,46 @@ int v4l2_get_format(int video_fd, unsigned int type, unsigned int *width,
return -1;
}
- count = format.fmt.pix_mp.num_planes;
+ if (v4l2_type_is_mplane(type)) {
+ count = format.fmt.pix_mp.num_planes;
+
+ if (width != NULL)
+ *width = format.fmt.pix_mp.width;
+
+ if (height != NULL)
+ *height = format.fmt.pix_mp.height;
- if (width != NULL)
- *width = format.fmt.pix_mp.width;
+ if (planes_count != NULL)
+ if (*planes_count > 0 && *planes_count < count)
+ count = *planes_count;
- if (height != NULL)
- *height = format.fmt.pix_mp.height;
+ if (bytesperline != NULL)
+ for (i = 0; i < count; i++)
+ bytesperline[i] =
+ format.fmt.pix_mp.plane_fmt[i].bytesperline;
- if (planes_count != NULL)
- if (*planes_count > 0 && *planes_count < count)
- count = *planes_count;
+ if (sizes != NULL)
+ for (i = 0; i < count; i++)
+ sizes[i] = format.fmt.pix_mp.plane_fmt[i].sizeimage;
- if (bytesperline != NULL)
- for (i = 0; i < count; i++)
- bytesperline[i] =
- format.fmt.pix_mp.plane_fmt[i].bytesperline;
+ if (planes_count != NULL)
+ *planes_count = count;
+ } else {
+ if (width != NULL)
+ *width = format.fmt.pix.width;
- if (sizes != NULL)
- for (i = 0; i < count; i++)
- sizes[i] = format.fmt.pix_mp.plane_fmt[i].sizeimage;
+ if (height != NULL)
+ *height = format.fmt.pix.height;
- if (planes_count != NULL)
- *planes_count = count;
+ if (bytesperline != NULL)
+ bytesperline[0] = format.fmt.pix.bytesperline;
+
+ if (sizes != NULL)
+ sizes[0] = format.fmt.pix.sizeimage;
+
+ if (planes_count != NULL)
+ *planes_count = 1;
+ }
return 0;
}
@@ -201,13 +290,21 @@ int v4l2_query_buffer(int video_fd, unsigned int type, unsigned int index,
return -1;
}
- if (lengths != NULL)
- for (i = 0; i < buffer.length; i++)
- lengths[i] = buffer.m.planes[i].length;
+ if (v4l2_type_is_mplane(type)) {
+ if (lengths != NULL)
+ for (i = 0; i < buffer.length; i++)
+ lengths[i] = buffer.m.planes[i].length;
- if (offsets != NULL)
- for (i = 0; i < buffer.length; i++)
- offsets[i] = buffer.m.planes[i].m.mem_offset;
+ if (offsets != NULL)
+ for (i = 0; i < buffer.length; i++)
+ offsets[i] = buffer.m.planes[i].m.mem_offset;
+ } else {
+ if (lengths != NULL)
+ lengths[0] = buffer.length;
+
+ if (offsets != NULL)
+ offsets[0] = buffer.m.offset;
+ }
return 0;
}
diff --git a/src/v4l2.h b/src/v4l2.h
index d56e6d2..ec40080 100644
--- a/src/v4l2.h
+++ b/src/v4l2.h
@@ -29,6 +29,8 @@
#define SOURCE_SIZE_MAX (1024 * 1024)
+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);
bool v4l2_find_format(int video_fd, unsigned int type,
unsigned int pixelformat);
diff --git a/src/video.c b/src/video.c
index 116e025..b8a75a0 100644
--- a/src/video.c
+++ b/src/video.c
@@ -39,18 +39,20 @@ static struct video_format formats[] = {
.description = "NV12 YUV",
.v4l2_format = V4L2_PIX_FMT_NV12,
.v4l2_buffers_count = 1,
+ .v4l2_mplane = false,
.drm_format = DRM_FORMAT_NV12,
.drm_modifier = DRM_FORMAT_MOD_NONE,
- .drm_planes_count = 2,
+ .planes_count = 2,
.bpp = 16,
},
{
.description = "Sunxi tiled NV12 YUV",
.v4l2_format = V4L2_PIX_FMT_SUNXI_TILED_NV12,
.v4l2_buffers_count = 1,
+ .v4l2_mplane = false,
.drm_format = DRM_FORMAT_NV12,
.drm_modifier = DRM_FORMAT_MOD_ALLWINNER_MB32_TILED,
- .drm_planes_count = 2,
+ .planes_count = 2,
.bpp = 16
},
};
diff --git a/src/video.h b/src/video.h
index 124c46f..1996fd5 100644
--- a/src/video.h
+++ b/src/video.h
@@ -31,9 +31,10 @@ struct video_format {
char *description;
unsigned int v4l2_format;
unsigned int v4l2_buffers_count;
+ bool v4l2_mplane;
unsigned int drm_format;
uint64_t drm_modifier;
- unsigned int drm_planes_count;
+ unsigned int planes_count;
unsigned int bpp;
};