Support timestamp and set missed bytesused value
authorJeongmo Yang <jm80.yang@samsung.com>
Tue, 14 Jan 2025 02:35:14 +0000 (11:35 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Mon, 20 Jan 2025 23:23:55 +0000 (08:23 +0900)
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
src/hal_backend_codec_v4l2.c

index c88471f9bc8c46e183e4c9e9f6ac1609b58a37c3..afe8ca832ec49c7608ad2db3a810c36c0f346bf3 100644 (file)
@@ -57,9 +57,8 @@
 #define LOGE(fmt, arg...) dlog_print(DLOG_ERROR, LOG_TAG, "%s (%d) %s : " fmt, __FILE__, __LINE__, __FUNCTION__, ##arg)
 #endif
 
-#define VIRTUAL_CODEC_FMT_MAX  2
-#define VIRTUAL_CODEC_RES_MAX  3
 #define DEVICE_NODE_PATH_PREFIX "/dev/video"
+
 #define FOURCC_FORMAT           "%c%c%c%c"
 #define FOURCC_CONVERT(fourcc)  \
        fourcc & 0xff,\
        (fourcc >> 16) & 0xff,\
        (fourcc >> 24) & 0xff
 
+#define TIMESTAMP_SECOND        ((uint64_t)1000000000)
+#define TIMESTAMP_FORMAT        "03lu:%02lu:%02lu.%03lu"
+#define TIMESTAMP_ARGS(time)    \
+       (((uint64_t)time / (TIMESTAMP_SECOND * 60 * 60))), \
+       (((uint64_t)time / (TIMESTAMP_SECOND * 60)) % 60), \
+       (((uint64_t)time / TIMESTAMP_SECOND) % 60), \
+       ((uint64_t)time % TIMESTAMP_SECOND)
+
 #define DEVICE_TYPE_MAX                 (HAL_CODEC_TYPE_ENCODER + 1)
 #define DEVICE_NODE_PATH_LENGTH_MAX     32
 #define DEVICE_MAX                      8
 #define POLL_ERROR_TRY_SLEEP_US         100000
 
 
+#define BUFFER_CONTROL_TYPE_STRING(type) \
+       ((type == CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT) ? "INPUT" : "OUTPUT")
+
 #define TIMESTAMP_TO_TIMEVAL(timestamp, timeval) \
        do { \
-               timeval.tv_sec = (glong)(timestamp / NSEC_PER_SEC); \
-               timeval.tv_usec = (glong)((timestamp % NSEC_PER_SEC) / 1000); \
+               (timeval).tv_sec = ((uint64_t)(timestamp) / NSEC_PER_SEC); \
+               (timeval).tv_usec = (((uint64_t)(timestamp) - ((timeval).tv_sec * NSEC_PER_SEC)) / 1000); \
        } while (0)
 
 #define TIMEVAL_TO_TIMESTAMP(timeval, timestamp) \
        do { \
-               timestamp = timeval.tv_sec * NSEC_PER_SEC; \
-               timestamp += timeval.tv_usec * 1000; \
+               (timestamp) = (uint64_t)(timeval).tv_sec * NSEC_PER_SEC; \
+               (timestamp) += (uint64_t)(timeval).tv_usec * 1000; \
        } while (0)
 
 #define CODEC_THREAD_NAME_HANDLE_BUFFER "handle_buffer"
@@ -166,6 +176,17 @@ static void __codec_v4l2_destructor(void)
 }
 
 
+static char *__codec_v4l2_get_error_string(int err_number)
+{
+       static char error_string[ERROR_STRING_LENGTH];
+
+       error_string[0] = '\0';
+       strerror_r(err_number, error_string, ERROR_STRING_LENGTH);
+
+       return error_string;
+}
+
+
 static void __codec_v4l2_get_supported_format_list(int device_fd,
        enum v4l2_buf_type buf_type,
        codec_v4l2_format_list_s *format_list)
