Bug fix 23/322923/4
authorJeongmo Yang <jm80.yang@samsung.com>
Fri, 18 Apr 2025 01:59:48 +0000 (10:59 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Fri, 18 Apr 2025 10:13:57 +0000 (19:13 +0900)
1. Encoder
 : Update to send INPUT_BUFFER_USED message.
 : Set sync flag for sync frame.
 : Support YUYV format.

2. Decoder
 : Get new TBM surface info when restart output stream.
 : Reset output buffer size when restart output stream.

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

index e4947d6f5367bbccfaf7167892c5c72c8fe14bd7..636ebe82eec634436d1db06b429c6fe66a43f830 100644 (file)
@@ -156,8 +156,8 @@ static int __codec_v4l2_stop_stream(codec_hal_handle_s *handle, codec_hal_buffer
 
 static int __codec_v4l2_set_command(codec_hal_handle_s *handle, int64_t command, void *value);
 
-static hal_codec_buffer_s *__codec_v4l2_get_idle_buffer(codec_hal_buffer_control_s *buffer_control, gint64 timeout_ms);
-static void __codec_v4l2_add_idle_buffer(codec_hal_buffer_control_s *buffer_control, hal_codec_buffer_s *buffer);
+static hal_codec_buffer_s *__codec_v4l2_get_idle_buffer(codec_hal_buffer_control_s *buffer_control, gint64 timeout_ms, hal_codec_buffer_s *user_buffer);
+static void __codec_v4l2_add_idle_buffer(codec_hal_buffer_control_s *buffer_control, hal_codec_buffer_s *buffer, hal_codec_buffer_s **user_buffer);
 
 static int  __codec_v4l2_get_format(guint32 fourcc, hal_codec_format_e *format);
 static int  __codec_v4l2_get_fourcc_plane_num(hal_codec_format_e format, uint32_t *fourcc, uint32_t *plane_num);
@@ -373,7 +373,6 @@ static int __codec_v4l2_probe_device(void)
 static void __codec_v4l2_release_device_list(void)
 {
        uint32_t device_index = 0;
-       uint32_t device_count = 0;
        codec_v4l2_device_s *codec_device = NULL;
 
        if (!g_codec_device_list) {
@@ -383,7 +382,7 @@ static void __codec_v4l2_release_device_list(void)
 
        LOGI("release device list [%p]", g_codec_device_list);
 
-       for (device_index = 0 ; device_index < device_count ; device_index++) {
+       for (device_index = 0 ; device_index < g_codec_device_list->count ; device_index++) {
                codec_device = g_codec_device_list->devices[device_index];
                if (!codec_device) {
                        LOGW("NULL codec_device for index[%u]", device_index);
@@ -489,38 +488,43 @@ static void __codec_v4l2_message_send(codec_hal_handle_s *handle, hal_codec_mess
        message = g_new0(hal_codec_message_s, 1);
        message->type = type;
 
-       locker = g_mutex_locker_new(&handle->msg_cb_lock);
-
        switch (type) {
        case HAL_CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED:
                message->buffer = (hal_codec_buffer_s *)value;
-               LOGD("InputBufferUsed[message:%p]: buffer[i:%d,HAL:%p]",
-                       message, message->buffer->index, message->buffer);
+               if (!message->buffer) {
+                       LOGE("[INPUT_BUFFER_USED] NULL buffer");
+                       g_free(message);
+                       return;
+               }
+               LOGD("[INPUT_BUFFER_USED] buffer[%d] %p", message->buffer->index, message->buffer);
                break;
        case HAL_CODEC_MESSAGE_TYPE_OUTPUT_BUFFER:
                message->buffer = (hal_codec_buffer_s *)value;
-               LOGD("OutputBuffer[message:%p]: buffer[i:%d,HAL:%p]",
-                       message, message->buffer->index, message->buffer);
+               if (!message->buffer) {
+                       LOGE("[OUTPUT_BUFFER] NULL buffer");
+                       g_free(message);
+                       return;
+               }
+               LOGD("[OUTPUT_BUFFER] buffer[%d] %p", message->buffer->index, message->buffer);
                break;
        case HAL_CODEC_MESSAGE_TYPE_RESOLUTION_CHANGED:
                message->resolution.width = ((hal_codec_resolution_s *)value)->width;
                message->resolution.height = ((hal_codec_resolution_s *)value)->height;
-               LOGI("ResolutionChanged[%dx%d]", message->resolution.width, message->resolution.height);
+               LOGI("[RESOLUTION_CHANGED] %dx%d", message->resolution.width, message->resolution.height);
                break;
        case HAL_CODEC_MESSAGE_TYPE_ERROR:
                message->error_code = GPOINTER_TO_INT(value);
-               LOGE("error code[%d]", message->error_code);
+               LOGE("[ERROR] code[%d]", message->error_code);
                break;
        default:
-               LOGW("unhandled type[%d]", type);
+               LOGE("unhandled type[%d]", type);
                g_free(message);
                return;
        }
 
-       g_queue_push_tail(handle->msg_list, message);
-
-       LOGD("message length[%u]", g_queue_get_length(handle->msg_list));
+       locker = g_mutex_locker_new(&handle->msg_cb_lock);
 
+       g_queue_push_tail(handle->msg_list, message);
        g_cond_broadcast(&handle->msg_cb_cond);
 }
 
@@ -952,6 +956,12 @@ static int __codec_v4l2_dqbuf(int device_fd,
                        (*out_buffer)->planes.plane[0].bytesused = v4l2_buf.bytesused;
        }
 
+       if (codec_config->format & HAL_CODEC_FORMAT_TYPE_ENCODED &&
+               v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
+               LOGI("[ENCODER] SYNC FRAME");
+               (*out_buffer)->meta.flags |= HAL_CODEC_BUFFER_FLAG_SYNCFRAME;
+       }
+
        if (!BUFFER_CONTROL_TYPE_IS_INPUT(buffer_control)) {
                TIMEVAL_TO_TIMESTAMP(v4l2_buf.timestamp, (*out_buffer)->meta.timestamp);
 
@@ -1496,11 +1506,8 @@ static void *__codec_v4l2_message_handler_func(gpointer data)
        g_mutex_lock(&handle->msg_cb_lock);
 
        while (handle->msg_cb_run) {
-               if (g_queue_is_empty(handle->msg_list)) {
-                       LOGD("wait for message");
+               if (g_queue_is_empty(handle->msg_list))
                        g_cond_wait(&handle->msg_cb_cond, &handle->msg_cb_lock);
-                       LOGD("message[length:%u] signal received", g_queue_get_length(handle->msg_list));
-               }
 
                if (!handle->msg_cb_run) {
                        LOGW("break message thread");
@@ -1513,22 +1520,21 @@ static void *__codec_v4l2_message_handler_func(gpointer data)
                        continue;
                }
 
+#ifdef ENABLE_MESSAGE_THREAD_LOG
                switch (message->type) {
                case HAL_CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED:
-                       LOGD("INPUT_BUFFER_USED[message:%p]: buffer[index:%d,HAL:%p]",
-                               message, message->buffer->index, message->buffer);
+                       LOGD("[INPUT_BUFFER_USED] buffer[%d] %p", message->buffer->index, message->buffer);
                        break;
                case HAL_CODEC_MESSAGE_TYPE_OUTPUT_BUFFER:
-                       LOGD("OUTPUT_BUFFER[message:%p]: buffer[index:%d,HAL:%p]",
-                               message, message->buffer->index, message->buffer);
+                       LOGD("[OUTPUT_BUFFER] buffer[%d] %p", message->buffer->index, message->buffer);
                        break;
                case HAL_CODEC_MESSAGE_TYPE_RESOLUTION_CHANGED:
-                       LOGD("[message:%p] RESOLUTION_CHANGED [%dx%d]",
-                               message, message->resolution.width, message->resolution.height);
+                       LOGD("[RESOLUTION_CHANGED] %dx%d", message, message->resolution.width, message->resolution.height);
                        break;
                default:
                        break;
                }
+#endif
 
                g_mutex_unlock(&handle->msg_cb_lock);
 
@@ -1733,6 +1739,8 @@ static uint32_t __codec_v4l2_get_tbm_format(hal_codec_format_e codec_format)
                return TBM_FORMAT_NV12;
        case HAL_CODEC_FORMAT_I420:
                return TBM_FORMAT_YUV420;
+       case HAL_CODEC_FORMAT_YUYV:
+               return TBM_FORMAT_YUYV;
        default:
                break;
        }
@@ -1990,13 +1998,14 @@ static int __codec_v4l2_poll(codec_hal_handle_s *handle, short events, int timeo
 
 static void __codec_v4l2_restart_output_stream(codec_hal_handle_s *handle)
 {
+       int i = 0;
        int ret = 0;
-       int new_width = 0;
-       int new_height = 0;
        struct v4l2_format v4l2_fmt;
        codec_hal_config_s *config = NULL;
        codec_hal_buffer_control_s *buffer_control = NULL;
 
+       tbm_surface_h surface = NULL;
+
        if (!handle) {
                LOGE("NULL handle");
                return;
@@ -2023,17 +2032,32 @@ static void __codec_v4l2_restart_output_stream(codec_hal_handle_s *handle)
        }
 
        if (V4L2_TYPE_IS_MULTIPLANAR(config->buf_type)) {
-               new_width = v4l2_fmt.fmt.pix_mp.width;
-               new_height = v4l2_fmt.fmt.pix_mp.height;
+               config->resolution.width = v4l2_fmt.fmt.pix_mp.width;
+               config->resolution.height = v4l2_fmt.fmt.pix_mp.height;
+               config->buffer_size = 0;
+
+               for (i = 0 ; i < v4l2_fmt.fmt.pix_mp.num_planes ; i++) {
+                       LOGI("[%s] plane[%d] size [%u]", BUFFER_CONTROL_TYPE_STRING(buffer_control),
+                               i, v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
+                       config->buffer_size += v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage;
+               }
        } else {
-               new_width = v4l2_fmt.fmt.pix.width;
-               new_height = v4l2_fmt.fmt.pix.height;
+               config->resolution.width = v4l2_fmt.fmt.pix.width;
+               config->resolution.height = v4l2_fmt.fmt.pix.height;
+               config->buffer_size = v4l2_fmt.fmt.pix.sizeimage;
        }
 
-       LOGI("new resolution[%dx%d]", new_width, new_height);
+       LOGI("new resolution[%dx%d], buffer size[%u]",
+               config->resolution.width, config->resolution.height,
+               config->buffer_size);
 
-       config->resolution.width = new_width;
-       config->resolution.height = new_height;
+       surface = tbm_surface_create(config->resolution.width, config->resolution.height,
+               __codec_v4l2_get_tbm_format(config->format));
+       if (!surface) {
+               LOGE("create surface failed [%dx%d][format:%d]",
+                       config->resolution.width, config->resolution.height, config->format);
+               return;
+       }
 
        ret = __codec_v4l2_start_stream(handle, buffer_control, BUFFER_NUM_DECODER_OUTPUT);
        if (ret != HAL_CODEC_ERROR_NONE) {
@@ -2060,6 +2084,7 @@ static gpointer __codec_v4l2_buffer_handler_func(gpointer data)
        codec_hal_handle_s *handle = (codec_hal_handle_s *)data;
        hal_codec_buffer_s *input_buffer = NULL;
        hal_codec_buffer_s *output_buffer = NULL;
+       hal_codec_buffer_s *user_buffer = NULL;
        codec_hal_buffer_control_s *input_control = NULL;
        codec_hal_buffer_control_s *output_control = NULL;
 
@@ -2160,7 +2185,17 @@ static gpointer __codec_v4l2_buffer_handler_func(gpointer data)
 
                        LOGD("[INPUT] DQBUF index[%d]", input_buffer->index);
 
-                       __codec_v4l2_add_idle_buffer(input_control, input_buffer);
+                       __codec_v4l2_add_idle_buffer(input_control, input_buffer, &user_buffer);
+
+                       if (!user_buffer)
+                               continue;
+
+                       if (handle->type == HAL_CODEC_TYPE_DECODER) {
+                               LOGW("[DECODER] but, got user_buffer, check it.");
+                               continue;
+                       }
+
+                       __codec_v4l2_message_send(handle, HAL_CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED, user_buffer);
                }
        }
 
@@ -2294,7 +2329,8 @@ int codec_v4l2_flush(void *codec_handle)
 }
 
 
-static hal_codec_buffer_s *__codec_v4l2_get_idle_buffer(codec_hal_buffer_control_s *buffer_control, gint64 timeout_ms)
+static hal_codec_buffer_s *__codec_v4l2_get_idle_buffer(codec_hal_buffer_control_s *buffer_control,
+       gint64 timeout_ms, hal_codec_buffer_s *user_buffer)
 {
        int index = IDLE_BUFFER_INDEX_INIT;
        gint64 end_time = 0;
@@ -2328,13 +2364,17 @@ static hal_codec_buffer_s *__codec_v4l2_get_idle_buffer(codec_hal_buffer_control
 
        index = GPOINTER_TO_INT(g_queue_pop_head(buffer_control->buffers.idle_buffers));
 
-       LOGD("type[%d] popped buffer[%d]", buffer_control->type, index);
+       buffer_control->buffers.user_buffer[index] = user_buffer;
+
+       LOGD("type[%d] buffer[%d]: user_buffer[%p]",
+               buffer_control->type, index, user_buffer);
 
        return &buffer_control->buffers.buffer[index];
 }
 
 
-static void __codec_v4l2_add_idle_buffer(codec_hal_buffer_control_s *buffer_control, hal_codec_buffer_s *buffer)
+static void __codec_v4l2_add_idle_buffer(codec_hal_buffer_control_s *buffer_control,
+       hal_codec_buffer_s *buffer, hal_codec_buffer_s **user_buffer)
 {
        g_autoptr(GMutexLocker) locker = NULL;
 
@@ -2347,6 +2387,11 @@ static void __codec_v4l2_add_idle_buffer(codec_hal_buffer_control_s *buffer_cont
 
        LOGD("add idle buffer[%d]", buffer->index);
 
+       if (user_buffer)
+               *user_buffer = buffer_control->buffers.user_buffer[buffer->index];
+
+       buffer_control->buffers.user_buffer[buffer->index] = NULL;
+
        g_queue_push_tail(buffer_control->buffers.idle_buffers, GINT_TO_POINTER(buffer->index));
 
        g_cond_broadcast(&buffer_control->cond);
@@ -2392,7 +2437,7 @@ int codec_v4l2_decode(void *codec_handle, hal_codec_buffer_s *buffer)
                return HAL_CODEC_ERROR_NONE;
        }
 
-       idle_buffer = __codec_v4l2_get_idle_buffer(buffer_control, 0);
+       idle_buffer = __codec_v4l2_get_idle_buffer(buffer_control, 0, NULL);
        if (!idle_buffer) {
                LOGE("no idle buffer");
                return HAL_CODEC_ERROR_DEVICE_BUSY;
@@ -2409,6 +2454,7 @@ 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);
+               __codec_v4l2_add_idle_buffer(buffer_control, idle_buffer, NULL);
                return ret;
        }
 
@@ -2460,7 +2506,7 @@ int codec_v4l2_encode(void *codec_handle, hal_codec_buffer_s *buffer)
                return HAL_CODEC_ERROR_NONE;
        }
 
-       idle_buffer = __codec_v4l2_get_idle_buffer(buffer_control, 0);
+       idle_buffer = __codec_v4l2_get_idle_buffer(buffer_control, 0, buffer);
        if (!idle_buffer) {
                LOGE("no idle buffer");
                return HAL_CODEC_ERROR_DEVICE_BUSY;
@@ -2468,7 +2514,8 @@ int codec_v4l2_encode(void *codec_handle, hal_codec_buffer_s *buffer)
 
        idle_buffer->memory.num_fd = buffer->memory.num_fd;
        for (i = 0 ; i < buffer->memory.num_fd ; i++) {
-               LOGD("[INPUT] buffer[%d]: memory[%u] fd %d", buffer->index, i, buffer->memory.fd[i]);
+               LOGD("[INPUT] user_buffer[%d] %p: memory[%u] fd %d, idle_buffer[%d] %p",
+                       buffer->index, buffer, i, buffer->memory.fd[i], idle_buffer->index, idle_buffer);
                idle_buffer->memory.fd[i] = buffer->memory.fd[i];
        }
 
@@ -2480,6 +2527,7 @@ int codec_v4l2_encode(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);
+               __codec_v4l2_add_idle_buffer(buffer_control, idle_buffer, NULL);
                return ret;
        }
 
index e03d8d18e860c6af8747ef867fb1eb8fe5b2bad1..806ce7436d6cf88e393dc41595a259e5f1931694 100644 (file)
@@ -30,7 +30,7 @@
 #define CODEC_HAL_INITIAL_INDEX         -1
 #define CODEC_HAL_INITIAL_FD            -1
 #define BUFFER_NUM_MIN                  2
-#define BUFFER_NUM_MAX                  16
+#define BUFFER_NUM_MAX                  32
 #define BUFFER_NUM_DECODER_INPUT        4
 #define BUFFER_NUM_DECODER_OUTPUT       8
 #define BUFFER_NUM_ENCODER_INPUT        8
@@ -67,6 +67,7 @@ typedef struct {
 typedef struct {
        uint32_t count;
        hal_codec_buffer_s buffer[BUFFER_NUM_MAX];
+       hal_codec_buffer_s *user_buffer[BUFFER_NUM_MAX];        /**< encoder use only */
        tbm_bo bo[BUFFER_NUM_MAX][HAL_CODEC_BUFFER_PLANE_MAX];
        gboolean is_queued[BUFFER_NUM_MAX];
        int queued_count;