diff options
-rw-r--r-- | src/buffer.c | 11 | ||||
-rw-r--r-- | src/config.c | 6 | ||||
-rw-r--r-- | src/context.c | 47 | ||||
-rw-r--r-- | src/image.c | 36 | ||||
-rw-r--r-- | src/picture.c | 15 | ||||
-rw-r--r-- | src/request.c | 2 | ||||
-rw-r--r-- | src/request.h | 1 | ||||
-rw-r--r-- | src/surface.c | 73 | ||||
-rw-r--r-- | src/v4l2.c | 157 | ||||
-rw-r--r-- | src/v4l2.h | 2 | ||||
-rw-r--r-- | src/video.c | 6 | ||||
-rw-r--r-- | src/video.h | 3 |
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; @@ -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; } @@ -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; }; |