@@ -255,14 +276,14 @@ static int __codec_v4l2_probe_device(void)
 
                device_fd = open(glob_buf.gl_pathv[i], O_RDWR);
                if (device_fd < 0) {
-                       LOGE("open failed [%s] errno %d", glob_buf.gl_pathv[i], errno);
+                       LOGE("open failed [%s] %s", glob_buf.gl_pathv[i], __codec_v4l2_get_error_string(errno));
                        continue;
                }
 
                memset(&v4l2_cap, 0x0, sizeof(struct v4l2_capability));
 
                if (ioctl(device_fd, VIDIOC_QUERYCAP, &v4l2_cap) < 0) {
-                       LOGE("querycap failed. errno %d", errno);
+                       LOGE("querycap failed[%s]", __codec_v4l2_get_error_string(errno));
                        close(device_fd);
                        continue;
                }
@@ -579,7 +600,7 @@ static int __codec_v4l2_s_fmt(codec_hal_buffer_control_s *buffer_control, int de
        }
 
        if (ioctl(device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
-               LOGE("type[%d] S_FMT failed. errno %d", type, errno);
+               LOGE("type[%d] S_FMT failed[%s]", type, __codec_v4l2_get_error_string(errno));
                return HAL_CODEC_ERROR_INTERNAL;
        }
 
@@ -609,7 +630,7 @@ static int __codec_v4l2_stream(int device_fd, int type, gboolean onoff)
        }
 
        if (ioctl(device_fd, onoff ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type) < 0) {
-               LOGE("stream %d failed. [t:%d] errno %d", onoff, type, errno);
+               LOGE("stream %d failed. [t:%d] %s", onoff, type, __codec_v4l2_get_error_string(errno));
                return HAL_CODEC_ERROR_INTERNAL;
        }
 
