Set input buffer size with supported max resolution
authorJeongmo Yang <jm80.yang@samsung.com>
Wed, 22 Jan 2025 06:00:04 +0000 (15:00 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Wed, 22 Jan 2025 06:01:07 +0000 (15:01 +0900)
- QBUF for input buffer could be failed because of small buffer size.
  The default buffer size is not enough in case of high bitrate content.

Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
src/hal_backend_codec_v4l2.c
src/hal_backend_codec_v4l2_private.h

index afe8ca832ec49c7608ad2db3a810c36c0f346bf3..9a9389027095ae1142e1ae44afd5c20337dc00c8 100644 (file)
@@ -110,6 +110,7 @@ typedef struct _codec_v4l2_format_list_s {
        enum v4l2_buf_type buf_type;
        hal_codec_format_type_e format_type;
        hal_codec_format_e formats[DEVICE_FORMAT_MAX];
+       hal_codec_resolution_s max_resolution[DEVICE_FORMAT_MAX];
 } codec_v4l2_format_list_s;
 
 typedef struct _codec_v4l2_device_s {
@@ -195,6 +196,7 @@ static void __codec_v4l2_get_supported_format_list(int device_fd,
        uint32_t count = 0;
        hal_codec_format_e format = HAL_CODEC_FORMAT_H264;
        struct v4l2_fmtdesc fmtdesc;
+       struct v4l2_frmsizeenum frmsize;
 
        if (device_fd < 0 || !format_list) {
                LOGE("invalid param[%d,%p]", device_fd, format_list);
@@ -214,15 +216,29 @@ static void __codec_v4l2_get_supported_format_list(int device_fd,
                        break;
                }
 
-               if (__codec_v4l2_get_format(fmtdesc.pixelformat, &format) == HAL_CODEC_ERROR_NONE) {
-                       format_list->formats[count] = format;
-                       count++;
+               if (__codec_v4l2_get_format(fmtdesc.pixelformat, &format) != HAL_CODEC_ERROR_NONE)
+                       continue;
+
+               format_list->formats[count] = format;
+
+               if (format & HAL_CODEC_FORMAT_TYPE_ENCODED)
+                       format_list->format_type = HAL_CODEC_FORMAT_TYPE_ENCODED;
+               else
+                       format_list->format_type = HAL_CODEC_FORMAT_TYPE_RAW;
+
+               memset(&frmsize, 0x0, sizeof(struct v4l2_frmsizeenum));
 
-                       if (format & HAL_CODEC_FORMAT_TYPE_ENCODED)
-                               format_list->format_type = HAL_CODEC_FORMAT_TYPE_ENCODED;
-                       else
-                               format_list->format_type = HAL_CODEC_FORMAT_TYPE_RAW;
+               frmsize.pixel_format = fmtdesc.pixelformat;
+
+               if (ioctl(device_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) == 0) {
+                       LOGI("["FOURCC_FORMAT"] max size [%ux%u]", FOURCC_CONVERT(fmtdesc.pixelformat),
+                               frmsize.stepwise.max_width, frmsize.stepwise.max_height);
+
+                       format_list->max_resolution[count].width = frmsize.stepwise.max_width;
+                       format_list->max_resolution[count].height = frmsize.stepwise.max_height;
                }
+
+               count++;
        }
 
        format_list->count = count;
@@ -321,10 +337,7 @@ static int __codec_v4l2_probe_device(void)
                close(device_fd);
 
                if (codec_device->in_format.count > 0 && codec_device->out_format.count > 0 &&
-                       ((codec_device->in_format.format_type == HAL_CODEC_FORMAT_TYPE_ENCODED &&
-                               codec_device->out_format.format_type == HAL_CODEC_FORMAT_TYPE_RAW) ||
-                        (codec_device->in_format.format_type == HAL_CODEC_FORMAT_TYPE_RAW &&
-                               codec_device->out_format.format_type == HAL_CODEC_FORMAT_TYPE_ENCODED))) {
+                       codec_device->in_format.format_type != codec_device->out_format.format_type) {
                        strncpy(codec_device->node_path, glob_buf.gl_pathv[i], DEVICE_NODE_PATH_LENGTH_MAX - 1);
                        codec_device->capabilities = device_caps;
 
@@ -390,8 +403,9 @@ static void __codec_v4l2_release_device_list(void)
 }
 
 
-static int __codec_v4l2_get_buf_type_and_node_path(hal_codec_format_e in_format, hal_codec_format_e out_format,
-       enum v4l2_buf_type *in_buf_type, enum v4l2_buf_type *out_buf_type, char **path)
+static int __codec_v4l2_get_device_info(hal_codec_format_e in_format, hal_codec_format_e out_format,
+       enum v4l2_buf_type *in_buf_type, enum v4l2_buf_type *out_buf_type,
+       hal_codec_resolution_s *in_max_resolution, hal_codec_resolution_s *out_max_resolution, char **path)
 {
        uint32_t device_index = 0;
        uint32_t format_index = 0;
@@ -419,6 +433,10 @@ static int __codec_v4l2_get_buf_type_and_node_path(hal_codec_format_e in_format,
                for (format_index = 0 ; format_index < format_list->count ; format_index++) {
                        if (format_list->formats[format_index] == in_format) {
                                *in_buf_type = format_list->buf_type;
+                               if (in_max_resolution) {
+                                       in_max_resolution->width = format_list->max_resolution[format_index].width;
+                                       in_max_resolution->height = format_list->max_resolution[format_index].height;
+                               }
                                break;
                        }
                }
@@ -435,6 +453,11 @@ static int __codec_v4l2_get_buf_type_and_node_path(hal_codec_format_e in_format,
                                *out_buf_type = format_list->buf_type;
                                *path = codec_device->node_path;
 
+                               if (out_max_resolution) {
+                                       out_max_resolution->width = format_list->max_resolution[format_index].width;
+                                       out_max_resolution->height = format_list->max_resolution[format_index].height;
+                               }
+
                                LOGI("found node path[%s], buf_type[in:%d, out:%d] for format[in:0x%x, out:0x%x]",
                                        *path, *in_buf_type, *out_buf_type, in_format, out_format);
 
@@ -535,7 +558,7 @@ static int __codec_v4l2_s_ctrl(int device_fd, int cid, int value)
 
 static int __codec_v4l2_set_config(codec_hal_buffer_control_s *buffer_control,
        enum v4l2_buf_type buf_type, enum v4l2_memory memory,
-       hal_codec_format_e format, int width, int height)
+       hal_codec_format_e format, int width, int height, int max_width, int max_height)
 {
        codec_hal_config_s *codec_config = NULL;
 
@@ -546,14 +569,16 @@ static int __codec_v4l2_set_config(codec_hal_buffer_control_s *buffer_control,
 
        codec_config = &buffer_control->config;
 
-       LOGI("type[%d] v4l2[buf type:%d, memory:%d], format[0x%x], resolution[%dx%d]",
-               buffer_control->type, buf_type, memory, format, width, height);
+       LOGI("type[%d] v4l2[buf type:%d, memory:%d], format[0x%x], resolution[%dx%d][max:%dx%d]",
+               buffer_control->type, buf_type, memory, format, width, height, max_width, max_height);
 
        codec_config->buf_type = buf_type;
        codec_config->memory = memory;
        codec_config->format = format;
        codec_config->resolution.width = width;
        codec_config->resolution.height = height;
+       codec_config->max_resolution.width = max_width;
+       codec_config->max_resolution.height = max_height;
 
        return HAL_CODEC_ERROR_NONE;
 }
@@ -577,7 +602,8 @@ static int __codec_v4l2_s_fmt(codec_hal_buffer_control_s *buffer_control, int de
        type = buffer_control->type;
 
        if (__codec_get_fourcc_plane_num(codec_config->format, &fourcc, &num_planes) != HAL_CODEC_ERROR_NONE) {
-               LOGE("type[%d] get fourcc failed for format [0x%x]", type, codec_config->format);
+               LOGE("[%s] get fourcc failed for format [0x%x]",
+                       BUFFER_CONTROL_TYPE_STRING(type), codec_config->format);
                return HAL_CODEC_ERROR_INVALID_PARAMETER;
        }
 
@@ -599,15 +625,26 @@ static int __codec_v4l2_s_fmt(codec_hal_buffer_control_s *buffer_control, int de
                v4l2_fmt.fmt.pix.bytesperline = codec_config->resolution.width;
        }
 
+       if (type == CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT &&
+               codec_config->max_resolution.width > 0 &&
+               codec_config->max_resolution.height > 0) {
+               v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = (codec_config->max_resolution.width * codec_config->max_resolution.height) >> 1;
+
+               LOGI("[%s] set buffer size[%u] with max resolution[%dx%d]",
+                       BUFFER_CONTROL_TYPE_STRING(type),
+                       v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage,
+                       codec_config->max_resolution.width, codec_config->max_resolution.height);
+       }
+
        if (ioctl(device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
-               LOGE("type[%d] S_FMT failed[%s]", type, __codec_v4l2_get_error_string(errno));
+               LOGE("[%s] S_FMT failed[%s]", BUFFER_CONTROL_TYPE_STRING(type), __codec_v4l2_get_error_string(errno));
                return HAL_CODEC_ERROR_INTERNAL;
        }
 
        if (V4L2_TYPE_IS_MULTIPLANAR(codec_config->buf_type)) {
                for (i = 0 ; i < v4l2_fmt.fmt.pix_mp.num_planes ; i++) {
-                       LOGI("type[%d]  plane[%d] size [%u]",
-                               type, i, v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
+                       LOGI("[%s] plane[%d] size [%u]", BUFFER_CONTROL_TYPE_STRING(type),
+                               i, v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
                        codec_config->buffer_size += v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage;
                }
        } else {
@@ -615,8 +652,8 @@ static int __codec_v4l2_s_fmt(codec_hal_buffer_control_s *buffer_control, int de
                codec_config->buffer_size = v4l2_fmt.fmt.pix.sizeimage;
        }
 
-       LOGI("type[%d] buffer size[%u], num planes[%u]",
-               type, codec_config->buffer_size, codec_config->num_planes);
+       LOGI("[%s] buffer size[%u], num planes[%u]", BUFFER_CONTROL_TYPE_STRING(type),
+               codec_config->buffer_size, codec_config->num_planes);
 
        return HAL_CODEC_ERROR_NONE;
 }
@@ -1515,6 +1552,8 @@ int codec_v4l2_configure(void *codec_handle, int width, int height,
        int i = 0;
        int ret = 0;
        int device_fd = CODEC_HAL_INITIAL_FD;
+       hal_codec_resolution_s in_max_resolution = {0, 0};
+       hal_codec_resolution_s out_max_resolution = {0, 0};
        char *node_path = NULL;
 
        codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
@@ -1544,8 +1583,8 @@ int codec_v4l2_configure(void *codec_handle, int width, int height,
                return HAL_CODEC_ERROR_INVALID_PARAMETER;
        }
 
-       ret = __codec_v4l2_get_buf_type_and_node_path(in_format, out_format,
-               &in_buf_type, &out_buf_type, &node_path);
+       ret = __codec_v4l2_get_device_info(in_format, out_format,
+               &in_buf_type, &out_buf_type, &in_max_resolution, &out_max_resolution, &node_path);
        if (ret != HAL_CODEC_ERROR_NONE)
                return ret;
 
@@ -1581,7 +1620,7 @@ int codec_v4l2_configure(void *codec_handle, int width, int height,
 
        /* set format for input */
        ret = __codec_v4l2_set_config(&handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT],
-               in_buf_type, V4L2_MEMORY_MMAP, in_format, width, height);
+               in_buf_type, V4L2_MEMORY_MMAP, in_format, width, height, in_max_resolution.width, in_max_resolution.height);
        if (ret != HAL_CODEC_ERROR_NONE)
                return ret;
 
@@ -1594,7 +1633,7 @@ int codec_v4l2_configure(void *codec_handle, int width, int height,
 
        /* set format for output */
        ret = __codec_v4l2_set_config(&handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT],
-               out_buf_type, V4L2_MEMORY_DMABUF, out_format, width, height);
+               out_buf_type, V4L2_MEMORY_DMABUF, out_format, width, height, 0, 0);
        if (ret != HAL_CODEC_ERROR_NONE)
                return ret;
 
@@ -1926,7 +1965,7 @@ static void __codec_v4l2_add_idle_buffer(codec_hal_buffer_control_s *buffer_cont
 
        g_queue_push_tail(buffer_control->buffers.idle_buffers, GINT_TO_POINTER(buffer->index));
 
-       g_cond_broadcast(&buffer_control->cond); 
+       g_cond_broadcast(&buffer_control->cond);
 }
 
 
@@ -1968,12 +2007,14 @@ int codec_v4l2_decode(void *codec_handle, hal_codec_buffer_s *buffer)
        if (ret != HAL_CODEC_ERROR_NONE) {
                LOGE("QBUF[%p] failed[i:%d], 0x%x",
                        buffer, idle_buffer->index, ret);
-       } else {
-               LOGD("QBUF[%p] done", buffer);
-               __codec_v4l2_message_send(handle, HAL_CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED, buffer);
+               return ret;
        }
 
-       return ret;
+       LOGD("QBUF[%p] done", buffer);
+
+       __codec_v4l2_message_send(handle, HAL_CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED, buffer);
+
+       return HAL_CODEC_ERROR_NONE;
 }
 
 
index 51acde6bba017b81a7b6198084bf7fe84ffcaf99..e32eb04a31c5df0785fa2fcdb8ede4c14121b1c9 100644 (file)
@@ -29,7 +29,7 @@
 
 #define CODEC_HAL_INITIAL_INDEX         -1
 #define CODEC_HAL_INITIAL_FD            -1
-#define BUFFER_MIN                      4
+#define BUFFER_MIN                      6
 #define BUFFER_MAX                      16
 #define V4L2_PLANES_MAX                 4
 
@@ -55,6 +55,7 @@ typedef struct {
        enum v4l2_memory memory;
        hal_codec_format_e format;
        hal_codec_resolution_s resolution;
+       hal_codec_resolution_s max_resolution;
        uint32_t num_planes;
        uint32_t buffer_size;
 } codec_hal_config_s;