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;
}
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);
}
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;
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;
}
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));
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];
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) {
}
}
- /* 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++) {
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;
}
}
}
/* 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]",
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];
}
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]",
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;
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;
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 */
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) {
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);
}
}
-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;
}
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;
static gpointer __codec_v4l2_buffer_handler_func(gpointer data)
{
int ret = 0;
+ int poll_errno = 0;
int error_count = 0;
gboolean run_loop = TRUE;
/* 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;
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);
}
}
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;
}
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");
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]);