Handle EOS event
authorJeongmo Yang <jm80.yang@samsung.com>
Wed, 22 Jan 2025 11:59:41 +0000 (20:59 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Thu, 23 Jan 2025 02:53:45 +0000 (11:53 +0900)
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
src/hal_backend_codec_v4l2.c

index 9a9389027095ae1142e1ae44afd5c20337dc00c8..1ff3ace3625550d87cb50fa3e8f4adb238b08dcf 100644 (file)
@@ -83,8 +83,8 @@
 #define IDLE_BUFFER_TIME_OUT_MS         1000
 #define NSEC_PER_SEC                    (G_USEC_PER_SEC * 1000)
 #define OUTPUT_POLL_TIMEOUT_MS          3000
-#define POLL_ERROR_TRY_COUNT_MAX        3
-#define POLL_ERROR_TRY_SLEEP_US         100000
+#define POLL_ERROR_TRY_COUNT_MAX        10
+#define POLL_ERROR_TRY_SLEEP_US         10000
 
 
 #define BUFFER_CONTROL_TYPE_STRING(type) \
@@ -855,6 +855,8 @@ static int __codec_v4l2_dqbuf(int device_fd,
 
        *out_buffer = &buffer_control->buffers.buffer[v4l2_buf.index];
 
+       (*out_buffer)->meta.flags = HAL_CODEC_BUFFER_FLAG_NONE;
+
        if (buffer_control->type == CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT) {
                TIMEVAL_TO_TIMESTAMP(v4l2_buf.timestamp, (*out_buffer)->meta.timestamp);
 
@@ -863,6 +865,12 @@ static int __codec_v4l2_dqbuf(int device_fd,
                        TIMESTAMP_ARGS((*out_buffer)->meta.timestamp));
        }
 
+       if (v4l2_buf.flags & V4L2_BUF_FLAG_LAST &&
+               v4l2_buf.m.planes[0].bytesused == 0) {
+               LOGW("[%s] LAST BUFFER - set EOS flag", BUFFER_CONTROL_TYPE_STRING(buffer_control->type));
+               (*out_buffer)->meta.flags |= HAL_CODEC_BUFFER_FLAG_EOS;
+       }
+
        return HAL_CODEC_ERROR_NONE;
 }
 
@@ -1722,6 +1730,7 @@ static gpointer __codec_v4l2_buffer_handler_func(gpointer data)
 {
        int ret = 0;
        int error_count = 0;
+       gboolean run_loop = TRUE;
 
        short revents = 0;
        codec_hal_handle_s *handle = (codec_hal_handle_s *)data;
@@ -1740,7 +1749,7 @@ static gpointer __codec_v4l2_buffer_handler_func(gpointer data)
        input_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT];
        output_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT];
 
-       while (TRUE) {
+       while (run_loop) {
                /* exit thread with some conditions */
                //////////////////////////////////////
 
@@ -1784,6 +1793,11 @@ static gpointer __codec_v4l2_buffer_handler_func(gpointer data)
 
                        LOGD("[OUTPUT] DQBUF index[%d]", output_buffer->index);
 
+                       if (output_buffer->meta.flags & HAL_CODEC_BUFFER_FLAG_EOS) {
+                               LOGW("[OUTPUT] Got EOS, stop buffer handler");
+                               run_loop = FALSE;
+                       }
+
                        __codec_v4l2_message_send(handle, HAL_CODEC_MESSAGE_TYPE_OUTPUT_BUFFER, output_buffer);
                }
 
@@ -1888,8 +1902,10 @@ int codec_v4l2_stop(void *codec_handle)
 
        LOGI("join output thread");
 
-       g_thread_join(handle->buffer_handler);
-       handle->buffer_handler = NULL;
+       if (handle->buffer_handler) {
+               g_thread_join(handle->buffer_handler);
+               handle->buffer_handler = NULL;
+       }
 
        handle->state = HAL_CODEC_STATE_CONFIGURED;
 
@@ -1991,6 +2007,23 @@ int codec_v4l2_decode(void *codec_handle, hal_codec_buffer_s *buffer)
 
        buffer_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT];
 
+       if (buffer->meta.flags & HAL_CODEC_BUFFER_FLAG_EOS) {
+               struct v4l2_decoder_cmd dcmd = { 0, };
+
+               LOGW("EOS - VIDIOC_DECODER_CMD: V4L2_DEC_CMD_STOP");
+
+               dcmd.cmd = V4L2_DEC_CMD_STOP;
+
+               if (ioctl(handle->device_fd, VIDIOC_DECODER_CMD, &dcmd) < 0)
+                       LOGE("V4L2_DEC_CMD_STOP failed %d", errno);
+
+               __codec_v4l2_message_send(handle, HAL_CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED, buffer);
+
+               LOGW("done");
+
+               return HAL_CODEC_ERROR_NONE;
+       }
+
        idle_buffer = __codec_v4l2_get_idle_buffer(buffer_control, IDLE_BUFFER_TIME_OUT_MS);
        if (!idle_buffer) {
                LOGE("no idle buffer");