@@ -637,7 +658,7 @@ static int __codec_v4l2_reqbufs(int device_fd, int type, int memory, uint32_t co
        v4l2_reqbuf.count = count;
 
        if (ioctl(device_fd, VIDIOC_REQBUFS, &v4l2_reqbuf) < 0) {
-               LOGE("REQBUFS[count %d] failed. errno %d", count, errno);
+               LOGE("REQBUFS[count %d] failed[%s]", count, __codec_v4l2_get_error_string(errno));
                return HAL_CODEC_ERROR_INTERNAL;
        }
 
@@ -683,18 +704,24 @@ static int __codec_v4l2_qbuf(int device_fd,
        if (codec_config->memory == V4L2_MEMORY_DMABUF) {
                if (codec_memory->num_fd == 0 ||
                        codec_memory->num_fd > HAL_CODEC_BUFFER_PLANE_MAX) {
-                       LOGE("invalid num_fd[%u]", codec_memory->num_fd);
+                       LOGE("[%s] QBUF invalid num_fd[%u]",
+                               BUFFER_CONTROL_TYPE_STRING(buffer_control->type),
+                               codec_memory->num_fd);
                        return HAL_CODEC_ERROR_INVALID_PARAMETER;
                }
 
                if (V4L2_TYPE_IS_MULTIPLANAR(codec_config->buf_type)) {
                        for (i = 0 ; i < codec_memory->num_fd ; i++) {
-                               LOGD("plane[%d] fd %d", i, codec_memory->fd[i]);
+                               LOGD("[%s] QBUF plane[%d] fd %d",
+                                       BUFFER_CONTROL_TYPE_STRING(buffer_control->type),
+                                       i, codec_memory->fd[i]);
                                v4l2_buf.m.planes[i].m.fd = codec_memory->fd[i];
                        }
                } else {
                        if (codec_memory->num_fd != 1)
-                               LOGW("invalid num_fd[%u]", codec_memory->num_fd);
+                               LOGW("[%s] QBUF invalid num_fd[%u]",
+                                       BUFFER_CONTROL_TYPE_STRING(buffer_control->type),
+                                       codec_memory->num_fd);
 
                        v4l2_buf.m.fd = codec_memory->fd[0];
                }
@@ -703,21 +730,39 @@ static int __codec_v4l2_qbuf(int device_fd,
        } else {
                /* V4L2_MEMORY_MMAP */
                v4l2_buf.length = 1;
+               if (V4L2_TYPE_IS_MULTIPLANAR(codec_config->buf_type)) {
+                       v4l2_buf.m.planes[0].bytesused = codec_buffer->planes.plane[0].bytesused;
+
+                       LOGD("[%s] QBUF multiplanar: bytesused[%u]",
+                               BUFFER_CONTROL_TYPE_STRING(buffer_control->type),
+                               v4l2_buf.m.planes[0].bytesused);
+               } else {
+                       v4l2_buf.bytesused = codec_buffer->planes.plane[0].bytesused;
+
+                       LOGD("[%s] QBUF singleplanar: bytesused[%u]",
+                               BUFFER_CONTROL_TYPE_STRING(buffer_control->type),
+                               v4l2_buf.bytesused);
+               }
        }
 
-       if (codec_buffer->meta.timestamp > 0) {
+       if (buffer_control->type == CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT) {
                TIMESTAMP_TO_TIMEVAL(codec_buffer->meta.timestamp, v4l2_buf.timestamp);
-               LOGD("timeval sec:%lu, usec:%lu", v4l2_buf.timestamp.tv_sec, v4l2_buf.timestamp.tv_usec);
+
+               LOGD("[INPUT] QBUF timestamp: [%"TIMESTAMP_FORMAT"] -> sec[%lu], usec[%lu]",
+                       TIMESTAMP_ARGS(codec_buffer->meta.timestamp),
+                       v4l2_buf.timestamp.tv_sec, v4l2_buf.timestamp.tv_usec);
        }
 
        if (ioctl(device_fd, VIDIOC_QBUF, &v4l2_buf) < 0) {
-               LOGE("QBUF failed.  control[%d] buffer[%d], errno[%d]",
-               buffer_control->type, codec_buffer->index, errno);
+               LOGE("[%s] QBUF failed: buffer[%d] %s",
+                       BUFFER_CONTROL_TYPE_STRING(buffer_control->type),
+                       codec_buffer->index, __codec_v4l2_get_error_string(errno));
                return HAL_CODEC_ERROR_INTERNAL;
        }
 
-       LOGD("QBUF done - control[%d] buffer[%d]",
-               buffer_control->type, codec_buffer->index);
+       LOGD("[%s] QBUF done: buffer[%d]",
+               BUFFER_CONTROL_TYPE_STRING(buffer_control->type),
+               codec_buffer->index);
 
        return HAL_CODEC_ERROR_NONE;
 }
@@ -752,16 +797,35 @@ static int __codec_v4l2_dqbuf(int device_fd,
 
        ret = ioctl(device_fd, VIDIOC_DQBUF, &v4l2_buf);
        if (ret < 0) {
-               LOGE("control[%d] DQBUF failed. [t: %d, m: %d] errno %d",
-                       buffer_control->type, codec_config->buf_type, codec_config->memory, errno);
+               LOGE("[%s] DQBUF failed. [t: %d, m: %d] %s",
+                       BUFFER_CONTROL_TYPE_STRING(buffer_control->type),
+                       codec_config->buf_type, codec_config->memory,
+                       __codec_v4l2_get_error_string(errno));
                return HAL_CODEC_ERROR_DEVICE_READ;
        }
 
-       LOGD("control[%d] DQBUF[i:%d], bytesused[%u], length[%u]",
-               buffer_control->type, v4l2_buf.index, v4l2_buf.bytesused, v4l2_buf.length);
+       if (V4L2_TYPE_IS_MULTIPLANAR(codec_config->buf_type)) {
+               LOGD("[%s] DQBUF done: index[%d], length[%u], bytesused[%u,%u]",
+                       BUFFER_CONTROL_TYPE_STRING(buffer_control->type),
+                       v4l2_buf.index, v4l2_buf.length,
+                       v4l2_buf.m.planes[0].bytesused,
+                       v4l2_buf.m.planes[1].bytesused);
+       } else {
+               LOGD("[%s] DQBUF done: index[%d], bytesused[%u], length[%u]",
+                       BUFFER_CONTROL_TYPE_STRING(buffer_control->type),
+                       v4l2_buf.index, v4l2_buf.bytesused, v4l2_buf.length);
+       }
 
        *out_buffer = &buffer_control->buffers.buffer[v4l2_buf.index];
 
+       if (buffer_control->type == CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT) {
+               TIMEVAL_TO_TIMESTAMP(v4l2_buf.timestamp, (*out_buffer)->meta.timestamp);
+
+               LOGD("[OUTPUT] DQBUF timestamp: sec[%lu], usec[%lu] -> [%"TIMESTAMP_FORMAT"]",
+                       v4l2_buf.timestamp.tv_sec, v4l2_buf.timestamp.tv_usec,
+                       TIMESTAMP_ARGS((*out_buffer)->meta.timestamp));
+       }
+
        return HAL_CODEC_ERROR_NONE;
 }
 
@@ -900,13 +964,13 @@ static int __codec_v4l2_stop_stream(codec_hal_handle_s *handle)
 
                for (k = 0 ; k < codec_memory->num_fd ; k++) {
                        if (codec_memory->fd[k] > CODEC_HAL_INITIAL_FD) {
-                               LOGI("[output][%d][%d] close fd[%d]", i, k, codec_memory->fd[k]);
+                               LOGI("[OUTPUT][%d][%d] close fd[%d]", i, k, codec_memory->fd[k]);
                                close(codec_memory->fd[k]);
                                codec_memory->fd[k] = CODEC_HAL_INITIAL_FD;
                        }
 
                        if (buffer_control->buffers.bo[i][k]) {
-                               LOGI("[output][%d][%d] unref bo[%p]", i, k, buffer_control->buffers.bo[i][k]);
+                               LOGI("[OUTPUT][%d][%d] unref bo[%p]", i, k, buffer_control->buffers.bo[i][k]);
                                tbm_bo_unref(buffer_control->buffers.bo[i][k]);
                                buffer_control->buffers.bo[i][k] = NULL;
                        }
@@ -916,7 +980,7 @@ static int __codec_v4l2_stop_stream(codec_hal_handle_s *handle)
        ret = __codec_v4l2_reqbufs(handle->device_fd,
                buffer_control->config.buf_type, V4L2_MEMORY_MMAP, 0, NULL);
        if (ret != HAL_CODEC_ERROR_NONE) {
-               LOGE("[output] REQBUFS 0 failed[0x%x]", ret);
+               LOGE("[OUTPUT] REQBUFS 0 failed[0x%x]", ret);
                return ret;
        }
 
@@ -927,12 +991,12 @@ static int __codec_v4l2_stop_stream(codec_hal_handle_s *handle)
                codec_buffer = &buffer_control->buffers.buffer[i];
 
                if (!codec_buffer->planes.plane[0].data || codec_buffer->size == 0) {
-                       LOGW("[input][%d] invalid data[%p], size[%u]",
+                       LOGW("[INPUT][%d] invalid data[%p], size[%u]",
                                i, codec_buffer->planes.plane[0].data, codec_buffer->size);
                        continue;
                }
 
-               LOGI("[input][%d] munmap[%p], size[%u]",
+               LOGI("[INPUT][%d] munmap[%p], size[%u]",
                        i, codec_buffer->planes.plane[0].data, codec_buffer->size);
 
                munmap(codec_buffer->planes.plane[0].data, codec_buffer->size);
@@ -944,7 +1008,7 @@ static int __codec_v4l2_stop_stream(codec_hal_handle_s *handle)
        ret = __codec_v4l2_reqbufs(handle->device_fd,
                buffer_control->config.buf_type, V4L2_MEMORY_MMAP, 0, NULL);
        if (ret != HAL_CODEC_ERROR_NONE) {
-               LOGE("[input] REQBUFS 0 failed[0x%x]", ret);
+               LOGE("[INPUT] REQBUFS 0 failed[0x%x]", ret);
                return ret;
        }
 
@@ -1021,7 +1085,8 @@ static int __codec_v4l2_start_stream(codec_hal_handle_s *handle,
                        v4l2_buf.length = num_planes;
 
                        if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
-                               LOGE("type[%d] buffer[i:%d] query buf failed (errno %d)", type, i, errno);
+                               LOGE("type[%d] buffer[i:%d] query buf failed[%s]",
+                                       type, i, __codec_v4l2_get_error_string(errno));
                                ret = HAL_CODEC_ERROR_INTERNAL;
                                goto _START_STREAM_FAILED;
                        }
@@ -1036,8 +1101,9 @@ static int __codec_v4l2_start_stream(codec_hal_handle_s *handle,
                                        (off_t)v4l2_planes[k].m.mem_offset);
 
                                if (codec_buffer->planes.plane[k].data == MAP_FAILED) {
-                                       LOGE("type[%d] buffer[i:%d][plane:%d] mmap failed, size[%d], offset[%u] for mmap (errno %d)",
-                                               type, i, k, v4l2_planes[k].length, v4l2_planes[k].m.mem_offset, errno);
+                                       LOGE("type[%d] buffer[i:%d][plane:%d] mmap failed, size[%d], offset[%u] for mmap[%s]",
+                                               type, i, k, v4l2_planes[k].length, v4l2_planes[k].m.mem_offset,
+                                               __codec_v4l2_get_error_string(errno));
                                        ret = HAL_CODEC_ERROR_INTERNAL;
                                        goto _START_STREAM_FAILED;
                                }
@@ -1104,8 +1170,8 @@ static int __codec_v4l2_start_stream(codec_hal_handle_s *handle,
                                buffer_control, codec_buffer);
 
                        if (ret != HAL_CODEC_ERROR_NONE) {
-                               LOGE("[output][%d] qbuf failed (fd %d, errno %d)",
-                                       i, codec_memory->fd[0], errno);
+                               LOGE("[output][%d] qbuf failed[fd:%d] %s",
+                                       i, codec_memory->fd[0], __codec_v4l2_get_error_string(errno));
                                goto _START_STREAM_FAILED;
                        }
                }
@@ -1509,9 +1575,7 @@ int codec_v4l2_configure(void *codec_handle, int width, int height,
        /* device open */
        device_fd = open(node_path, O_RDWR);
        if (device_fd < 0) {
-               char error_string[ERROR_STRING_LENGTH] = {'\0',};
-               strerror_r(errno, error_string, ERROR_STRING_LENGTH);
-               LOGE("[%s] open failed [%s]", node_path, error_string);
+               LOGE("[%s] open failed [%s]", node_path, __codec_v4l2_get_error_string(errno));
                return HAL_CODEC_ERROR_DEVICE_OPEN;
        }
 
@@ -1588,7 +1652,6 @@ static int __codec_v4l2_poll(codec_hal_handle_s *handle, short events, int timeo
 {
        int ret = 0;
        struct pollfd poll_fd;
-       char error_string[ERROR_STRING_LENGTH] = {'\0',};
 
        if (!handle) {
                LOGE("NULL handle");
@@ -1603,8 +1666,7 @@ static int __codec_v4l2_poll(codec_hal_handle_s *handle, short events, int timeo
        ret = poll(&poll_fd, 1, timeout_ms);
 
        if (ret < 0) {
-               strerror_r(errno, error_string, ERROR_STRING_LENGTH);
-               LOGE("poll[events 0x%x] failed[%s]", events, error_string);
+               LOGE("poll[events 0x%x] failed[%s]", events, __codec_v4l2_get_error_string(errno));
        } else if (ret == 0) {
                LOGW("poll[events 0x%x] time out for %d ms", events, timeout_ms);
        } else {
@@ -1652,9 +1714,7 @@ static gpointer __codec_v4l2_buffer_handler_func(gpointer data)
                        break;
 
                if (revents & POLLERR) {
-                       char error_string[ERROR_STRING_LENGTH] = {'\0',};
-                       strerror_r(errno, error_string, ERROR_STRING_LENGTH);
-                       LOGW("POLLERR[%s]", error_string);
+                       LOGW("POLLERR[%s]", __codec_v4l2_get_error_string(errno));
 
                        if (handle->is_stopping) {
                                LOGW("now stopping... stop buffer handler");
@@ -1899,6 +1959,8 @@ int codec_v4l2_decode(void *codec_handle, hal_codec_buffer_s *buffer)
        }
 
        memcpy(idle_buffer->planes.plane[0].data, buffer->planes.plane[0].data, buffer->planes.plane[0].bytesused);
+       idle_buffer->planes.plane[0].bytesused = buffer->planes.plane[0].bytesused;
+
        memcpy(&idle_buffer->meta, &buffer->meta, sizeof(hal_codec_meta_s));
 
        ret = __codec_v4l2_qbuf(handle->device_fd,
@@ -1944,11 +2006,15 @@ int codec_v4l2_get_state(void *codec_handle, hal_codec_state_e *state)
 {
        codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
 
-       if (!handle) {
-               LOGE("NULL handle");
+       if (!handle || !state) {
+               LOGE("NULL param[%p,%p]", handle, state);
                return HAL_CODEC_ERROR_INVALID_PARAMETER;
        }
 
+       *state = handle->state;
+
+       LOGD("state[%d]", *state);
+
        return HAL_CODEC_ERROR_NONE;
 }
 
@@ -1966,7 +2032,7 @@ static int __codec_v4l2_set_command(codec_hal_handle_s *handle, int64_t command,
 
        set_value = *(int *)value;
 
-       if (handle->state < HAL_CODEC_STATE_OPENED) {
+       if (handle->state < HAL_CODEC_STATE_CONFIGURED) {
                LOGE("invalid state %d", handle->state);
                return HAL_CODEC_ERROR_INVALID_STATE;
        }
@@ -1988,7 +2054,7 @@ static int __codec_v4l2_set_command(codec_hal_handle_s *handle, int64_t command,
                switch (errno) {
                case EACCES:
                case EPERM:
-                       LOGE("Permission denied %d", errno);
+                       LOGE("Permission denied[%s]", __codec_v4l2_get_error_string(errno));
                        return HAL_CODEC_ERROR_PERMISSION_DENIED;
                case EINVAL:
                        LOGE("Invalid argument");
@@ -2000,7 +2066,7 @@ static int __codec_v4l2_set_command(codec_hal_handle_s *handle, int64_t command,
                        LOGE("Not supported");
                        return HAL_CODEC_ERROR_NOT_SUPPORTED;
                default:
-                       LOGE("Unknown errro %d", errno);
+                       LOGE("Unknown errno[%s]", __codec_v4l2_get_error_string(errno));
                        return HAL_CODEC_ERROR_INTERNAL;
                }
        }
@@ -2038,14 +2104,14 @@ int codec_v4l2_get_command(void *codec_handle, hal_codec_command_e command, void
 
        locker = g_mutex_locker_new(&handle->lock);
 
-       LOGI("command[0x%x]", command);
+       LOGI("command[0x%"PRIx64"]", command);
 
        switch (command) {
        case HAL_CODEC_COMMAND_BITRATE:
                cid = V4L2_CID_MPEG_VIDEO_BITRATE;
                break;
        default:
-               LOGE("Not supported command[0x%x]", command);
+               LOGE("Not supported command[0x%"PRIx64"]", command);
                return HAL_CODEC_ERROR_NOT_SUPPORTED;
        }
 
@@ -2054,7 +2120,7 @@ int codec_v4l2_get_command(void *codec_handle, hal_codec_command_e command, void
                switch (errno) {
                case EACCES:
                case EPERM:
-                       LOGE("Permission denied %d", errno);
+                       LOGE("Permission denied[%s]", __codec_v4l2_get_error_string(errno));
                        ret = HAL_CODEC_ERROR_PERMISSION_DENIED;
                        break;
                case EINVAL:
@@ -2070,7 +2136,7 @@ int codec_v4l2_get_command(void *codec_handle, hal_codec_command_e command, void
                        ret = HAL_CODEC_ERROR_NOT_SUPPORTED;
                        break;
                default:
-                       LOGE("Unknown errro %d", errno);
+                       LOGE("Unknown errro[%s]", __codec_v4l2_get_error_string(errno));
                        ret = HAL_CODEC_ERROR_INTERNAL;
                        break;
                }
@@ -2128,7 +2194,7 @@ int codec_v4l2_set_batch_command(void *codec_handle, hal_codec_batch_command_con
 
                ret = __codec_v4l2_set_command(handle, set_table[i].command, set_table[i].value);
                if (ret != HAL_CODEC_ERROR_NONE) {
-                       LOGE("failed command 0x%x, ret 0x%x", set_table[i].command, ret);
+                       LOGE("failed command 0x%"PRIx64", ret 0x%x", set_table[i].command, ret);
                        break;
                }
        }