From: Jeongmo Yang Date: Fri, 7 Feb 2025 08:41:15 +0000 (+0900) Subject: Update buffer handling X-Git-Tag: accepted/tizen/unified/20250610.081745~10 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=73d9446e7e6234207d80fbe1ceda8296d0d9b4b3;p=platform%2Fhal%2Fbackend%2Fcodec-v4l2.git Update buffer handling Signed-off-by: Jeongmo Yang --- diff --git a/src/hal_backend_codec_v4l2.c b/src/hal_backend_codec_v4l2.c index 2fa1139..d0ae4e4 100644 --- a/src/hal_backend_codec_v4l2.c +++ b/src/hal_backend_codec_v4l2.c @@ -490,11 +490,13 @@ static void __codec_v4l2_message_send(codec_hal_handle_s *handle, hal_codec_mess switch (type) { case HAL_CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED: message->buffer = (hal_codec_buffer_s *)value; - LOGD("InputBufferUsed : buffer[i:%d] %p", message->buffer->index, message->buffer); + LOGD("InputBufferUsed[message:%p]: buffer[i:%d,HAL:%p]", + message, message->buffer->index, message->buffer); break; case HAL_CODEC_MESSAGE_TYPE_OUTPUT_BUFFER: message->buffer = (hal_codec_buffer_s *)value; - LOGD("OutputBuffer : buffer[i:%d] %p", message->buffer->index, message->buffer); + LOGD("OutputBuffer[message:%p]: buffer[i:%d,HAL:%p]", + message, message->buffer->index, message->buffer); break; case HAL_CODEC_MESSAGE_TYPE_RESOLUTION_CHANGED: break; @@ -509,6 +511,9 @@ static void __codec_v4l2_message_send(codec_hal_handle_s *handle, hal_codec_mess } g_queue_push_tail(handle->msg_list, message); + + LOGD("message length[%u]", g_queue_get_length(handle->msg_list)); + g_cond_broadcast(&handle->msg_cb_cond); } @@ -721,12 +726,16 @@ static int __codec_v4l2_qbuf(int device_fd, struct v4l2_buffer v4l2_buf; struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; + g_autoptr(GMutexLocker) locker = NULL; + if (device_fd < 0 || !buffer_control || !codec_buffer) { LOGE("invalid device fd[%d]/buffer control[%p]/codec buffer[%p]", device_fd, buffer_control, codec_buffer); return HAL_CODEC_ERROR_INVALID_PARAMETER; } + locker = g_mutex_locker_new(&buffer_control->lock); + codec_config = &buffer_control->config; codec_memory = &codec_buffer->memory; @@ -797,9 +806,15 @@ static int __codec_v4l2_qbuf(int device_fd, return HAL_CODEC_ERROR_INTERNAL; } - LOGD("[%s] QBUF done: buffer[%d]", + buffer_control->buffers.is_queued[codec_buffer->index] = TRUE; + buffer_control->buffers.queued_count++; + + LOGD("[%s] QBUF done: buffer[%d], queued_count[%d]", BUFFER_CONTROL_TYPE_STRING(buffer_control->type), - codec_buffer->index); + codec_buffer->index, buffer_control->buffers.queued_count); + + if (buffer_control->type == CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT) + g_cond_broadcast(&buffer_control->cond); return HAL_CODEC_ERROR_NONE; } @@ -816,12 +831,16 @@ static int __codec_v4l2_dqbuf(int device_fd, struct v4l2_buffer v4l2_buf; struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; + g_autoptr(GMutexLocker) locker = NULL; + if (device_fd < 0 || !buffer_control || !out_buffer) { LOGE("invalid device fd[%d]/buffer control[%p]/out_buffer[%p]", device_fd, buffer_control, out_buffer); return HAL_CODEC_ERROR_INVALID_PARAMETER; } + locker = g_mutex_locker_new(&buffer_control->lock); + codec_config = &buffer_control->config; memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer)); @@ -841,16 +860,26 @@ static int __codec_v4l2_dqbuf(int device_fd, return HAL_CODEC_ERROR_DEVICE_READ; } + buffer_control->buffers.is_queued[v4l2_buf.index] = FALSE; + buffer_control->buffers.queued_count--; + if (buffer_control->buffers.queued_count < 0) { + LOGW("[%s] invalid queued_count[%d], check it.", + BUFFER_CONTROL_TYPE_STRING(buffer_control->type), + buffer_control->buffers.queued_count); + } + if (V4L2_TYPE_IS_MULTIPLANAR(codec_config->buf_type)) { - LOGD("[%s] DQBUF done: index[%d], length[%u], bytesused[%u,%u]", + LOGD("[%s] DQBUF done: index[%d], length[%u], bytesused[0:%u,1:%u], queued_count[%d]", 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); + v4l2_buf.m.planes[1].bytesused, + buffer_control->buffers.queued_count); } else { - LOGD("[%s] DQBUF done: index[%d], bytesused[%u], length[%u]", + LOGD("[%s] DQBUF done: index[%d], bytesused[%u], length[%u], queued_count[%d]", BUFFER_CONTROL_TYPE_STRING(buffer_control->type), - v4l2_buf.index, v4l2_buf.bytesused, v4l2_buf.length); + v4l2_buf.index, v4l2_buf.bytesused, v4l2_buf.length, + buffer_control->buffers.queued_count); } *out_buffer = &buffer_control->buffers.buffer[v4l2_buf.index]; @@ -978,8 +1007,10 @@ static int __codec_v4l2_stop_stream(codec_hal_handle_s *handle) int i = 0; int k = 0; int ret = HAL_CODEC_ERROR_NONE; + gint64 end_time = 0; hal_codec_memory_s *codec_memory = NULL; codec_hal_buffer_control_s *buffer_control = NULL; + codec_hal_buffers_s *buffers = NULL; hal_codec_buffer_s *codec_buffer = NULL; if (!handle) { @@ -999,12 +1030,34 @@ static int __codec_v4l2_stop_stream(codec_hal_handle_s *handle) } } - /* decoder */ + /* wait for output buffer */ + buffer_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT]; + + g_mutex_lock(&buffer_control->lock); + + while (buffer_control->buffers.queued_count < buffer_control->buffers.count) { + LOGW("wait for output buffer[queued:%d vs count:%u]", + buffer_control->buffers.queued_count, buffer_control->buffers.count); + + end_time = g_get_monotonic_time() + G_TIME_SPAN_SECOND; + + if (!g_cond_wait_until(&buffer_control->cond, &buffer_control->lock, end_time)) { + LOGE("timeout: wait for output buffer"); + break; + } + + LOGW("signal received, check it again[queued:%d,count:%u]", + buffer_control->buffers.queued_count, buffer_control->buffers.count); + } + + g_mutex_unlock(&buffer_control->lock); + /* release output buffer */ buffer_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT]; + buffers = &buffer_control->buffers; - for (i = 0 ; i < buffer_control->buffers.count ; i++) { - codec_buffer = &buffer_control->buffers.buffer[i]; + for (i = 0 ; i < buffers->count ; i++) { + codec_buffer = &buffers->buffer[i]; codec_memory = &codec_buffer->memory; for (k = 0 ; k < codec_memory->num_fd ; k++) { @@ -1014,10 +1067,10 @@ static int __codec_v4l2_stop_stream(codec_hal_handle_s *handle) 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]); - tbm_bo_unref(buffer_control->buffers.bo[i][k]); - buffer_control->buffers.bo[i][k] = NULL; + if (buffers->bo[i][k]) { + LOGI("[OUTPUT][%d][%d] unref bo[%p]", i, k, buffers->bo[i][k]); + tbm_bo_unref(buffers->bo[i][k]); + buffers->bo[i][k] = NULL; } } } @@ -1032,8 +1085,8 @@ static int __codec_v4l2_stop_stream(codec_hal_handle_s *handle) /* release input buffer */ buffer_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT]; - for (i = 0 ; i < buffer_control->buffers.count ; i++) { - codec_buffer = &buffer_control->buffers.buffer[i]; + for (i = 0 ; i < buffers->count ; i++) { + codec_buffer = &buffers->buffer[i]; if (!codec_buffer->planes.plane[0].data || codec_buffer->size == 0) { LOGW("[INPUT][%d] invalid data[%p], size[%u]", @@ -1075,6 +1128,7 @@ static int __codec_v4l2_start_stream(codec_hal_handle_s *handle, hal_codec_buffer_s *codec_buffer = NULL; codec_hal_config_s *codec_config = NULL; codec_hal_buffer_control_type_e type; + codec_hal_buffers_s *buffers = NULL; struct v4l2_buffer v4l2_buf; struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX]; @@ -1088,6 +1142,7 @@ static int __codec_v4l2_start_stream(codec_hal_handle_s *handle, } type = buffer_control->type; + buffers = &buffer_control->buffers; codec_config = &buffer_control->config; LOGI("type[%d] buf_type[%d], memory[%d], plane num[%u], buffer count[%u]", @@ -1096,19 +1151,22 @@ static int __codec_v4l2_start_stream(codec_hal_handle_s *handle, ret = __codec_v4l2_reqbufs(handle->device_fd, codec_config->buf_type, codec_config->memory, - buffer_count, &buffer_control->buffers.count); + buffer_count, &buffers->count); if (ret != HAL_CODEC_ERROR_NONE) { LOGE("type[%d] REQBUFS failed [0x%x]", type, ret); return ret; } LOGI("type[%d] buffer count - request[%u] -> result[%u]", - type, buffer_count, buffer_control->buffers.count); + type, buffer_count, buffers->count); num_planes = codec_config->num_planes; - for (i = 0 ; i < buffer_control->buffers.count ; i++) { - codec_buffer = &buffer_control->buffers.buffer[i]; + buffers->queued_count = 0; + + for (i = 0 ; i < buffers->count ; i++) { + + codec_buffer = &buffers->buffer[i]; codec_buffer->index = i; codec_buffer->meta.format = codec_config->format; @@ -1178,7 +1236,7 @@ static int __codec_v4l2_start_stream(codec_hal_handle_s *handle, goto _START_STREAM_FAILED; } - buffer_control->buffers.bo[i][0] = new_bo; + buffers->bo[i][0] = new_bo; codec_memory->num_fd = 1; codec_buffer->planes.plane[0].data = bo_handle.ptr; @@ -1207,7 +1265,7 @@ static int __codec_v4l2_start_stream(codec_hal_handle_s *handle, if (buffer_control->type == CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT) { g_mutex_lock(&buffer_control->lock); LOGI("[input] push idle buffer[%d]", i); - g_queue_push_tail(buffer_control->buffers.idle_buffers, GINT_TO_POINTER(i)); + g_queue_push_tail(buffers->idle_buffers, GINT_TO_POINTER(i)); g_mutex_unlock(&buffer_control->lock); } else { /* CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT */ @@ -1333,7 +1391,7 @@ static void *__codec_v4l2_message_handler_func(gpointer data) if (g_queue_is_empty(handle->msg_list)) { LOGD("wait for message"); g_cond_wait(&handle->msg_cb_cond, &handle->msg_cb_lock); - LOGD("message signal received"); + LOGD("message[length:%u] signal received", g_queue_get_length(handle->msg_list)); } if (!handle->msg_cb_run) { @@ -1347,10 +1405,33 @@ static void *__codec_v4l2_message_handler_func(gpointer data) continue; } + 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); + break; + case HAL_CODEC_MESSAGE_TYPE_OUTPUT_BUFFER: + LOGD("OUTPUT_BUFFER[message:%p]: buffer[index:%d,HAL:%p]", + message, 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); + break; + default: + break; + } + g_mutex_unlock(&handle->msg_cb_lock); - if (handle->msg_cb) { - LOGD("call message callback - type[%d]", message->type); + if (!handle->msg_cb) { + LOGW("NULL callback for message"); + + if (message->type == HAL_CODEC_MESSAGE_TYPE_OUTPUT_BUFFER) { + LOGI("release output buffer[index:%d]", message->buffer->index); + codec_v4l2_release_output_buffer(handle, message->buffer->index); + } + } else { handle->msg_cb(message, handle->msg_cb_data); } @@ -1695,13 +1776,13 @@ int codec_v4l2_release(void *codec_handle) } -static int __codec_v4l2_poll(codec_hal_handle_s *handle, short events, int timeout_ms, short *revents) +static int __codec_v4l2_poll(codec_hal_handle_s *handle, short events, int timeout_ms, short *revents, int *poll_errno) { int ret = 0; struct pollfd poll_fd; - if (!handle) { - LOGE("NULL handle"); + if (!handle || !revents || !poll_errno) { + LOGE("NULL param[%p,%p,%p]", handle, revents, poll_errno); return -1; } @@ -1713,13 +1794,18 @@ static int __codec_v4l2_poll(codec_hal_handle_s *handle, short events, int timeo ret = poll(&poll_fd, 1, timeout_ms); if (ret < 0) { - LOGE("poll[events 0x%x] failed[%s]", events, __codec_v4l2_get_error_string(errno)); + *poll_errno = errno; + LOGE("poll[events 0x%x] failed[errno:%d,%s]", + events, *poll_errno, __codec_v4l2_get_error_string(*poll_errno)); } else if (ret == 0) { LOGW("poll[events 0x%x] time out for %d ms", events, timeout_ms); } else { LOGD("poll[events 0x%x -> revents 0x%x] success[%d]", events, poll_fd.revents, ret); - if (revents) - *revents = poll_fd.revents; + + if (poll_fd.revents & POLLERR) + *poll_errno = errno; + + *revents = poll_fd.revents; } return ret; @@ -1729,6 +1815,7 @@ static int __codec_v4l2_poll(codec_hal_handle_s *handle, short events, int timeo static gpointer __codec_v4l2_buffer_handler_func(gpointer data) { int ret = 0; + int poll_errno = 0; int error_count = 0; gboolean run_loop = TRUE; @@ -1753,7 +1840,9 @@ static gpointer __codec_v4l2_buffer_handler_func(gpointer data) /* exit thread with some conditions */ ////////////////////////////////////// - ret = __codec_v4l2_poll(handle, (POLLIN | POLLOUT | POLLPRI), OUTPUT_POLL_TIMEOUT_MS, &revents); + poll_errno = 0; + + ret = __codec_v4l2_poll(handle, (POLLIN | POLLOUT | POLLPRI), OUTPUT_POLL_TIMEOUT_MS, &revents, &poll_errno); if (ret == 0) continue; @@ -1762,19 +1851,29 @@ static gpointer __codec_v4l2_buffer_handler_func(gpointer data) break; if (revents & POLLERR) { - LOGW("POLLERR[%s]", __codec_v4l2_get_error_string(errno)); + LOGE("POLLERR[errno:%d,%s]", poll_errno, __codec_v4l2_get_error_string(poll_errno)); + + g_mutex_lock(&output_control->lock); + + if (output_control->buffers.queued_count == 0) { + LOGW("wait for dequeued output buffer"); + g_cond_wait(&output_control->cond, &output_control->lock); + LOGW("signal received"); + } + + g_mutex_unlock(&output_control->lock); if (handle->is_stopping) { LOGW("now stopping... stop buffer handler"); break; + } + + if (error_count++ < POLL_ERROR_TRY_COUNT_MAX) { + LOGW("try[count:%d] poll after %d ms", error_count, POLL_ERROR_TRY_SLEEP_US); + usleep(POLL_ERROR_TRY_SLEEP_US); + continue; } else { - if (error_count++ < POLL_ERROR_TRY_COUNT_MAX) { - LOGW("try[count:%d] poll after %d ms", error_count, POLL_ERROR_TRY_SLEEP_US); - usleep(POLL_ERROR_TRY_SLEEP_US); - continue; - } else { - LOGE("error count[%d][max:%d] exceeded", error_count, POLL_ERROR_TRY_COUNT_MAX); - } + LOGE("error count[%d][max:%d] exceeded", error_count, POLL_ERROR_TRY_COUNT_MAX); } } @@ -1899,9 +1998,13 @@ int codec_v4l2_stop(void *codec_handle) goto _STOP_DONE; } - LOGI("join output thread"); + LOGI("join buffer thread"); if (handle->buffer_handler) { + g_mutex_lock(&handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT].lock); + g_cond_broadcast(&handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT].cond); + g_mutex_unlock(&handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT].lock); + g_thread_join(handle->buffer_handler); handle->buffer_handler = NULL; } @@ -2062,7 +2165,6 @@ int codec_v4l2_release_output_buffer(void *codec_handle, int buffer_index) int ret = HAL_CODEC_ERROR_NONE; codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle; codec_hal_buffer_control_s *buffer_control = NULL; - //g_autoptr(GMutexLocker) locker = NULL; if (!handle) { LOGE("NULL handle"); @@ -2071,8 +2173,6 @@ int codec_v4l2_release_output_buffer(void *codec_handle, int buffer_index) buffer_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT]; - //locker = g_mutex_locker_new(&handle->lock); - ret = __codec_v4l2_qbuf(handle->device_fd, buffer_control, &buffer_control->buffers.buffer[buffer_index]); diff --git a/src/hal_backend_codec_v4l2_private.h b/src/hal_backend_codec_v4l2_private.h index c27867b..d9e2218 100644 --- a/src/hal_backend_codec_v4l2_private.h +++ b/src/hal_backend_codec_v4l2_private.h @@ -64,6 +64,8 @@ typedef struct { uint32_t count; hal_codec_buffer_s buffer[BUFFER_MAX]; tbm_bo bo[BUFFER_MAX][HAL_CODEC_BUFFER_PLANE_MAX]; + gboolean is_queued[BUFFER_MAX]; + int queued_count; GQueue *idle_buffers; } codec_hal_buffers_s;