(fourcc >> 16) & 0xff,\
(fourcc >> 24) & 0xff
+#define DEVICE_TYPE_MAX (CODEC_TYPE_ENCODER + 1)
#define DEVICE_NODE_PATH_LENGTH_MAX 32
#define DEVICE_MAX 8
#define DEVICE_FORMAT_MAX 16
/* global variables */
static codec_v4l2_device_list_s *g_codec_device_list;
+static char *g_decoder_type_string[DEVICE_TYPE_MAX] = {
+ [CODEC_TYPE_DECODER] = "DECODER",
+ [CODEC_TYPE_ENCODER] = "ENCODER"
+};
/* local functions */
*out_buf_type = format_list->buf_type;
*path = codec_device->node_path;
- LOGI("found node path[%s], buf_type[in:%d, out:%d] for format[in:%d, out:%d]",
+ LOGI("found node path[%s], buf_type[in:%d, out:%d] for format[in:0x%x, out:0x%x]",
*path, *in_buf_type, *out_buf_type, in_format, out_format);
return CODEC_ERROR_NONE;
}
-static int __codec_v4l2_s_fmt(int device_fd,
- codec_format_e format, enum v4l2_buf_type buf_type,
+static int __codec_v4l2_s_fmt(codec_buffer_control_s *buffer_control,
+ int device_fd, codec_format_e format, enum v4l2_buf_type buf_type,
int width, int height)
{
+ int i = 0;
uint32_t fourcc = 0;
uint32_t plane_num = 0;
struct v4l2_format v4l2_fmt;
+ codec_buffer_s *codec_buffer = NULL;
+
+ if (!buffer_control) {
+ LOGE("NULL buffer control");
+ return CODEC_ERROR_INVALID_PARAMETER;
+ }
memset(&v4l2_fmt, 0x0, sizeof(struct v4l2_format));
- LOGI("S_FMT : format[%d], buf_type[%d], resolution[%dx%d]",
+ LOGI("S_FMT : format[0x%x], buf_type[%d], resolution[%dx%d]",
format, buf_type, width, height);
if (__codec_get_fourcc_plane_num(format, &fourcc, &plane_num) != CODEC_ERROR_NONE) {
- LOGE("get fourcc failed for format [%d]", format);
+ LOGE("get fourcc failed for format [0x%x]", format);
return CODEC_ERROR_INVALID_PARAMETER;
}
return CODEC_ERROR_INTERNAL;
}
- LOGI("done");
+ codec_buffer = &buffer_control->buffers[0];
+
+ codec_buffer->format = format;
+ codec_buffer->resolution.width = width;
+ codec_buffer->resolution.height = height;
+ codec_buffer->num_planes = plane_num;
+
+ codec_buffer->total_size = 0;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(buf_type)) {
+ for (i = 0 ; i < v4l2_fmt.fmt.pix_mp.num_planes ; i++) {
+ codec_buffer->planes[i].size = v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage;
+ codec_buffer->total_size += codec_buffer->planes[i].size;
+ LOGI(" plane[%d] size [%u]", i, codec_buffer->planes[i].size);
+ }
+ } else {
+ /* TODO: get size of each plane */
+ codec_buffer->total_size = v4l2_fmt.fmt.pix.sizeimage;
+ }
+
+ LOGI("format[0x%x], resolution[%dx%d] buffer size[%u]",
+ format, width, height, codec_buffer->total_size);
return CODEC_ERROR_NONE;
}
v4l2_buf.type = type;
v4l2_buf.memory = memory;
v4l2_buf.m.planes = v4l2_planes;
+ v4l2_buf.length = 1;
if (dmabuf_fd > CODEC_HAL_INITIAL_FD) {
if (V4L2_TYPE_IS_MULTIPLANAR(type))
return CODEC_ERROR_INTERNAL;
}
- LOGI("fourcc ["FOURCC_FORMAT"] -> format [%d]",
+ LOGI("fourcc ["FOURCC_FORMAT"] -> format [0x%x]",
FOURCC_CONVERT(fourcc), *format);
return CODEC_ERROR_NONE;
return CODEC_ERROR_INTERNAL;
}
- LOGD("format [%d] -> fourcc ["FOURCC_FORMAT"]",
+ LOGD("format [0x%x] -> fourcc ["FOURCC_FORMAT"]",
format, FOURCC_CONVERT(*fourcc));
return CODEC_ERROR_NONE;
static int __codec_stop_stream(hal_codec_handle_s *handle)
{
- int ret = CODEC_ERROR_NONE;
-#if 0
int i = 0;
- codec_buffer_s *buffer = NULL;
-#endif
-#ifdef TIZEN_FEATURE_ZERO_COPY_SUPPORT
- codec_tbm_buffer_s *tbm_buffer = NULL;
-#endif
+ int ret = CODEC_ERROR_NONE;
+ codec_memory_s *codec_memory = NULL;
+ codec_buffer_s *codec_buffer = NULL;
+ codec_buffer_control_s *buffer_control = NULL;
if (!handle) {
LOGE("NULL handle");
return CODEC_ERROR_INVALID_PARAMETER;
}
+ LOGI("start");
+
/* stream off */
- ret = __codec_v4l2_stream(handle->device_fd, handle->input_buffer_control.buf_type, FALSE);
- ret = __codec_v4l2_stream(handle->device_fd, handle->output_buffer_control.buf_type, FALSE);
+ ret = __codec_v4l2_stream(handle->device_fd,
+ handle->input_buffer_control.buf_type, FALSE);
+ ret |= __codec_v4l2_stream(handle->device_fd,
+ handle->output_buffer_control.buf_type, FALSE);
+ if (ret != CODEC_ERROR_NONE) {
+ LOGE("STREAMOFF failed[0x%x]", ret);
+ return ret;
+ }
- LOGI("stream off[0x%x]", ret);
+ /* decoder */
+ /* release output buffer */
+ buffer_control = &handle->output_buffer_control;
- /* release buffer */
-#if 0
- for (i = 0 ; i < buffer_count ; i++) {
- buffer = &handle->codec_buffers[i];
+ for (i = 0 ; i < buffer_control->count ; i++) {
+ codec_buffer = &buffer_control->buffers[i];
+ codec_memory = &codec_buffer->memory;
- LOGI("release buffer[%d]", i);
+ if (codec_memory->fd[0] <= CODEC_HAL_INITIAL_FD || !codec_memory->bo[0]) {
+ LOGW("[output][%d] invalid fd[%d], bo[%p]",
+ i, codec_memory->fd[0], codec_memory->bo[0]);
+ continue;
+ }
-#ifdef TIZEN_FEATURE_ZERO_COPY_SUPPORT
- tbm_buffer = &handle->tbm_buffers[i];
+ LOGI("[output][%d] close fd[%d], unref bo[%p]",
+ i, codec_memory->fd[0], codec_memory->bo[0]);
- if (tbm_buffer->dmabuf_fd > CODEC_HAL_INITIAL_FD) {
- LOGI(" close dmabuf fd[%d]", tbm_buffer->dmabuf_fd);
- close(tbm_buffer->dmabuf_fd);
- tbm_buffer->dmabuf_fd = CODEC_HAL_INITIAL_FD;
- }
+ close(codec_memory->fd[0]);
+ tbm_bo_unref(codec_memory->bo[0]);
- if (tbm_buffer->bo) {
- LOGI(" unref tbm bo[%p]", tbm_buffer->bo);
- tbm_bo_unref(tbm_buffer->bo);
- tbm_buffer->bo = NULL;
- }
+ codec_memory->fd[0] = CODEC_HAL_INITIAL_FD;
+ codec_memory->bo[0] = NULL;
+ }
- tbm_buffer->bo_handle.ptr = NULL;
-#endif
+ ret = __codec_v4l2_reqbufs(handle->device_fd,
+ handle->output_buffer_control.buf_type, V4L2_MEMORY_MMAP, 0, NULL);
+ if (ret != CODEC_ERROR_NONE) {
+ LOGE("[output] REQBUFS 0 failed[0x%x]", ret);
+ return ret;
+ }
- if (buffer->planes[0].data) {
-#ifndef TIZEN_FEATURE_ZERO_COPY_SUPPORT
- LOGI(" munmap %p", buffer->planes[0].data);
- munmap(buffer->planes[0].data, buffer->planes[0].size);
-#endif
- buffer->planes[0].data = NULL;
- buffer->planes[0].size = 0;
- } else {
- LOGI(" NULL data [i:%d]", i);
+ /* release input buffer */
+ buffer_control = &handle->input_buffer_control;
+
+ for (i = 0 ; i < buffer_control->count ; i++) {
+ codec_buffer = &buffer_control->buffers[i];
+
+ if (!codec_buffer->planes[0].data || codec_buffer->total_size == 0) {
+ LOGW("[input][%d] invalid data[%p], size[%u]",
+ i, codec_buffer->planes[0].data, codec_buffer->total_size);
+ continue;
}
+
+ LOGI("[input][%d] munmap[%p], size[%u]",
+ i, codec_buffer->planes[0].data, codec_buffer->total_size);
+ munmap(codec_buffer->planes[0].data, codec_buffer->total_size);
+
+ codec_buffer->planes[0].data = NULL;
+ codec_buffer->total_size = 0;
}
-#endif
ret = __codec_v4l2_reqbufs(handle->device_fd,
handle->input_buffer_control.buf_type, V4L2_MEMORY_MMAP, 0, NULL);
+ if (ret != CODEC_ERROR_NONE) {
+ LOGE("[input] REQBUFS 0 failed[0x%x]", ret);
+ return ret;
+ }
- ret = __codec_v4l2_reqbufs(handle->device_fd,
- handle->output_buffer_control.buf_type, V4L2_MEMORY_MMAP, 0, NULL);
-
- LOGI("reqbufs 0 [0x%x]", ret);
+ LOGI("done");
- return ret;
+ return CODEC_ERROR_NONE;
}
static int __codec_start_stream(hal_codec_handle_s *handle,
uint32_t in_buffer_count, uint32_t out_buffer_count)
{
- int ret = CODEC_ERROR_NONE;
-#if 0
int i = 0;
- codec_buffer_s *buffer = NULL;
-#endif
-#ifdef TIZEN_FEATURE_ZERO_COPY_SUPPORT
+ int width = 0;
+ int height = 0;
+ int num_planes = 0;
+ int ret = CODEC_ERROR_NONE;
+ codec_format_e format = CODEC_FORMAT_NV12;
+ codec_memory_s *codec_memory = NULL;
+ codec_buffer_s *codec_buffer = NULL;
+ codec_buffer_control_s *buffer_control = NULL;
uint32_t buffer_size = 0;
- codec_tbm_buffer_s *tbm_buffer = NULL;
-#else
-#if 0
+ uint32_t plane_size[V4L2_PLANES_MAX] = {0, };
+ tbm_bo_handle bo_handle = {NULL, };
struct v4l2_buffer v4l2_buf;
struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];
-#endif
-#endif
if (!handle) {
LOGE("NULL handle");
return CODEC_ERROR_INTERNAL;
}
- /* request buffer */
+ /* input buffer */
+ buffer_control = &handle->input_buffer_control;
+
ret = __codec_v4l2_reqbufs(handle->device_fd,
- handle->input_buffer_control.buf_type, V4L2_MEMORY_MMAP,
- in_buffer_count, &handle->input_buffer_control.count);
+ buffer_control->buf_type, V4L2_MEMORY_MMAP,
+ in_buffer_count, &buffer_control->count);
if (ret != CODEC_ERROR_NONE) {
- LOGE("REQBUFS for input failed [0x%x]", ret);
+ LOGE("[input] REQBUFS failed [0x%x]", ret);
return ret;
}
- LOGI("input buffer count : request %d -> result %d",
- in_buffer_count, handle->input_buffer_control.count);
+ LOGI("[input] buffer count : request %u -> result %u",
+ in_buffer_count, buffer_control->count);
- ret = __codec_v4l2_reqbufs(handle->device_fd,
- handle->output_buffer_control.buf_type, V4L2_MEMORY_MMAP,
- out_buffer_count, &handle->output_buffer_control.count);
- if (ret != CODEC_ERROR_NONE) {
- LOGE("REQBUFS for output failed [0x%x]", ret);
- return ret;
- }
+ format = buffer_control->buffers[0].format;
+ width = buffer_control->buffers[0].resolution.width;
+ height = buffer_control->buffers[0].resolution.height;
+ num_planes = buffer_control->buffers[0].num_planes;
- LOGI("output buffer count : request %d -> result %d",
- out_buffer_count, handle->output_buffer_control.count);
+ for (i = 0 ; i < buffer_control->count ; i++) {
+ codec_buffer = &buffer_control->buffers[i];
-#if 0
- /* alloc and queue buffer */
- for (i = 0 ; i < handle->buffer_count ; i++) {
- buffer = &handle->codec_buffers[i];
-
- buffer->index = i;
- buffer->format = format;
- buffer->resolution.width = resolution->width;
- buffer->resolution.height = resolution->height;
- buffer->num_planes = plane_num;
-
-#ifdef TIZEN_FEATURE_ZERO_COPY_SUPPORT
- tbm_buffer = &handle->tbm_buffers[i];
-
- tbm_buffer->bo = tbm_bo_alloc(handle->bufmgr, (int)buffer_size, TBM_BO_DEFAULT);
- if (!tbm_buffer->bo) {
- LOGE("bo alloc failed[size:%u]", buffer_size);
- ret = CODEC_ERROR_OUT_OF_MEMORY;
- goto _START_STREAM_FAILED;
- }
+ codec_buffer->index = i;
+ codec_buffer->format = format;
+ codec_buffer->resolution.width = width;
+ codec_buffer->resolution.height = height;
+ codec_buffer->num_planes = num_planes;
- tbm_buffer->bo_handle = tbm_bo_get_handle(tbm_buffer->bo, TBM_DEVICE_CPU);
- if (!tbm_buffer->bo_handle.ptr) {
- LOGE("bo[%p] get handle failed", tbm_buffer->bo);
+ /* decoder input */
+ memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
+ memset(v4l2_planes, 0x0, sizeof(v4l2_planes));
+
+ v4l2_buf.type = buffer_control->buf_type;
+ v4l2_buf.memory = buffer_control->memory_type;
+ v4l2_buf.index = i;
+ v4l2_buf.m.planes = v4l2_planes;
+ v4l2_buf.length = num_planes;
+
+ if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
+ LOGE("[input][%d] query buf failed. errno %d", i, errno);
ret = CODEC_ERROR_INTERNAL;
goto _START_STREAM_FAILED;
}
- tbm_buffer->dmabuf_fd = tbm_bo_export_fd(tbm_buffer->bo);
- if (tbm_buffer->dmabuf_fd < 0) {
- LOGE("export fd failed from bo[%p]", tbm_buffer->bo);
+ codec_buffer->total_size = v4l2_planes[0].length;
+ codec_buffer->planes[0].size = v4l2_planes[0].length;
+ codec_buffer->planes[0].data = mmap(0,
+ v4l2_planes[0].length,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ handle->device_fd,
+ (off_t)v4l2_planes[0].m.mem_offset);
+ if (codec_buffer->planes[0].data == MAP_FAILED) {
+ LOGE("[input][%d] mmap failed, size[%d], offset[%u] for mmap(errno %d)",
+ i, v4l2_planes[0].length, v4l2_planes[0].m.mem_offset, errno);
ret = CODEC_ERROR_INTERNAL;
goto _START_STREAM_FAILED;
}
- buffer->total_size = buffer_size;
- buffer->planes[0].size = buffer_size;
- buffer->planes[0].data = tbm_buffer->bo_handle.ptr;
- buffer->num_bos = 1;
- buffer->bos[0] = tbm_buffer->bo;
+ LOGI("[input][%d] buffer size[%d], data[%p]",
+ i, codec_buffer->planes[0].size, codec_buffer->planes[0].data);
+ }
- LOGD("buffer[%d], size[%d], data[%p], bo[%p], fd[%d]",
- i, buffer->planes[0].size, buffer->planes[0].data,
- tbm_buffer->bo, tbm_buffer->dmabuf_fd);
+ /* output buffer */
+ buffer_control = &handle->output_buffer_control;
- ret = __codec_v4l2_qbuf(handle->device_fd,
- handle->buffer_type, handle->memory_type,
- i, tbm_buffer->dmabuf_fd);
-#else /* TIZEN_FEATURE_ZERO_COPY_SUPPORT */
- memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
- memset(v4l2_planes, 0x0, sizeof(v4l2_planes));
+ ret = __codec_v4l2_reqbufs(handle->device_fd,
+ buffer_control->buf_type, V4L2_MEMORY_DMABUF,
+ out_buffer_count, &buffer_control->count);
+ if (ret != CODEC_ERROR_NONE) {
+ LOGE("[output] REQBUFS failed [0x%x]", ret);
+ return ret;
+ }
- v4l2_buf.type = handle->buffer_type;
- v4l2_buf.memory = handle->memory_type;
- v4l2_buf.index = i;
- v4l2_buf.m.planes = v4l2_planes;
- v4l2_buf.length = plane_num;
+ LOGI("[output] buffer count : request[%u] -> result[%u]",
+ out_buffer_count, buffer_control->count);
- if (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
- LOGE("[%d] query buf failed. errno %d", i, errno);
+ format = buffer_control->buffers[0].format;
+ width = buffer_control->buffers[0].resolution.width;
+ height = buffer_control->buffers[0].resolution.height;
+ num_planes = buffer_control->buffers[0].num_planes;
+
+ buffer_size = buffer_control->buffers[0].total_size;
+ plane_size[0] = buffer_control->buffers[0].planes[0].size;
+ plane_size[1] = buffer_control->buffers[0].planes[1].size;
+
+ for (i = 0 ; i < buffer_control->count ; i++) {
+ codec_buffer = &buffer_control->buffers[i];
+
+ codec_buffer->index = i;
+ codec_buffer->format = format;
+ codec_buffer->resolution.width = width;
+ codec_buffer->resolution.height = height;
+ codec_buffer->num_planes = num_planes;
+
+ codec_memory = &codec_buffer->memory;
+
+ codec_memory->bo[0] = tbm_bo_alloc(handle->bufmgr, (int)buffer_size, TBM_BO_DEFAULT);
+ if (!codec_memory->bo[0]) {
+ LOGE("[output][%d] bo alloc failed[size:%u]", i, buffer_size);
+ ret = CODEC_ERROR_OUT_OF_MEMORY;
+ goto _START_STREAM_FAILED;
+ }
+
+ bo_handle = tbm_bo_get_handle(codec_memory->bo[0], TBM_DEVICE_CPU);
+ if (!bo_handle.ptr) {
+ LOGE("[output][%d] bo[%p] get handle failed", i, codec_memory->bo[0]);
ret = CODEC_ERROR_INTERNAL;
goto _START_STREAM_FAILED;
}
- buffer->index = i;
- buffer->format = format;
- buffer->resolution.width = resolution->width;
- buffer->resolution.height = resolution->height;
- buffer->total_size = v4l2_buf.length;
- buffer->num_planes = plane_num;
- buffer->planes[0].size = v4l2_buf.length;
- buffer->planes[0].data = mmap(0,
- v4l2_buf.length,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- handle->device_fd,
- (off_t)v4l2_buf.m.offset);
+ codec_buffer->planes[0].data = bo_handle.ptr;
+ codec_buffer->planes[0].size = plane_size[0];
+ codec_buffer->planes[1].data = codec_buffer->planes[0].data + codec_buffer->planes[0].size;
+ codec_buffer->planes[1].size = plane_size[1];
- if (buffer->planes[0].data == MAP_FAILED) {
- LOGE("[%d] mmap failed (errno %d)", i, errno);
+ codec_memory->fd[0] = tbm_bo_export_fd(codec_memory->bo[0]);
+ if (codec_memory->fd[0] < 0) {
+ LOGE("[output][%d] export fd failed from bo[%p]", i, codec_memory->bo[0]);
+ ret = CODEC_ERROR_INTERNAL;
goto _START_STREAM_FAILED;
}
- LOGI("buffer[%d], size[%d], data[%p]",
- i, buffer->planes[0].size, buffer->planes[0].data);
+ LOGI("[output][%d] size[%u], bo[%p], fd[%d]",
+ i, buffer_size, codec_memory->bo[0], codec_memory->fd[0]);
ret = __codec_v4l2_qbuf(handle->device_fd,
- handle->buffer_type, handle->memory_type,
- i, CODEC_HAL_INITIAL_FD);
-#endif /* TIZEN_FEATURE_ZERO_COPY_SUPPORT */
-
+ buffer_control->buf_type, buffer_control->memory_type,
+ i, codec_memory->fd[0]);
if (ret != CODEC_ERROR_NONE) {
- LOGE("[%d] qbuf failed (errno %d)", i, errno);
+ LOGE("[output][%d] qbuf failed (fd %d, errno %d)",
+ i, codec_memory->fd[0], errno);
goto _START_STREAM_FAILED;
}
}
-#endif
/* stream on */
ret = __codec_v4l2_stream(handle->device_fd, handle->input_buffer_control.buf_type, TRUE);
if (ret != CODEC_ERROR_NONE) {
- LOGE("intput stream on failed");
+ LOGE("[input] stream on failed");
goto _START_STREAM_FAILED;
}
ret = __codec_v4l2_stream(handle->device_fd, handle->output_buffer_control.buf_type, TRUE);
if (ret != CODEC_ERROR_NONE) {
- LOGE("output stream on failed");
+ LOGE("[output] stream on failed");
goto _START_STREAM_FAILED;
}
}
new_handle = g_new0(hal_codec_handle_s, 1);
- if (!new_handle) {
- LOGE("failed to alloc codec HAL handle");
- tbm_bufmgr_deinit(bufmgr);
- return CODEC_ERROR_OUT_OF_MEMORY;
- }
+ new_handle->type = type;
new_handle->bufmgr = bufmgr;
g_mutex_init(&new_handle->lock);
*codec_handle = new_handle;
- LOGD("codec HAL handle [%p]", new_handle);
+ LOGD("codec HAL handle [%p] - type[%s]", new_handle, g_decoder_type_string[type]);
return CODEC_ERROR_NONE;
}
}
/* set format for input */
- ret = __codec_v4l2_s_fmt(device_fd, in_format, in_buf_type, width, height);
+ ret = __codec_v4l2_s_fmt(&handle->input_buffer_control,
+ device_fd, in_format, in_buf_type, width, height);
if (ret != CODEC_ERROR_NONE) {
LOGE("set format[%d] for input failed - [0x%x]", in_format, ret);
close(device_fd);
}
/* set format for output */
- ret = __codec_v4l2_s_fmt(device_fd, out_format, out_buf_type, width, height);
+ ret = __codec_v4l2_s_fmt(&handle->output_buffer_control,
+ device_fd, out_format, out_buf_type, width, height);
if (ret != CODEC_ERROR_NONE) {
LOGE("set format[%d] for output failed - [0x%x]", in_format, ret);
close(device_fd);
}
handle->input_buffer_control.buf_type = in_buf_type;
+ handle->input_buffer_control.memory_type = V4L2_MEMORY_MMAP;
handle->output_buffer_control.buf_type = out_buf_type;
+ handle->output_buffer_control.memory_type = V4L2_MEMORY_DMABUF;
handle->device_fd = device_fd;
handle->state = CODEC_STATE_CONFIGURED;