#include <glob.h>
#include <dlog.h>
#include <sched.h>
+#include <poll.h>
#include "hal_backend_codec_v4l2_private.h"
-#include <tbm_surface.h>
#ifdef LOG_TAG
#undef LOG_TAG
(fourcc >> 16) & 0xff,\
(fourcc >> 24) & 0xff
-#define DEVICE_TYPE_MAX (CODEC_TYPE_ENCODER + 1)
+#define DEVICE_TYPE_MAX (HAL_CODEC_TYPE_ENCODER + 1)
#define DEVICE_NODE_PATH_LENGTH_MAX 32
#define DEVICE_MAX 8
#define DEVICE_FORMAT_MAX 16
#define ERROR_STRING_LENGTH 64
+#define IDLE_BUFFER_INDEX_INIT -1
+#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 TIMESTAMP_TO_TIMEVAL(timestamp, timeval) \
+ do { \
+ timeval.tv_sec = (glong)(timestamp / NSEC_PER_SEC); \
+ timeval.tv_usec = (glong)((timestamp % 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; \
+ } while (0)
+
+#define CODEC_THREAD_NAME_HANDLE_BUFFER "handle_buffer"
+
typedef struct _codec_v4l2_format_list_s {
uint32_t count;
enum v4l2_buf_type buf_type;
- codec_format_type_e format_type;
- codec_format_e formats[DEVICE_FORMAT_MAX];
+ hal_codec_format_type_e format_type;
+ hal_codec_format_e formats[DEVICE_FORMAT_MAX];
} codec_v4l2_format_list_s;
typedef struct _codec_v4l2_device_s {
/* 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"
+ [HAL_CODEC_TYPE_DECODER] = "DECODER",
+ [HAL_CODEC_TYPE_ENCODER] = "ENCODER"
};
static void __codec_v4l2_constructor(void) __attribute__((constructor));
static void __codec_v4l2_destructor(void) __attribute__((destructor));
+static void __codec_v4l2_release_handle(codec_hal_handle_s *handle);
+
static int __codec_v4l2_probe_device(void);
static void __codec_v4l2_release_device_list(void);
-static void __codec_init_buffer_control(codec_buffer_control_s *buffer_control);
-static void __codec_deinit_buffer_control(codec_buffer_control_s *buffer_control);
+static void __codec_v4l2_init_buffer_control(codec_hal_handle_s *handle);
+static void __codec_v4l2_deinit_buffer_control(codec_hal_handle_s *handle);
+
+static void *__codec_v4l2_message_handler_func(gpointer data);
+static void __codec_v4l2_message_release_func(gpointer data);
+static void __codec_v4l2_message_send(codec_hal_handle_s *handle, hal_codec_message_type_e type, gpointer value);
+
+static int __codec_v4l2_start_stream(codec_hal_handle_s *handle, codec_hal_buffer_control_s *buffer_control, uint32_t buffer_count);
+static int __codec_v4l2_stop_stream(codec_hal_handle_s *handle);
+
+static int __codec_v4l2_set_command(codec_hal_handle_s *handle, int64_t command, void *value);
+
+static hal_codec_buffer_s *__codec_v4l2_get_idle_buffer(codec_hal_buffer_control_s *buffer_control, gint64 timeout_ms);
+static void __codec_v4l2_add_idle_buffer(codec_hal_buffer_control_s *buffer_control, hal_codec_buffer_s *buffer);
-static int __codec_v4l2_get_format(guint32 fourcc, codec_format_e *format);
-static int __codec_get_fourcc_plane_num(codec_format_e format, uint32_t *fourcc, uint32_t *plane_num);
-static void __codec_v4l2_send_message(hal_codec_handle_s *handle, codec_message_type_e type, int value);
+static int __codec_v4l2_get_format(guint32 fourcc, hal_codec_format_e *format);
+static int __codec_get_fourcc_plane_num(hal_codec_format_e format, uint32_t *fourcc, uint32_t *plane_num);
{
int index = 0;
uint32_t count = 0;
- codec_format_e format = CODEC_FORMAT_H264;
+ hal_codec_format_e format = HAL_CODEC_FORMAT_H264;
struct v4l2_fmtdesc fmtdesc;
if (device_fd < 0 || !format_list) {
break;
}
- if (__codec_v4l2_get_format(fmtdesc.pixelformat, &format) == CODEC_ERROR_NONE) {
+ if (__codec_v4l2_get_format(fmtdesc.pixelformat, &format) == HAL_CODEC_ERROR_NONE) {
format_list->formats[count] = format;
count++;
- if (format & CODEC_FORMAT_TYPE_ENCODED)
- format_list->format_type = CODEC_FORMAT_TYPE_ENCODED;
+ if (format & HAL_CODEC_FORMAT_TYPE_ENCODED)
+ format_list->format_type = HAL_CODEC_FORMAT_TYPE_ENCODED;
else
- format_list->format_type = CODEC_FORMAT_TYPE_RAW;
+ format_list->format_type = HAL_CODEC_FORMAT_TYPE_RAW;
}
}
switch (ret) {
case GLOB_NOSPACE:
LOGE("out of memory");
- return CODEC_ERROR_OUT_OF_MEMORY;
+ return HAL_CODEC_ERROR_OUT_OF_MEMORY;
case GLOB_ABORTED:
LOGE("read error");
- return CODEC_ERROR_INTERNAL;
+ return HAL_CODEC_ERROR_INTERNAL;
case GLOB_NOMATCH:
LOGE("match not found");
- return CODEC_ERROR_INTERNAL;
+ return HAL_CODEC_ERROR_INTERNAL;
default:
LOGE("unknown error[%d]", ret);
- return CODEC_ERROR_INTERNAL;
+ return HAL_CODEC_ERROR_INTERNAL;
}
}
close(device_fd);
if (codec_device->in_format.count > 0 && codec_device->out_format.count > 0 &&
- ((codec_device->in_format.format_type == CODEC_FORMAT_TYPE_ENCODED &&
- codec_device->out_format.format_type == CODEC_FORMAT_TYPE_RAW) ||
- (codec_device->in_format.format_type == CODEC_FORMAT_TYPE_RAW &&
- codec_device->out_format.format_type == CODEC_FORMAT_TYPE_ENCODED))) {
+ ((codec_device->in_format.format_type == HAL_CODEC_FORMAT_TYPE_ENCODED &&
+ codec_device->out_format.format_type == HAL_CODEC_FORMAT_TYPE_RAW) ||
+ (codec_device->in_format.format_type == HAL_CODEC_FORMAT_TYPE_RAW &&
+ codec_device->out_format.format_type == HAL_CODEC_FORMAT_TYPE_ENCODED))) {
strncpy(codec_device->node_path, glob_buf.gl_pathv[i], DEVICE_NODE_PATH_LENGTH_MAX - 1);
codec_device->capabilities = device_caps;
g_codec_device_list = NULL;
}
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
}
-static int __codec_v4l2_get_buf_type_and_node_path(codec_format_e in_format, codec_format_e out_format,
+static int __codec_v4l2_get_buf_type_and_node_path(hal_codec_format_e in_format, hal_codec_format_e out_format,
enum v4l2_buf_type *in_buf_type, enum v4l2_buf_type *out_buf_type, char **path)
{
uint32_t device_index = 0;
if (!g_codec_device_list) {
LOGE("no codec device list");
- return CODEC_ERROR_INTERNAL;
+ return HAL_CODEC_ERROR_INTERNAL;
}
if (!path || !in_buf_type || !out_buf_type) {
LOGE("NULL param [%p,%p,%p]", path, in_buf_type, out_buf_type);
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
for (device_index = 0 ; device_index < g_codec_device_list->count ; device_index++) {
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;
+ return HAL_CODEC_ERROR_NONE;
}
}
}
LOGE("node path not found for format[in:%d,out:%d]", in_format, out_format);
- return CODEC_ERROR_NOT_SUPPORTED;
+ return HAL_CODEC_ERROR_NOT_SUPPORTED;
}
-static void __codec_v4l2_send_message(hal_codec_handle_s *handle, codec_message_type_e type, int value)
+static void __codec_v4l2_message_send(codec_hal_handle_s *handle, hal_codec_message_type_e type, gpointer value)
{
- codec_message_s *message = NULL;
+ hal_codec_message_s *message = NULL;
g_autoptr(GMutexLocker) locker = NULL;
if (!handle) {
return;
}
+ message = g_new0(hal_codec_message_s, 1);
+ message->type = type;
+
locker = g_mutex_locker_new(&handle->msg_cb_lock);
switch (type) {
- case CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED:
+ 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);
break;
- case CODEC_MESSAGE_TYPE_OUTPUT_BUFFER:
+ 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);
break;
- case CODEC_MESSAGE_TYPE_RESOLUTION_CHANGED:
+ case HAL_CODEC_MESSAGE_TYPE_RESOLUTION_CHANGED:
break;
- case CODEC_MESSAGE_TYPE_ERROR:
- message->error_code = (codec_error_e)value;
+ case HAL_CODEC_MESSAGE_TYPE_ERROR:
+ message->error_code = GPOINTER_TO_INT(value);
+ LOGE("error code[%d]", message->error_code);
break;
default:
LOGW("unhandled type[%d]", type);
+ g_free(message);
return;
}
- message = g_new0(codec_message_s, 1);
-
- message->type = type;
-
- LOGD("type[%d], value[0x%x]", type, value);
-
g_queue_push_tail(handle->msg_list, message);
- g_cond_signal(&handle->msg_cb_cond);
-}
-
-
-static int __codec_v4l2_wait_frame(int device_fd, int wait_time)
-{
- int ret = CODEC_ERROR_NONE;
- fd_set fds;
- struct timeval timeout;
-
- if (device_fd < 0) {
- LOGE("invalid fd %d", device_fd);
- return CODEC_ERROR_INVALID_PARAMETER;
- }
-
- FD_ZERO(&fds);
- FD_SET(device_fd, &fds);
-
- memset(&timeout, 0x0, sizeof(struct timeval));
-
- timeout.tv_sec = wait_time;
- timeout.tv_usec = 0;
-
- /*LOGD("select : %d sec", wait_time);*/
-
- ret = select(device_fd + 1, &fds, NULL, NULL, &timeout);
- if (ret == -1) {
- if (EINTR == errno) {
- LOGD("select error : EINTR");
- return CODEC_ERROR_NONE;
- }
- LOGE("select failed. errno %d", errno);
- return CODEC_ERROR_INTERNAL;
- }
-
- if (ret == 0) {
- LOGE("select timeout.");
- return CODEC_ERROR_INTERNAL;
- }
-
- /*LOGD("select done");*/
-
- return CODEC_ERROR_NONE;
+ g_cond_broadcast(&handle->msg_cb_cond);
}
if (!value) {
LOGE("NULL param");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
memset(&ctrl, 0x0, sizeof(struct v4l2_control));
}
-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)
+static int __codec_v4l2_set_config(codec_hal_buffer_control_s *buffer_control,
+ enum v4l2_buf_type buf_type, enum v4l2_memory memory,
+ hal_codec_format_e format, int width, int height)
+{
+ codec_hal_config_s *codec_config = NULL;
+
+ if (!buffer_control) {
+ LOGE("NULL control");
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
+ }
+
+ codec_config = &buffer_control->config;
+
+ LOGI("type[%d] v4l2[buf type:%d, memory:%d], format[0x%x], resolution[%dx%d]",
+ buffer_control->type, buf_type, memory, format, width, height);
+
+ codec_config->buf_type = buf_type;
+ codec_config->memory = memory;
+ codec_config->format = format;
+ codec_config->resolution.width = width;
+ codec_config->resolution.height = height;
+
+ return HAL_CODEC_ERROR_NONE;
+}
+
+
+static int __codec_v4l2_s_fmt(codec_hal_buffer_control_s *buffer_control, int device_fd)
{
int i = 0;
uint32_t fourcc = 0;
- uint32_t plane_num = 0;
+ uint32_t num_planes = 0;
+ codec_hal_config_s *codec_config = NULL;
+ codec_hal_buffer_control_type_e type;
struct v4l2_format v4l2_fmt;
- codec_buffer_s *codec_buffer = NULL;
if (!buffer_control) {
- LOGE("NULL buffer control");
- return CODEC_ERROR_INVALID_PARAMETER;
+ LOGE("NULL control");
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
- memset(&v4l2_fmt, 0x0, sizeof(struct v4l2_format));
+ codec_config = &buffer_control->config;
+ type = buffer_control->type;
- 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 [0x%x]", format);
- return CODEC_ERROR_INVALID_PARAMETER;
+ if (__codec_get_fourcc_plane_num(codec_config->format, &fourcc, &num_planes) != HAL_CODEC_ERROR_NONE) {
+ LOGE("type[%d] get fourcc failed for format [0x%x]", type, codec_config->format);
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
+ codec_config->num_planes = num_planes;
+
memset(&v4l2_fmt, 0x0, sizeof(struct v4l2_format));
- v4l2_fmt.type = buf_type;
- if (V4L2_TYPE_IS_MULTIPLANAR(buf_type)) {
- v4l2_fmt.fmt.pix_mp.width = width;
- v4l2_fmt.fmt.pix_mp.height = height;
+ v4l2_fmt.type = codec_config->buf_type;
+
+ if (V4L2_TYPE_IS_MULTIPLANAR(codec_config->buf_type)) {
+ v4l2_fmt.fmt.pix_mp.width = codec_config->resolution.width;
+ v4l2_fmt.fmt.pix_mp.height = codec_config->resolution.height;
v4l2_fmt.fmt.pix_mp.pixelformat = fourcc;
- v4l2_fmt.fmt.pix_mp.num_planes = plane_num;
+ v4l2_fmt.fmt.pix_mp.num_planes = num_planes;
} else {
- v4l2_fmt.fmt.pix.width = width;
- v4l2_fmt.fmt.pix.height = height;
+ v4l2_fmt.fmt.pix.width = codec_config->resolution.width;
+ v4l2_fmt.fmt.pix.height = codec_config->resolution.height;
v4l2_fmt.fmt.pix.pixelformat = fourcc;
- v4l2_fmt.fmt.pix.bytesperline = width;
+ v4l2_fmt.fmt.pix.bytesperline = codec_config->resolution.width;
}
if (ioctl(device_fd, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
- LOGE("S_FMT failed. errno %d", errno);
- return CODEC_ERROR_INTERNAL;
+ LOGE("type[%d] S_FMT failed. errno %d", type, errno);
+ return HAL_CODEC_ERROR_INTERNAL;
}
- 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)) {
+ if (V4L2_TYPE_IS_MULTIPLANAR(codec_config->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);
+ LOGI("type[%d] plane[%d] size [%u]",
+ type, i, v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage);
+ codec_config->buffer_size += v4l2_fmt.fmt.pix_mp.plane_fmt[i].sizeimage;
}
} else {
/* TODO: get size of each plane */
- codec_buffer->total_size = v4l2_fmt.fmt.pix.sizeimage;
+ codec_config->buffer_size = v4l2_fmt.fmt.pix.sizeimage;
}
- LOGI("format[0x%x], resolution[%dx%d] buffer size[%u]",
- format, width, height, codec_buffer->total_size);
+ LOGI("type[%d] buffer size[%u], num planes[%u]",
+ type, codec_config->buffer_size, codec_config->num_planes);
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
{
if (device_fd < 0) {
LOGE("invalid fd %d", device_fd);
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
if (ioctl(device_fd, onoff ? VIDIOC_STREAMON : VIDIOC_STREAMOFF, &type) < 0) {
LOGE("stream %d failed. [t:%d] errno %d", onoff, type, errno);
- return CODEC_ERROR_INTERNAL;
+ return HAL_CODEC_ERROR_INTERNAL;
}
LOGD("stream %d done [t:%d]", onoff, type);
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
if (device_fd < 0) {
LOGE("invalid fd %d", device_fd);
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
- LOGI("type[%d], memory[%d], count[%u]", type, memory, count);
+ LOGI("type[%d] memory[%d], count[%u]", type, memory, count);
memset(&v4l2_reqbuf, 0x0, sizeof(struct v4l2_requestbuffers));
if (ioctl(device_fd, VIDIOC_REQBUFS, &v4l2_reqbuf) < 0) {
LOGE("REQBUFS[count %d] failed. errno %d", count, errno);
- return CODEC_ERROR_INTERNAL;
+ return HAL_CODEC_ERROR_INTERNAL;
}
if (v4l2_reqbuf.count != count)
if (result_count)
*result_count = v4l2_reqbuf.count;
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
-static int __codec_v4l2_qbuf(int device_fd, int type, int memory, int index, int dmabuf_fd)
+static int __codec_v4l2_qbuf(int device_fd,
+ codec_hal_buffer_control_s *buffer_control,
+ hal_codec_buffer_s *codec_buffer)
{
+ uint32_t i = 0;
+
+ codec_hal_config_s *codec_config = NULL;
+ hal_codec_memory_s *codec_memory = NULL;
+
struct v4l2_buffer v4l2_buf;
struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];
- if (device_fd < 0) {
- LOGE("invalid fd %d", device_fd);
- return CODEC_ERROR_INVALID_PARAMETER;
+ 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;
}
+ codec_config = &buffer_control->config;
+ codec_memory = &codec_buffer->memory;
+
memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
memset(v4l2_planes, 0x0, sizeof(v4l2_planes));
- v4l2_buf.index = index;
- v4l2_buf.type = type;
- v4l2_buf.memory = memory;
+ v4l2_buf.index = codec_buffer->index;
+ v4l2_buf.type = codec_config->buf_type;
+ v4l2_buf.memory = codec_config->memory;
v4l2_buf.m.planes = v4l2_planes;
- v4l2_buf.length = 1;
- if (dmabuf_fd > CODEC_HAL_INITIAL_FD) {
- if (V4L2_TYPE_IS_MULTIPLANAR(type))
- v4l2_buf.m.planes[0].m.fd = dmabuf_fd;
- else
- v4l2_buf.m.fd = dmabuf_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);
+ 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]);
+ 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);
+
+ v4l2_buf.m.fd = codec_memory->fd[0];
+ }
+
+ v4l2_buf.length = codec_memory->num_fd;
+ } else {
+ /* V4L2_MEMORY_MMAP */
+ v4l2_buf.length = 1;
+ }
+
+ if (codec_buffer->meta.timestamp > 0) {
+ 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);
}
if (ioctl(device_fd, VIDIOC_QBUF, &v4l2_buf) < 0) {
- LOGE("qbuf failed. [i: %d, t: %d, m: %d] errno %d",
- index, type, memory, errno);
- return CODEC_ERROR_INTERNAL;
+ LOGE("QBUF failed. control[%d] buffer[%d], errno[%d]",
+ buffer_control->type, codec_buffer->index, errno);
+ return HAL_CODEC_ERROR_INTERNAL;
}
- LOGD("QBUF done [i:%d, t:%d, m:%d, fd:%d]",
- index, type, memory, dmabuf_fd);
+ LOGD("QBUF done - control[%d] buffer[%d]",
+ buffer_control->type, codec_buffer->index);
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
-static int __codec_v4l2_dqbuf(int device_fd, int type, int memory, int *index, uint32_t *bytesused)
+static int __codec_v4l2_dqbuf(int device_fd,
+ codec_hal_buffer_control_s *buffer_control,
+ hal_codec_buffer_s **out_buffer)
{
- int ret = CODEC_ERROR_NONE;
+ int ret = HAL_CODEC_ERROR_NONE;
+
+ codec_hal_config_s *codec_config = NULL;
+
struct v4l2_buffer v4l2_buf;
struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];
- if (device_fd < 0) {
- LOGE("invalid fd %d", device_fd);
- return CODEC_ERROR_INVALID_PARAMETER;
+ 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;
}
- if (!index) {
- LOGE("NULL parameter");
- return CODEC_ERROR_INVALID_PARAMETER;
- }
+ codec_config = &buffer_control->config;
memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
memset(v4l2_planes, 0x0, sizeof(v4l2_planes));
- v4l2_buf.type = type;
- v4l2_buf.memory = memory;
+ v4l2_buf.type = codec_config->buf_type;
+ v4l2_buf.memory = codec_config->memory;
v4l2_buf.m.planes = v4l2_planes;
+ v4l2_buf.length = codec_config->num_planes;
ret = ioctl(device_fd, VIDIOC_DQBUF, &v4l2_buf);
if (ret < 0) {
- LOGE("dqbuf failed. [t: %d, m: %d] errno %d",
- type, memory, errno);
- return CODEC_ERROR_DEVICE_READ;
+ LOGE("control[%d] DQBUF failed. [t: %d, m: %d] errno %d",
+ buffer_control->type, codec_config->buf_type, codec_config->memory, errno);
+ return HAL_CODEC_ERROR_DEVICE_READ;
}
- LOGD("DQBUF[i:%d], bytesused[%u], length[%u]",
- v4l2_buf.index, v4l2_buf.bytesused, v4l2_buf.length);
+ LOGD("control[%d] DQBUF[i:%d], bytesused[%u], length[%u]",
+ buffer_control->type, v4l2_buf.index, v4l2_buf.bytesused, v4l2_buf.length);
- *index = v4l2_buf.index;
- if (bytesused)
- *bytesused = v4l2_buf.bytesused;
+ *out_buffer = &buffer_control->buffers.buffer[v4l2_buf.index];
- /*LOGD("dqbuf index %d", *index);*/
-
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
-static int __codec_v4l2_get_format(guint32 fourcc, codec_format_e *format)
+static int __codec_v4l2_get_format(guint32 fourcc, hal_codec_format_e *format)
{
if (!format) {
LOGE("NULL parameter");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
switch (fourcc) {
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV12M:
- *format = CODEC_FORMAT_NV12;
+ *format = HAL_CODEC_FORMAT_NV12;
break;
case V4L2_PIX_FMT_NV12MT:
- *format = CODEC_FORMAT_NV12T;
+ *format = HAL_CODEC_FORMAT_NV12T;
break;
case V4L2_PIX_FMT_NV21:
case V4L2_PIX_FMT_NV21M:
- *format = CODEC_FORMAT_NV21;
+ *format = HAL_CODEC_FORMAT_NV21;
break;
case V4L2_PIX_FMT_YUV420:
- *format = CODEC_FORMAT_I420;
+ *format = HAL_CODEC_FORMAT_I420;
break;
case V4L2_PIX_FMT_YVU420:
- *format = CODEC_FORMAT_YV12;
+ *format = HAL_CODEC_FORMAT_YV12;
break;
case V4L2_PIX_FMT_YUYV:
- *format = CODEC_FORMAT_YUYV;
+ *format = HAL_CODEC_FORMAT_YUYV;
break;
case V4L2_PIX_FMT_UYVY:
- *format = CODEC_FORMAT_UYVY;
+ *format = HAL_CODEC_FORMAT_UYVY;
break;
case V4L2_PIX_FMT_H264:
- *format = CODEC_FORMAT_H264;
+ *format = HAL_CODEC_FORMAT_H264;
break;
default:
LOGW("unhandled fourcc ["FOURCC_FORMAT"]", FOURCC_CONVERT(fourcc));
- return CODEC_ERROR_INTERNAL;
+ return HAL_CODEC_ERROR_INTERNAL;
}
LOGI("fourcc ["FOURCC_FORMAT"] -> format [0x%x]",
FOURCC_CONVERT(fourcc), *format);
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
-static int __codec_get_fourcc_plane_num(codec_format_e format, uint32_t *fourcc, uint32_t *plane_num)
+static int __codec_get_fourcc_plane_num(hal_codec_format_e format, uint32_t *fourcc, uint32_t *plane_num)
{
if (!fourcc || !plane_num) {
LOGE("NULL parameter %p %p", fourcc, plane_num);
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
switch (format) {
- case CODEC_FORMAT_NV12:
+ case HAL_CODEC_FORMAT_NV12:
*fourcc = V4L2_PIX_FMT_NV12;
*plane_num = 2;
break;
- case CODEC_FORMAT_NV12T:
+ case HAL_CODEC_FORMAT_NV12T:
*fourcc = V4L2_PIX_FMT_NV12MT;
*plane_num = 2;
break;
- case CODEC_FORMAT_NV21:
+ case HAL_CODEC_FORMAT_NV21:
*fourcc = V4L2_PIX_FMT_NV21;
*plane_num = 2;
break;
- case CODEC_FORMAT_I420:
+ case HAL_CODEC_FORMAT_I420:
*fourcc = V4L2_PIX_FMT_YUV420;
*plane_num = 3;
break;
- case CODEC_FORMAT_YV12:
+ case HAL_CODEC_FORMAT_YV12:
*fourcc = V4L2_PIX_FMT_YVU420;
*plane_num = 3;
break;
- case CODEC_FORMAT_YUYV:
+ case HAL_CODEC_FORMAT_YUYV:
*fourcc = V4L2_PIX_FMT_YUYV;
*plane_num = 1;
break;
- case CODEC_FORMAT_UYVY:
+ case HAL_CODEC_FORMAT_UYVY:
*fourcc = V4L2_PIX_FMT_UYVY;
*plane_num = 1;
break;
- case CODEC_FORMAT_H264:
+ case HAL_CODEC_FORMAT_H264:
*fourcc = V4L2_PIX_FMT_H264;
*plane_num = 1;
break;
default:
LOGE("unhandled format [%d]", format);
- return CODEC_ERROR_INTERNAL;
+ return HAL_CODEC_ERROR_INTERNAL;
}
LOGD("format [0x%x] -> fourcc ["FOURCC_FORMAT"]",
format, FOURCC_CONVERT(*fourcc));
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
-static int __codec_stop_stream(hal_codec_handle_s *handle)
+static int __codec_v4l2_stop_stream(codec_hal_handle_s *handle)
{
int i = 0;
- int ret = CODEC_ERROR_NONE;
- codec_memory_s *codec_memory = NULL;
- codec_buffer_s *codec_buffer = NULL;
- codec_buffer_control_s *buffer_control = NULL;
+ int k = 0;
+ int ret = HAL_CODEC_ERROR_NONE;
+ hal_codec_memory_s *codec_memory = NULL;
+ codec_hal_buffer_control_s *buffer_control = NULL;
+ hal_codec_buffer_s *codec_buffer = NULL;
if (!handle) {
LOGE("NULL handle");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_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);
- if (ret != CODEC_ERROR_NONE) {
- LOGE("STREAMOFF failed[0x%x]", ret);
- return ret;
+ for (i = 0 ; i < CODEC_HAL_BUFFER_CONTROL_TYPE_MAX ; i++) {
+ ret = __codec_v4l2_stream(handle->device_fd,
+ handle->buffer_control[i].config.buf_type, FALSE);
+ if (ret != HAL_CODEC_ERROR_NONE) {
+ LOGE("buffer_control[%d] STREAMOFF failed[0x%x]", i, ret);
+ return ret;
+ }
}
/* decoder */
/* release output buffer */
- buffer_control = &handle->output_buffer_control;
+ buffer_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT];
- for (i = 0 ; i < buffer_control->count ; i++) {
- codec_buffer = &buffer_control->buffers[i];
+ for (i = 0 ; i < buffer_control->buffers.count ; i++) {
+ codec_buffer = &buffer_control->buffers.buffer[i];
codec_memory = &codec_buffer->memory;
- 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;
- }
-
- LOGI("[output][%d] close fd[%d], unref bo[%p]",
- i, codec_memory->fd[0], codec_memory->bo[0]);
-
- close(codec_memory->fd[0]);
- tbm_bo_unref(codec_memory->bo[0]);
+ 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]);
+ close(codec_memory->fd[k]);
+ codec_memory->fd[k] = CODEC_HAL_INITIAL_FD;
+ }
- codec_memory->fd[0] = CODEC_HAL_INITIAL_FD;
- codec_memory->bo[0] = NULL;
+ 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;
+ }
+ }
}
ret = __codec_v4l2_reqbufs(handle->device_fd,
- handle->output_buffer_control.buf_type, V4L2_MEMORY_MMAP, 0, NULL);
- if (ret != CODEC_ERROR_NONE) {
+ buffer_control->config.buf_type, V4L2_MEMORY_MMAP, 0, NULL);
+ if (ret != HAL_CODEC_ERROR_NONE) {
LOGE("[output] REQBUFS 0 failed[0x%x]", ret);
return ret;
}
/* release input buffer */
- buffer_control = &handle->input_buffer_control;
+ buffer_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT];
- for (i = 0 ; i < buffer_control->count ; i++) {
- codec_buffer = &buffer_control->buffers[i];
+ for (i = 0 ; i < buffer_control->buffers.count ; i++) {
+ codec_buffer = &buffer_control->buffers.buffer[i];
- if (!codec_buffer->planes[0].data || codec_buffer->total_size == 0) {
+ if (!codec_buffer->planes.plane[0].data || codec_buffer->size == 0) {
LOGW("[input][%d] invalid data[%p], size[%u]",
- i, codec_buffer->planes[0].data, codec_buffer->total_size);
+ i, codec_buffer->planes.plane[0].data, codec_buffer->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);
+ i, codec_buffer->planes.plane[0].data, codec_buffer->size);
- codec_buffer->planes[0].data = NULL;
- codec_buffer->total_size = 0;
+ munmap(codec_buffer->planes.plane[0].data, codec_buffer->size);
+
+ codec_buffer->planes.plane[0].data = NULL;
+ codec_buffer->size = 0;
}
ret = __codec_v4l2_reqbufs(handle->device_fd,
- handle->input_buffer_control.buf_type, V4L2_MEMORY_MMAP, 0, NULL);
- if (ret != CODEC_ERROR_NONE) {
+ buffer_control->config.buf_type, V4L2_MEMORY_MMAP, 0, NULL);
+ if (ret != HAL_CODEC_ERROR_NONE) {
LOGE("[input] REQBUFS 0 failed[0x%x]", ret);
return ret;
}
LOGI("done");
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
-static int __codec_start_stream(hal_codec_handle_s *handle,
- uint32_t in_buffer_count, uint32_t out_buffer_count)
+static int __codec_v4l2_start_stream(codec_hal_handle_s *handle,
+ codec_hal_buffer_control_s *buffer_control, uint32_t buffer_count)
{
int i = 0;
- int width = 0;
- int height = 0;
+ int k = 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;
- uint32_t plane_size[V4L2_PLANES_MAX] = {0, };
- tbm_bo_handle bo_handle = {NULL, };
+ int ret = HAL_CODEC_ERROR_NONE;
+
+ hal_codec_memory_s *codec_memory = NULL;
+ hal_codec_buffer_s *codec_buffer = NULL;
+ codec_hal_config_s *codec_config = NULL;
+ codec_hal_buffer_control_type_e type;
+
struct v4l2_buffer v4l2_buf;
struct v4l2_plane v4l2_planes[V4L2_PLANES_MAX];
- if (!handle) {
- LOGE("NULL handle");
- return CODEC_ERROR_INTERNAL;
- }
-
- /* input buffer */
- buffer_control = &handle->input_buffer_control;
+ tbm_bo new_bo = NULL;
+ tbm_bo_handle bo_handle = {NULL, };
- ret = __codec_v4l2_reqbufs(handle->device_fd,
- buffer_control->buf_type, V4L2_MEMORY_MMAP,
- in_buffer_count, &buffer_control->count);
- if (ret != CODEC_ERROR_NONE) {
- LOGE("[input] REQBUFS failed [0x%x]", ret);
- return ret;
+ if (!handle || !buffer_control) {
+ LOGE("NULL param [%p,%p]", handle, buffer_control);
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
- LOGI("[input] buffer count : request %u -> result %u",
- in_buffer_count, buffer_control->count);
+ type = buffer_control->type;
+ codec_config = &buffer_control->config;
- 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;
-
- 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;
-
- /* 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;
- }
-
- 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;
- }
-
- LOGI("[input][%d] buffer size[%d], data[%p]",
- i, codec_buffer->planes[0].size, codec_buffer->planes[0].data);
- }
-
- /* output buffer */
- buffer_control = &handle->output_buffer_control;
+ LOGI("type[%d] buf_type[%d], memory[%d], plane num[%u], buffer count[%u]",
+ type, codec_config->buf_type, codec_config->memory,
+ codec_config->num_planes, buffer_count);
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);
+ codec_config->buf_type, codec_config->memory,
+ buffer_count, &buffer_control->buffers.count);
+ if (ret != HAL_CODEC_ERROR_NONE) {
+ LOGE("type[%d] REQBUFS failed [0x%x]", type, ret);
return ret;
}
- LOGI("[output] buffer count : request[%u] -> result[%u]",
- out_buffer_count, buffer_control->count);
-
- 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("type[%d] buffer count - request[%u] -> result[%u]",
+ type, buffer_count, buffer_control->buffers.count);
- 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;
+ num_planes = codec_config->num_planes;
- for (i = 0 ; i < buffer_control->count ; i++) {
- codec_buffer = &buffer_control->buffers[i];
+ for (i = 0 ; i < buffer_control->buffers.count ; i++) {
+ codec_buffer = &buffer_control->buffers.buffer[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_buffer->meta.format = codec_config->format;
+ codec_buffer->meta.resolution.width = codec_config->resolution.width;
+ codec_buffer->meta.resolution.height = codec_config->resolution.height;
+ codec_buffer->planes.num_planes = num_planes;
+ codec_buffer->size = codec_config->buffer_size;
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;
- }
+ if (codec_config->memory == V4L2_MEMORY_MMAP) {
+ memset(&v4l2_buf, 0x0, sizeof(struct v4l2_buffer));
+ memset(v4l2_planes, 0x0, sizeof(v4l2_planes));
- 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;
- }
+ v4l2_buf.type = codec_config->buf_type;
+ v4l2_buf.memory = codec_config->memory;
+ v4l2_buf.index = i;
+ v4l2_buf.m.planes = v4l2_planes;
+ v4l2_buf.length = num_planes;
- 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 (ioctl(handle->device_fd, VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
+ LOGE("type[%d] buffer[i:%d] query buf failed (errno %d)", type, i, errno);
+ ret = HAL_CODEC_ERROR_INTERNAL;
+ goto _START_STREAM_FAILED;
+ }
- 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;
- }
+ for (k = 0 ; k < v4l2_buf.length ; k++) {
+ codec_buffer->planes.plane[k].size = v4l2_planes[k].length;
+ codec_buffer->planes.plane[k].data = mmap(0,
+ v4l2_planes[k].length,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ handle->device_fd,
+ (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);
+ ret = HAL_CODEC_ERROR_INTERNAL;
+ goto _START_STREAM_FAILED;
+ }
+
+ LOGI("type[%d] buffer[i:%d][%d] buffer size[%d], data[%p]",
+ type, i, k, codec_buffer->planes.plane[k].size, codec_buffer->planes.plane[k].data);
+ }
+ } else {
+ /* V4L2_MEMORY_DMABUF */
+ new_bo = tbm_bo_alloc(handle->bufmgr, (int)codec_buffer->size, TBM_BO_DEFAULT);
+ if (!new_bo) {
+ LOGE("type[%d] buffer[i:%d] bo alloc failed, size[%u]", type, i, codec_buffer->size);
+ goto _START_STREAM_FAILED;
+ }
+
+ bo_handle = tbm_bo_get_handle(new_bo, TBM_DEVICE_CPU);
+ if (!bo_handle.ptr) {
+ LOGE("type[%d] buffer[i:%d] bo get handle failed for bo[%p]", type, i, new_bo);
+ tbm_bo_unref(new_bo);
+ goto _START_STREAM_FAILED;
+ }
- LOGI("[output][%d] size[%u], bo[%p], fd[%d]",
- i, buffer_size, codec_memory->bo[0], codec_memory->fd[0]);
+ codec_memory->fd[0] = tbm_bo_export_fd(new_bo);
+ if (codec_memory->fd[0] < 0) {
+ LOGE("type[%d] buffer[i:%d] get fd handle failed for bo[%p]", type, i, new_bo);
+ tbm_bo_unref(new_bo);
+ goto _START_STREAM_FAILED;
+ }
- ret = __codec_v4l2_qbuf(handle->device_fd,
- buffer_control->buf_type, buffer_control->memory_type,
- i, codec_memory->fd[0]);
- if (ret != CODEC_ERROR_NONE) {
- LOGE("[output][%d] qbuf failed (fd %d, errno %d)",
- i, codec_memory->fd[0], errno);
- goto _START_STREAM_FAILED;
+ buffer_control->buffers.bo[i][0] = new_bo;
+ codec_memory->num_fd = 1;
+
+ codec_buffer->planes.plane[0].data = bo_handle.ptr;
+ codec_buffer->planes.plane[0].stride = handle->ts_info.planes[0].stride;
+ codec_buffer->planes.plane[0].size = handle->ts_info.planes[0].size;
+ codec_buffer->planes.plane[0].bytesused = handle->ts_info.planes[0].stride * codec_config->resolution.height;
+
+ codec_buffer->planes.plane[1].data = bo_handle.ptr + handle->ts_info.planes[0].size;
+ codec_buffer->planes.plane[1].stride = handle->ts_info.planes[1].stride;
+ codec_buffer->planes.plane[1].size = handle->ts_info.planes[1].size;
+ codec_buffer->planes.plane[1].bytesused = handle->ts_info.planes[1].stride * (codec_config->resolution.height >> 1);
+
+ LOGI("type[%d] buffer[i:%d] new bo[%p], vaddr[%p]", type, i, new_bo, bo_handle.ptr);
+ LOGI(" plane[0] data[%p], stride[%u], size[%u], bytesused[%u]",
+ codec_buffer->planes.plane[0].data,
+ codec_buffer->planes.plane[0].stride,
+ codec_buffer->planes.plane[0].size,
+ codec_buffer->planes.plane[0].bytesused);
+ LOGI(" plane[1] data[%p], stride[%u], size[%u], bytesused[%u]",
+ codec_buffer->planes.plane[1].data,
+ codec_buffer->planes.plane[1].stride,
+ codec_buffer->planes.plane[1].size,
+ codec_buffer->planes.plane[1].bytesused);
}
- }
- /* stream on */
- ret = __codec_v4l2_stream(handle->device_fd, handle->input_buffer_control.buf_type, TRUE);
- if (ret != CODEC_ERROR_NONE) {
- LOGE("[input] stream on failed");
- goto _START_STREAM_FAILED;
+ 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_mutex_unlock(&buffer_control->lock);
+ } else {
+ /* CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT */
+ ret = __codec_v4l2_qbuf(handle->device_fd,
+ 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);
+ 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");
+ ret = __codec_v4l2_stream(handle->device_fd, codec_config->buf_type, TRUE);
+ if (ret != HAL_CODEC_ERROR_NONE) {
+ LOGE("type[%d] stream on failed", codec_config->buf_type);
goto _START_STREAM_FAILED;
}
- LOGI("done");
+ LOGI("type[%d] done", codec_config->buf_type);
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
_START_STREAM_FAILED:
- __codec_stop_stream(handle);
+ __codec_v4l2_stop_stream(handle);
return ret;
}
+#if 0
static gboolean __codec_h264_is_delta_frame(guint8 *data, uint32_t size)
{
uint32_t offset = 0;
return FALSE;
}
}
+#endif
-static void __codec_message_release_func(gpointer data)
+static void __codec_v4l2_message_release_func(gpointer data)
{
- codec_message_s *message = (codec_message_s *)data;
+ hal_codec_message_s *message = (hal_codec_message_s *)data;
if (!message) {
LOGW("NULL message");
return;
}
- LOGD("release message %p, type %d", message, message->type);
+ LOGD("release message[%p] type[%d]", message, message->type);
g_free(message);
}
-static void *_codec_message_handler_func(gpointer data)
+static void *__codec_v4l2_message_handler_func(gpointer data)
{
- int i = 0;
- codec_message_s *message = NULL;
- hal_codec_handle_s *handle = (hal_codec_handle_s *)data;
+ hal_codec_message_s *message = NULL;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)data;
if (!handle) {
LOGE("NULL handle for capture thread");
g_mutex_unlock(&handle->msg_cb_lock);
if (handle->msg_cb) {
- LOGD("call message callback[%d] type[%d]", i, message->type);
+ LOGD("call message callback - type[%d]", message->type);
handle->msg_cb(message, handle->msg_cb_data);
}
}
-static void __codec_release_handle(hal_codec_handle_s *handle)
+static void __codec_v4l2_release_handle(codec_hal_handle_s *handle)
{
if (!handle) {
LOGW("NULL handle");
LOGD("release codec HAL handle [%p]", handle);
- if (handle->msg_thread) {
+ if (handle->msg_handler) {
g_mutex_lock(&handle->msg_cb_lock);
+
handle->msg_cb_run = FALSE;
- g_cond_signal(&handle->msg_cb_cond);
+ g_cond_broadcast(&handle->msg_cb_cond);
+
g_mutex_unlock(&handle->msg_cb_lock);
- g_thread_join(handle->msg_thread);
- g_queue_free_full(handle->msg_list, (GDestroyNotify)__codec_message_release_func);
+
+ g_thread_join(handle->msg_handler);
+
+ g_queue_free_full(handle->msg_list, (GDestroyNotify)__codec_v4l2_message_release_func);
handle->msg_list = NULL;
}
- __codec_deinit_buffer_control(&handle->input_buffer_control);
- __codec_deinit_buffer_control(&handle->output_buffer_control);
+ __codec_v4l2_deinit_buffer_control(handle);
g_mutex_clear(&handle->lock);
g_mutex_clear(&handle->msg_cb_lock);
}
-static void __codec_init_buffer_control(codec_buffer_control_s *buffer_control)
+static void __codec_v4l2_init_buffer_control(codec_hal_handle_s *handle)
{
- if (!buffer_control) {
- LOGE("NULL control");
+ int i = 0;
+ codec_hal_buffer_control_s *buffer_control = NULL;
+
+ if (!handle) {
+ LOGE("NULL handle");
return;
}
- g_mutex_init(&buffer_control->lock);
- g_cond_init(&buffer_control->cond);
+ for (i = 0 ; i < CODEC_HAL_BUFFER_CONTROL_TYPE_MAX ; i++) {
+ buffer_control = &handle->buffer_control[i];
+
+ buffer_control->codec_handle = handle;
+ buffer_control->type = i;
+
+ g_mutex_init(&buffer_control->lock);
+ g_cond_init(&buffer_control->cond);
+
+ buffer_control->buffers.idle_buffers = g_queue_new();
+
+ LOGI("buffer_control[%d] init done", i);
+ }
}
-static void __codec_deinit_buffer_control(codec_buffer_control_s *buffer_control)
+static void __codec_v4l2_deinit_buffer_control(codec_hal_handle_s *handle)
{
- if (!buffer_control) {
- LOGE("NULL control");
+ int i = 0;
+ codec_hal_buffer_control_s *buffer_control = NULL;
+
+ if (!handle) {
+ LOGE("NULL handle");
return;
}
- g_mutex_clear(&buffer_control->lock);
- g_cond_clear(&buffer_control->cond);
+ for (i = 0 ; i < CODEC_HAL_BUFFER_CONTROL_TYPE_MAX ; i++) {
+ buffer_control = &handle->buffer_control[i];
+
+ g_mutex_clear(&buffer_control->lock);
+ g_cond_clear(&buffer_control->cond);
+
+ g_queue_free(buffer_control->buffers.idle_buffers);
+ buffer_control->buffers.idle_buffers = NULL;
+
+ LOGI("buffer_control[%d] deinit done", i);
+ }
}
-int codec_v4l2_init(codec_type_e type, void **codec_handle)
+int codec_v4l2_init(hal_codec_type_e type, void **codec_handle)
{
- hal_codec_handle_s *new_handle = NULL;
+ codec_hal_handle_s *new_handle = NULL;
tbm_bufmgr bufmgr = NULL;
if (!codec_handle) {
LOGE("NULL pointer for handle");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
bufmgr = tbm_bufmgr_init(-1);
if (bufmgr == NULL) {
LOGE("get tbm bufmgr failed");
- return CODEC_ERROR_INTERNAL;
+ return HAL_CODEC_ERROR_INTERNAL;
}
- new_handle = g_new0(hal_codec_handle_s, 1);
+ new_handle = g_new0(codec_hal_handle_s, 1);
new_handle->type = type;
new_handle->bufmgr = bufmgr;
g_cond_init(&new_handle->cond);
/* buffer */
- __codec_init_buffer_control(&new_handle->input_buffer_control);
- __codec_init_buffer_control(&new_handle->output_buffer_control);
+ __codec_v4l2_init_buffer_control(new_handle);
/* message */
g_mutex_init(&new_handle->msg_cb_lock);
new_handle->msg_list = g_queue_new();
new_handle->msg_cb_run = TRUE;
- new_handle->msg_thread = g_thread_try_new("codecHAL:msg",
- _codec_message_handler_func, (gpointer)new_handle, NULL);
- if (!new_handle->msg_thread) {
- LOGE("failed to create message thread");
- __codec_release_handle(new_handle);
- return CODEC_ERROR_INTERNAL;
+ new_handle->msg_handler = g_thread_try_new("codecHAL:msg",
+ __codec_v4l2_message_handler_func, (gpointer)new_handle, NULL);
+ if (!new_handle->msg_handler) {
+ LOGE("failed to create message handler");
+ __codec_v4l2_release_handle(new_handle);
+ return HAL_CODEC_ERROR_INTERNAL;
}
new_handle->device_index = CODEC_HAL_INITIAL_INDEX;
new_handle->device_fd = CODEC_HAL_INITIAL_FD;
- new_handle->state = CODEC_STATE_INITIALIZED;
+ new_handle->state = HAL_CODEC_STATE_INITIALIZED;
*codec_handle = new_handle;
LOGD("codec HAL handle [%p] - type[%s]", new_handle, g_decoder_type_string[type]);
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
int codec_v4l2_deinit(void *codec_handle)
{
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
if (!handle) {
LOGE("NULL handle");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
g_mutex_lock(&handle->lock);
- if (handle->state != CODEC_STATE_INITIALIZED) {
+ if (handle->state != HAL_CODEC_STATE_INITIALIZED) {
LOGE("invalid state [%d]", handle->state);
g_mutex_unlock(&handle->lock);
- return CODEC_ERROR_INVALID_STATE;
+ return HAL_CODEC_ERROR_INVALID_STATE;
}
g_mutex_unlock(&handle->lock);
- __codec_release_handle(handle);
+ __codec_v4l2_release_handle(handle);
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
-int codec_v4l2_configure(void *codec_handle, int width, int height, codec_format_e in_format, codec_format_e out_format, bool is_secure)
+static uint32_t __codec_v4l2_get_tbm_format(hal_codec_format_e codec_format)
{
+ switch (codec_format) {
+ case HAL_CODEC_FORMAT_NV12:
+ return TBM_FORMAT_NV12;
+ case HAL_CODEC_FORMAT_I420:
+ return TBM_FORMAT_YUV420;
+ default:
+ break;
+ }
+
+ LOGW("unhandled format[%d], return TBM_FORMAT_NV12", codec_format);
+
+ return TBM_FORMAT_NV12;
+}
+
+
+int codec_v4l2_configure(void *codec_handle, int width, int height,
+ hal_codec_format_e in_format, hal_codec_format_e out_format, bool is_secure)
+{
+ int i = 0;
int ret = 0;
int device_fd = CODEC_HAL_INITIAL_FD;
char *node_path = NULL;
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
+
enum v4l2_buf_type in_buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
enum v4l2_buf_type out_buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ tbm_surface_h surface = NULL;
+
g_autoptr(GMutexLocker) locker = NULL;
if (!handle) {
LOGE("NULL handle");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
locker = g_mutex_locker_new(&handle->lock);
- if (handle->state != CODEC_STATE_INITIALIZED) {
+ if (handle->state != HAL_CODEC_STATE_INITIALIZED) {
LOGE("invalid state %d", handle->state);
- return CODEC_ERROR_INVALID_STATE;
+ return HAL_CODEC_ERROR_INVALID_STATE;
}
- if (((in_format & CODEC_FORMAT_TYPE_ENCODED) && (out_format & CODEC_FORMAT_TYPE_ENCODED)) ||
- ((in_format & CODEC_FORMAT_TYPE_RAW) && (out_format & CODEC_FORMAT_TYPE_RAW))) {
+ if (((in_format & HAL_CODEC_FORMAT_TYPE_ENCODED) && (out_format & HAL_CODEC_FORMAT_TYPE_ENCODED)) ||
+ ((in_format & HAL_CODEC_FORMAT_TYPE_RAW) && (out_format & HAL_CODEC_FORMAT_TYPE_RAW))) {
LOGE("invalid format : in[%d], out[%d]", in_format, out_format);
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
ret = __codec_v4l2_get_buf_type_and_node_path(in_format, out_format,
&in_buf_type, &out_buf_type, &node_path);
- if (ret != CODEC_ERROR_NONE)
+ if (ret != HAL_CODEC_ERROR_NONE)
return ret;
+ surface = tbm_surface_create(width, height, __codec_v4l2_get_tbm_format(out_format));
+ if (!surface) {
+ LOGE("create surface failed [%dx%d][format:%d]", width, height, out_format);
+ return HAL_CODEC_ERROR_INTERNAL;
+ }
+
+ ret = tbm_surface_get_info(surface, &handle->ts_info);
+
+ tbm_surface_destroy(surface);
+ surface = NULL;
+
+ if (ret != TBM_SURFACE_ERROR_NONE) {
+ LOGE("get surface info failed[0x%x]", ret);
+ return HAL_CODEC_ERROR_INTERNAL;
+ }
+
+ for (i = 0 ; i < handle->ts_info.num_planes ; i++) {
+ LOGI("TBM surface plane[%d] stride[%u], size[%u], offset[%u]", i,
+ handle->ts_info.planes[i].stride,
+ handle->ts_info.planes[i].size,
+ handle->ts_info.planes[i].offset);
+ }
+
/* 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);
- return CODEC_ERROR_DEVICE_OPEN;
+ return HAL_CODEC_ERROR_DEVICE_OPEN;
}
/* set format for input */
- ret = __codec_v4l2_s_fmt(&handle->input_buffer_control,
- device_fd, in_format, in_buf_type, width, height);
- if (ret != CODEC_ERROR_NONE) {
+ ret = __codec_v4l2_set_config(&handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT],
+ in_buf_type, V4L2_MEMORY_MMAP, in_format, width, height);
+ if (ret != HAL_CODEC_ERROR_NONE)
+ return ret;
+
+ ret = __codec_v4l2_s_fmt(&handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT], device_fd);
+ if (ret != HAL_CODEC_ERROR_NONE) {
LOGE("set format[%d] for input failed - [0x%x]", in_format, ret);
close(device_fd);
return ret;
}
/* set format for output */
- 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);
+ ret = __codec_v4l2_set_config(&handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT],
+ out_buf_type, V4L2_MEMORY_DMABUF, out_format, width, height);
+ if (ret != HAL_CODEC_ERROR_NONE)
+ return ret;
+
+ ret = __codec_v4l2_s_fmt(&handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT], device_fd);
+ if (ret != HAL_CODEC_ERROR_NONE) {
+ LOGE("set format[%d] for output failed - [0x%x]", out_format, ret);
close(device_fd);
return ret;
}
- 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->is_secure = is_secure;
handle->device_fd = device_fd;
- handle->state = CODEC_STATE_CONFIGURED;
+ handle->state = HAL_CODEC_STATE_CONFIGURED;
- LOGD("done");
+ LOGD("done - secure[%d]", is_secure);
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
int codec_v4l2_release(void *codec_handle)
{
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
g_autoptr(GMutexLocker) locker = NULL;
if (!handle) {
LOGE("NULL handle");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
locker = g_mutex_locker_new(&handle->lock);
- if (handle->state != CODEC_STATE_CONFIGURED) {
+ if (handle->state != HAL_CODEC_STATE_CONFIGURED) {
LOGE("invalid state %d", handle->state);
- return CODEC_ERROR_INVALID_STATE;
+ return HAL_CODEC_ERROR_INVALID_STATE;
}
if (handle->device_fd > CODEC_HAL_INITIAL_FD) {
}
handle->device_fd = CODEC_HAL_INITIAL_FD;
- handle->state = CODEC_STATE_INITIALIZED;
+ handle->state = HAL_CODEC_STATE_INITIALIZED;
LOGD("done");
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
+}
+
+
+static int __codec_v4l2_poll(codec_hal_handle_s *handle, short events, int timeout_ms, short *revents)
+{
+ int ret = 0;
+ struct pollfd poll_fd;
+ char error_string[ERROR_STRING_LENGTH] = {'\0',};
+
+ if (!handle) {
+ LOGE("NULL handle");
+ return -1;
+ }
+
+ LOGI("device fd[%d] - events[0x%x]", handle->device_fd, events);
+
+ poll_fd.fd = handle->device_fd;
+ poll_fd.events = events;
+
+ 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);
+ } 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;
+ }
+
+ return ret;
+}
+
+
+static gpointer __codec_v4l2_buffer_handler_func(gpointer data)
+{
+ int ret = 0;
+ int error_count = 0;
+
+ short revents = 0;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)data;
+ hal_codec_buffer_s *input_buffer = NULL;
+ hal_codec_buffer_s *output_buffer = NULL;
+ codec_hal_buffer_control_s *input_control = NULL;
+ codec_hal_buffer_control_s *output_control = NULL;
+
+ if (!handle) {
+ LOGE("NULL handle");
+ return NULL;
+ }
+
+ LOGI("start - fd[%d]", handle->device_fd);
+
+ input_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT];
+ output_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT];
+
+ while (TRUE) {
+ /* exit thread with some conditions */
+ //////////////////////////////////////
+
+ ret = __codec_v4l2_poll(handle, (POLLIN | POLLOUT | POLLPRI), OUTPUT_POLL_TIMEOUT_MS, &revents);
+
+ if (ret == 0)
+ continue;
+
+ if (ret < 0)
+ break;
+
+ if (revents & POLLERR) {
+ char error_string[ERROR_STRING_LENGTH] = {'\0',};
+ strerror_r(errno, error_string, ERROR_STRING_LENGTH);
+ LOGW("POLLERR[%s]", error_string);
+
+ if (handle->is_stopping) {
+ LOGW("now stopping... stop buffer handler");
+ break;
+ } 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] exceeded", POLL_ERROR_TRY_COUNT_MAX);
+ break;
+ }
+ }
+ }
+
+ error_count = 0;
+
+ if (revents & POLLIN) {
+ output_buffer = NULL;
+
+ ret = __codec_v4l2_dqbuf(handle->device_fd,
+ output_control, &output_buffer);
+ if (ret != HAL_CODEC_ERROR_NONE || !output_buffer) {
+ LOGE("[OUTPUT] DQBUF failed[0x%x], buffer[%p]", ret, output_buffer);
+ continue;
+ }
+
+ LOGD("[OUTPUT] DQBUF index[%d]", output_buffer->index);
+
+ __codec_v4l2_message_send(handle, HAL_CODEC_MESSAGE_TYPE_OUTPUT_BUFFER, output_buffer);
+ }
+
+ if (revents & POLLOUT) {
+ input_buffer = NULL;
+
+ ret = __codec_v4l2_dqbuf(handle->device_fd,
+ input_control, &input_buffer);
+ if (ret != HAL_CODEC_ERROR_NONE || !input_buffer) {
+ LOGE("INPUT DQBUF failed[0x%x], buffer[%p]", ret, input_buffer);
+ continue;
+ }
+
+ LOGD("[INPUT] DQBUF index[%d]", input_buffer->index);
+
+ __codec_v4l2_add_idle_buffer(input_control, input_buffer);
+ }
+ }
+
+ LOGI("leave");
+
+ return NULL;
}
int codec_v4l2_start(void *codec_handle, hal_codec_message_cb callback, void *user_data)
{
int ret = 0;
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
g_autoptr(GMutexLocker) locker = NULL;
if (!handle || !callback) {
LOGE("NULL param %p %p", handle, callback);
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
locker = g_mutex_locker_new(&handle->lock);
- if (handle->state != CODEC_STATE_CONFIGURED) {
+ if (handle->state != HAL_CODEC_STATE_CONFIGURED) {
LOGE("invalid state %d", handle->state);
- return CODEC_ERROR_INVALID_STATE;
+ return HAL_CODEC_ERROR_INVALID_STATE;
}
- ret = __codec_start_stream(handle, BUFFER_MIN, BUFFER_MIN);
- if (ret != CODEC_ERROR_NONE) {
- LOGE("__codec_start_stream failed[0x%x]", ret);
+ ret = __codec_v4l2_start_stream(handle, &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT], BUFFER_MIN);
+ if (ret != HAL_CODEC_ERROR_NONE) {
+ LOGE("[input] __codec_start_stream failed[0x%x]", ret);
return ret;
}
- handle->state = CODEC_STATE_STARTED;
+ ret = __codec_v4l2_start_stream(handle, &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT], BUFFER_MIN);
+ if (ret != HAL_CODEC_ERROR_NONE) {
+ LOGE("[output] __codec_start_stream failed[0x%x]", ret);
+ return ret;
+ }
+
+ handle->msg_cb = callback;
+ handle->msg_cb_data = user_data;
+
+ handle->buffer_handler = g_thread_try_new(CODEC_THREAD_NAME_HANDLE_BUFFER,
+ __codec_v4l2_buffer_handler_func, (gpointer)handle, NULL);
+ if (!handle->buffer_handler) {
+ LOGE("failed to create buffer handler");
+ return HAL_CODEC_ERROR_INTERNAL;
+ }
+
+ handle->state = HAL_CODEC_STATE_STARTED;
- LOGD("start preview done");
+ LOGD("start codec[type:%d] done", handle->type);
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
int codec_v4l2_stop(void *codec_handle)
{
- int ret = CODEC_ERROR_NONE;
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+ int ret = HAL_CODEC_ERROR_NONE;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
g_autoptr(GMutexLocker) locker = NULL;
if (!handle) {
LOGE("NULL handle");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
LOGD("start");
locker = g_mutex_locker_new(&handle->lock);
- if (handle->state != CODEC_STATE_STARTED) {
+ if (handle->state != HAL_CODEC_STATE_STARTED) {
LOGE("invalid state %d", handle->state);
- return CODEC_ERROR_INVALID_STATE;
+ ret = HAL_CODEC_ERROR_INVALID_STATE;
+ goto _STOP_DONE;
+ }
+
+ handle->is_stopping = TRUE;
+
+ ret = __codec_v4l2_stop_stream(handle);
+ if (ret != HAL_CODEC_ERROR_NONE) {
+ LOGE("__codec_stop_stream failed[0x%x]", ret);
+ goto _STOP_DONE;
}
- ret = __codec_stop_stream(handle);
+ LOGI("join output thread");
- handle->state = CODEC_STATE_CONFIGURED;
+ g_thread_join(handle->buffer_handler);
+ handle->buffer_handler = NULL;
+ handle->state = HAL_CODEC_STATE_CONFIGURED;
+
+_STOP_DONE:
+ handle->is_stopping = FALSE;
LOGD("stop done [0x%x]", ret);
- return CODEC_ERROR_NONE;
+ return ret;
}
int codec_v4l2_flush(void *codec_handle)
{
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
+ g_autoptr(GMutexLocker) locker = NULL;
if (!handle) {
LOGE("NULL handle");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
+ locker = g_mutex_locker_new(&handle->lock);
+
+ return HAL_CODEC_ERROR_NONE;
+}
+
+
+static hal_codec_buffer_s *__codec_v4l2_get_idle_buffer(codec_hal_buffer_control_s *buffer_control, gint64 timeout_ms)
+{
+ int index = IDLE_BUFFER_INDEX_INIT;
+ gint64 end_time = 0;
g_autoptr(GMutexLocker) locker = NULL;
- locker = g_mutex_locker_new(&handle->lock);
+ if (!buffer_control) {
+ LOGE("NULL buffer control");
+ return NULL;
+ }
- return CODEC_ERROR_NONE;
+ locker = g_mutex_locker_new(&buffer_control->lock);
+
+ while (g_queue_is_empty(buffer_control->buffers.idle_buffers)) {
+ LOGD("type[%d] wait for idle buffer for %"G_GINT64_FORMAT" ms",
+ buffer_control->type, timeout_ms);
+
+ end_time = g_get_monotonic_time() + (G_TIME_SPAN_MILLISECOND * timeout_ms);
+
+ if (!g_cond_wait_until(&buffer_control->cond, &buffer_control->lock, end_time)) {
+ LOGE("type[%d] wait timed out for %"G_GINT64_FORMAT" ms", buffer_control->type, timeout_ms);
+ return NULL;
+ }
+ }
+
+ index = GPOINTER_TO_INT(g_queue_pop_head(buffer_control->buffers.idle_buffers));
+
+ LOGD("type[%d] popped buffer[%d]", buffer_control->type, index);
+
+ return &buffer_control->buffers.buffer[index];
}
-int codec_v4l2_push_input_buffer(void *codec_handle, codec_buffer_s *buffer)
+static void __codec_v4l2_add_idle_buffer(codec_hal_buffer_control_s *buffer_control, hal_codec_buffer_s *buffer)
{
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+ g_autoptr(GMutexLocker) locker = NULL;
- if (!handle) {
- LOGE("NULL handle");
- return CODEC_ERROR_INVALID_PARAMETER;
+ if (!buffer_control || !buffer) {
+ LOGE("NULL param[%p,%p]", buffer_control, buffer);
+ return;
}
+ locker = g_mutex_locker_new(&buffer_control->lock);
+
+ LOGD("add idle buffer[%d]", buffer->index);
+
+ g_queue_push_tail(buffer_control->buffers.idle_buffers, GINT_TO_POINTER(buffer->index));
+
+ g_cond_broadcast(&buffer_control->cond);
+}
+
+
+int codec_v4l2_decode(void *codec_handle, hal_codec_buffer_s *buffer)
+{
+ int ret = HAL_CODEC_ERROR_NONE;
+ hal_codec_buffer_s *idle_buffer = NULL;
+ codec_hal_buffer_control_s *buffer_control;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
g_autoptr(GMutexLocker) locker = NULL;
+ if (!handle) {
+ LOGE("NULL handle");
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
+ }
+
locker = g_mutex_locker_new(&handle->lock);
- return CODEC_ERROR_NONE;
+ if (handle->state < HAL_CODEC_STATE_STARTED) {
+ LOGE("invalid state[%d]", handle->state);
+ return HAL_CODEC_ERROR_INVALID_STATE;
+ }
+
+ buffer_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT];
+
+ idle_buffer = __codec_v4l2_get_idle_buffer(buffer_control, IDLE_BUFFER_TIME_OUT_MS);
+ if (!idle_buffer) {
+ LOGE("no idle buffer");
+ return HAL_CODEC_ERROR_INTERNAL;
+ }
+
+ memcpy(idle_buffer->planes.plane[0].data, buffer->planes.plane[0].data, buffer->planes.plane[0].bytesused);
+ memcpy(&idle_buffer->meta, &buffer->meta, sizeof(hal_codec_meta_s));
+
+ ret = __codec_v4l2_qbuf(handle->device_fd,
+ buffer_control, idle_buffer);
+ if (ret != HAL_CODEC_ERROR_NONE) {
+ LOGE("QBUF[%p] failed[i:%d], 0x%x",
+ buffer, idle_buffer->index, ret);
+ } else {
+ LOGD("QBUF[%p] done", buffer);
+ __codec_v4l2_message_send(handle, HAL_CODEC_MESSAGE_TYPE_INPUT_BUFFER_USED, buffer);
+ }
+
+ return ret;
}
int codec_v4l2_release_output_buffer(void *codec_handle, int buffer_index)
{
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+ 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");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
- g_autoptr(GMutexLocker) locker = NULL;
+ buffer_control = &handle->buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT];
- locker = g_mutex_locker_new(&handle->lock);
+ //locker = g_mutex_locker_new(&handle->lock);
+
+ ret = __codec_v4l2_qbuf(handle->device_fd,
+ buffer_control, &buffer_control->buffers.buffer[buffer_index]);
+
+ LOGI("ret[0x%x]", ret);
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
-int codec_v4l2_get_state(void *codec_handle, codec_state_e *state)
+int codec_v4l2_get_state(void *codec_handle, hal_codec_state_e *state)
{
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
if (!handle) {
LOGE("NULL handle");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
-static int __set_command(hal_codec_handle_s *handle, int64_t command, void *value)
+static int __codec_v4l2_set_command(codec_hal_handle_s *handle, int64_t command, void *value)
{
int cid = 0;
int ctrl_ret = 0;
if (!handle || !value) {
LOGE("NULL param %p %p", handle, value);
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
set_value = *(int *)value;
- if (handle->state < CODEC_STATE_OPENED) {
+ if (handle->state < HAL_CODEC_STATE_OPENED) {
LOGE("invalid state %d", handle->state);
- return CODEC_ERROR_INVALID_STATE;
+ return HAL_CODEC_ERROR_INVALID_STATE;
}
LOGI("command[%"PRIx64"] -> [%d]", command, set_value);
switch (command) {
- case CODEC_COMMAND_BITRATE:
+ case HAL_CODEC_COMMAND_BITRATE:
cid = V4L2_CID_MPEG_VIDEO_BITRATE;
set_value = *(int *)value;
break;
default:
LOGE("NOT_SUPPORTED command %"PRIx64, command);
- return CODEC_ERROR_NOT_SUPPORTED;
+ return HAL_CODEC_ERROR_NOT_SUPPORTED;
}
ctrl_ret = __codec_v4l2_s_ctrl(handle->device_fd, cid, set_value);
case EACCES:
case EPERM:
LOGE("Permission denied %d", errno);
- return CODEC_ERROR_PERMISSION_DENIED;
+ return HAL_CODEC_ERROR_PERMISSION_DENIED;
case EINVAL:
LOGE("Invalid argument");
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
case EBUSY:
LOGE("Device busy");
- return CODEC_ERROR_DEVICE_BUSY;
+ return HAL_CODEC_ERROR_DEVICE_BUSY;
case ENOTSUP:
LOGE("Not supported");
- return CODEC_ERROR_NOT_SUPPORTED;
+ return HAL_CODEC_ERROR_NOT_SUPPORTED;
default:
LOGE("Unknown errro %d", errno);
- return CODEC_ERROR_INTERNAL;
+ return HAL_CODEC_ERROR_INTERNAL;
}
}
- return CODEC_ERROR_NONE;
+ return HAL_CODEC_ERROR_NONE;
}
-int codec_v4l2_set_command(void *codec_handle, int64_t command, void *value)
+int codec_v4l2_set_command(void *codec_handle, hal_codec_command_e command, void *value)
{
- int ret = CODEC_ERROR_NONE;
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+ int ret = HAL_CODEC_ERROR_NONE;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
g_autoptr(GMutexLocker) locker = NULL;
locker = g_mutex_locker_new(&handle->lock);
- ret = __set_command(handle, command, value);
+ ret = __codec_v4l2_set_command(handle, command, value);
return ret;
}
-int codec_v4l2_get_command(void *codec_handle, int64_t command, void **value)
+int codec_v4l2_get_command(void *codec_handle, hal_codec_command_e command, void **value)
{
- int ret = CODEC_ERROR_NONE;
+ int ret = HAL_CODEC_ERROR_NONE;
int cid = 0;
int ctrl_ret = 0;
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
g_autoptr(GMutexLocker) locker = NULL;
if (!handle || !value) {
LOGE("NULL param %p %p", handle, value);
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
locker = g_mutex_locker_new(&handle->lock);
- LOGI("command[%"PRIx64"]", command);
+ LOGI("command[0x%x]", command);
switch (command) {
- case CODEC_COMMAND_BITRATE:
+ case HAL_CODEC_COMMAND_BITRATE:
cid = V4L2_CID_MPEG_VIDEO_BITRATE;
break;
default:
- LOGE("Not supported command[%"PRIx64"]", command);
- return CODEC_ERROR_NOT_SUPPORTED;
+ LOGE("Not supported command[0x%x]", command);
+ return HAL_CODEC_ERROR_NOT_SUPPORTED;
}
ctrl_ret = __codec_v4l2_g_ctrl(handle->device_fd, cid, (int *)*value);
case EACCES:
case EPERM:
LOGE("Permission denied %d", errno);
- ret = CODEC_ERROR_PERMISSION_DENIED;
+ ret = HAL_CODEC_ERROR_PERMISSION_DENIED;
break;
case EINVAL:
LOGE("Invalid argument");
- ret = CODEC_ERROR_INVALID_PARAMETER;
+ ret = HAL_CODEC_ERROR_INVALID_PARAMETER;
break;
case EBUSY:
LOGE("Device busy");
- ret = CODEC_ERROR_DEVICE_BUSY;
+ ret = HAL_CODEC_ERROR_DEVICE_BUSY;
break;
case ENOTSUP:
LOGE("Not supported");
- ret = CODEC_ERROR_NOT_SUPPORTED;
+ ret = HAL_CODEC_ERROR_NOT_SUPPORTED;
break;
default:
LOGE("Unknown errro %d", errno);
- ret = CODEC_ERROR_INTERNAL;
+ ret = HAL_CODEC_ERROR_INTERNAL;
break;
}
}
- if (ret == CODEC_ERROR_NONE)
+ if (ret == HAL_CODEC_ERROR_NONE)
LOGI("get[%d]", **(int **)value);
return ret;
}
-static void __dump_batch_command(codec_batch_command_control_s *batch_command)
+static void __dump_batch_command(hal_codec_batch_command_control_s *batch_command)
{
if (!batch_command) {
LOGE("NULL batch command");
}
-int codec_v4l2_set_batch_command(void *codec_handle, codec_batch_command_control_s *batch_command, int64_t *error_command)
+int codec_v4l2_set_batch_command(void *codec_handle, hal_codec_batch_command_control_s *batch_command, hal_codec_command_e *error_command)
{
- int ret = CODEC_ERROR_NONE;
+ int ret = HAL_CODEC_ERROR_NONE;
int i = 0;
int support_count = 0;
- hal_codec_handle_s *handle = (hal_codec_handle_s *)codec_handle;
+ codec_hal_handle_s *handle = (codec_hal_handle_s *)codec_handle;
g_autoptr(GMutexLocker) locker = NULL;
set_batch_table_s set_table[] = {
- {CODEC_COMMAND_BITRATE, batch_command ? (void *)&batch_command->bitrate : NULL},
- {CODEC_COMMAND_REQUEST_CODECDATA, NULL},
- {CODEC_COMMAND_REQUEST_SYNCFRAME, NULL}
+ {HAL_CODEC_COMMAND_BITRATE, batch_command ? (void *)&batch_command->bitrate : NULL},
+ {HAL_CODEC_COMMAND_REQUEST_CODECDATA, NULL},
+ {HAL_CODEC_COMMAND_REQUEST_SYNCFRAME, NULL}
};
if (!handle || !batch_command) {
LOGE("NULL param %p %p", handle, batch_command);
- return CODEC_ERROR_INVALID_PARAMETER;
+ return HAL_CODEC_ERROR_INVALID_PARAMETER;
}
locker = g_mutex_locker_new(&handle->lock);
if (!(batch_command->command_set_flag & set_table[i].command))
continue;
- ret = __set_command(handle, set_table[i].command, set_table[i].value);
- if (ret != CODEC_ERROR_NONE) {
- LOGE("failed command %"PRIx64", ret 0x%x", set_table[i].command, ret);
+ 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);
break;
}
}
funcs->start = codec_v4l2_start;
funcs->stop = codec_v4l2_stop;
funcs->flush = codec_v4l2_flush;
- funcs->push_input_buffer = codec_v4l2_push_input_buffer;
+ funcs->decode = codec_v4l2_decode;
funcs->release_output_buffer = codec_v4l2_release_output_buffer;
funcs->get_state = codec_v4l2_get_state;
funcs->set_command = codec_v4l2_set_command;