Update functions
authorJeongmo Yang <jm80.yang@samsung.com>
Fri, 15 Nov 2024 11:37:13 +0000 (20:37 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Mon, 13 Jan 2025 11:11:29 +0000 (20:11 +0900)
1. Implement decode().
2. Rename internal functions.
3. Handle buffers for input and output.

Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
packaging/hal-backend-codec-v4l2.spec
src/hal_backend_codec_v4l2.c
src/hal_backend_codec_v4l2_private.h

index 5b502c1bcfe69611bf82b24654a54d96f3cbddd4..d4cc836c8f69b1893dbe82b6d7dc476f3142736a 100644 (file)
@@ -1,6 +1,8 @@
+%define disable_hal_rootstrap_checker 1
+
 Name:       hal-backend-codec-v4l2
 Summary:    Tizen Codec HAL using generic V4L2 interface
-Version:    1.0.0
+Version:    0.0.1
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0
index 840c44e97de0fc52b414f1c735aefb7358067a26..c88471f9bc8c46e183e4c9e9f6ac1609b58a37c3 100644 (file)
@@ -33,8 +33,8 @@
 #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 {
@@ -96,8 +118,8 @@ typedef struct _codec_v4l2_device_list_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"
 };
 
 
@@ -105,15 +127,28 @@ static char *g_decoder_type_string[DEVICE_TYPE_MAX] = {
 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);
 
 
 
@@ -137,7 +172,7 @@ static void __codec_v4l2_get_supported_format_list(int device_fd,
 {
        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) {
@@ -158,14 +193,14 @@ static void __codec_v4l2_get_supported_format_list(int device_fd,
                        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;
                }
        }
 
@@ -194,16 +229,16 @@ static int __codec_v4l2_probe_device(void)
                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;
                }
        }
 
@@ -265,10 +300,10 @@ static int __codec_v4l2_probe_device(void)
                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;
 
@@ -295,7 +330,7 @@ static int __codec_v4l2_probe_device(void)
                g_codec_device_list = NULL;
        }
 
-       return CODEC_ERROR_NONE;
+       return HAL_CODEC_ERROR_NONE;
 }
 
 
@@ -334,7 +369,7 @@ static void __codec_v4l2_release_device_list(void)
 }
 
 
-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;
@@ -344,12 +379,12 @@ static int __codec_v4l2_get_buf_type_and_node_path(codec_format_e in_format, cod
 
        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++) {
@@ -382,20 +417,20 @@ static int __codec_v4l2_get_buf_type_and_node_path(codec_format_e in_format, cod
                                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) {
@@ -403,73 +438,34 @@ static void __codec_v4l2_send_message(hal_codec_handle_s *handle, codec_message_
                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);
 }
 
 
@@ -480,7 +476,7 @@ static int __codec_v4l2_g_ctrl(int device_fd, int cid, int *value)
 
        if (!value) {
                LOGE("NULL param");
-               return CODEC_ERROR_INVALID_PARAMETER;
+               return HAL_CODEC_ERROR_INVALID_PARAMETER;
        }
 
        memset(&ctrl, 0x0, sizeof(struct v4l2_control));
@@ -516,75 +512,92 @@ static int __codec_v4l2_s_ctrl(int device_fd, int cid, int value)
 }
 
 
-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;
 }
 
 
@@ -592,17 +605,17 @@ static int __codec_v4l2_stream(int device_fd, int type, gboolean onoff)
 {
        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;
 }
 
 
@@ -612,10 +625,10 @@ static int __codec_v4l2_reqbufs(int device_fd, int type, int memory, uint32_t co
 
        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));
 
@@ -625,7 +638,7 @@ static int __codec_v4l2_reqbufs(int device_fd, int type, int memory, uint32_t co
 
        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)
@@ -634,461 +647,487 @@ static int __codec_v4l2_reqbufs(int device_fd, int type, int memory, uint32_t co
        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;
@@ -1145,18 +1184,19 @@ CHECK_AGAIN:
                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);
 
@@ -1164,11 +1204,10 @@ static void __codec_message_release_func(gpointer data)
 }
 
 
-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");
@@ -1200,7 +1239,7 @@ static void *_codec_message_handler_func(gpointer data)
                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);
                }
 
@@ -1217,7 +1256,7 @@ static void *_codec_message_handler_func(gpointer 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");
@@ -1226,18 +1265,21 @@ static void __codec_release_handle(hal_codec_handle_s *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);
@@ -1254,32 +1296,58 @@ static void __codec_release_handle(hal_codec_handle_s *handle)
 }
 
 
-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;
 
@@ -1287,16 +1355,16 @@ int codec_v4l2_init(codec_type_e type, void **codec_handle)
 
        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;
@@ -1305,8 +1373,7 @@ int codec_v4l2_init(codec_type_e type, void **codec_handle)
        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);
@@ -1314,140 +1381,191 @@ int codec_v4l2_init(codec_type_e type, void **codec_handle)
 
        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) {
@@ -1458,141 +1576,384 @@ int codec_v4l2_release(void *codec_handle)
        }
 
        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;
@@ -1600,26 +1961,26 @@ static int __set_command(hal_codec_handle_s *handle, int64_t command, void *valu
 
        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);
@@ -1628,64 +1989,64 @@ static int __set_command(hal_codec_handle_s *handle, int64_t command, void *valu
                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);
@@ -1694,35 +2055,35 @@ int codec_v4l2_get_command(void *codec_handle, int64_t command, void **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");
@@ -1735,22 +2096,22 @@ static void __dump_batch_command(codec_batch_command_control_s *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);
@@ -1765,9 +2126,9 @@ int codec_v4l2_set_batch_command(void *codec_handle, codec_batch_command_control
                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;
                }
        }
@@ -1796,7 +2157,7 @@ static int codec_v4l2_backend_init(void **data)
        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;
index b9e3c0f1a1d198abd947bcf6bac4bd508d488d12..51acde6bba017b81a7b6198084bf7fe84ffcaf99 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/videodev2.h>
 #include <glib.h>
 #include <tbm_bufmgr.h>
+#include <tbm_surface.h>
 #include <hal/hal-common-interface.h>
 #include <hal/hal-codec-interface.h>
 
 #define V4L2_PLANES_MAX                 4
 
 
-typedef struct _set_batch_table_s {
-       int64_t command;
+typedef enum {
+       CODEC_HAL_BUFFER_CONTROL_TYPE_INPUT = 0,
+       CODEC_HAL_BUFFER_CONTROL_TYPE_OUTPUT,
+       CODEC_HAL_BUFFER_CONTROL_TYPE_MAX
+} codec_hal_buffer_control_type_e;
+
+typedef enum {
+       CODEC_HAL_QUEUE_ELEMENT_TYPE_NONE = 0,
+       CODEC_HAL_QUEUE_ELEMENT_TYPE_BUFFER
+} codec_hal_queue_element_type_e;
+
+typedef struct {
+       hal_codec_command_e command;
        void *value;
 } set_batch_table_s;
 
-typedef struct _codec_tbm_buffer_s {
-       tbm_bo bo;
-       tbm_bo_handle bo_handle;
-       int dmabuf_fd;
-} codec_tbm_buffer_s;
-
-typedef struct _codec_hal_buffer_control_s {
-       gboolean is_run;
-       guint32 count;
-       guint32 queued_count;
+typedef struct {
+       enum v4l2_buf_type buf_type;
+       enum v4l2_memory memory;
+       hal_codec_format_e format;
+       hal_codec_resolution_s resolution;
+       uint32_t num_planes;
+       uint32_t buffer_size;
+} codec_hal_config_s;
+
+typedef struct {
+       uint32_t count;
+       hal_codec_buffer_s buffer[BUFFER_MAX];
+       tbm_bo bo[BUFFER_MAX][HAL_CODEC_BUFFER_PLANE_MAX];
+       GQueue *idle_buffers;
+} codec_hal_buffers_s;
+
+typedef struct {
+       int device_fd;
+       codec_hal_buffer_control_type_e type;
        GMutex lock;
        GCond cond;
-       enum v4l2_buf_type buf_type;
-       enum v4l2_memory memory_type;
-       codec_buffer_s buffers[BUFFER_MAX];
-} codec_buffer_control_s;
+       codec_hal_config_s config;
+       codec_hal_buffers_s buffers;
+       void *codec_handle;
+} codec_hal_buffer_control_s;
 
-typedef struct _codec_hal_handle_s {
-       codec_type_e type;
+typedef struct {
+       hal_codec_type_e type;
 
        /* tbm */
        tbm_bufmgr bufmgr;
@@ -66,13 +87,12 @@ typedef struct _codec_hal_handle_s {
        gint32 device_fd;
 
        /* buffer */
-       codec_buffer_control_s input_buffer_control;
-       codec_buffer_control_s output_buffer_control;
-       GThread *output_thread;
-       gboolean output_thread_run;
+       codec_hal_buffer_control_s buffer_control[CODEC_HAL_BUFFER_CONTROL_TYPE_MAX];
+       tbm_surface_info_s ts_info;
+       GThread *buffer_handler;
 
        /* message */
-       GThread *msg_thread;
+       GThread *msg_handler;
        hal_codec_message_cb msg_cb;
        gpointer msg_cb_data;
        gboolean msg_cb_run;
@@ -86,21 +106,27 @@ typedef struct _codec_hal_handle_s {
        /* etc */
        GMutex lock;
        GCond cond;
-       codec_state_e state;
-} hal_codec_handle_s;
+       hal_codec_state_e state;
+       gboolean is_stopping;
+
+       /* secure */
+       gboolean is_secure;
+} codec_hal_handle_s;
+
 
-int codec_v4l2_init(codec_type_e type, void **codec_handle);
+int codec_v4l2_init(hal_codec_type_e type, void **codec_handle);
 int codec_v4l2_deinit(void *codec_handle);
-int codec_v4l2_configure(void *codec_handle, int width, int height, codec_format_e in_format, codec_format_e out_format, bool is_secure);
+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 codec_v4l2_release(void *codec_handle);
 int codec_v4l2_start(void *codec_handle, hal_codec_message_cb callback, void *user_data);
 int codec_v4l2_stop(void *codec_handle);
 int codec_v4l2_flush(void *codec_handle);
-int codec_v4l2_push_input_buffer(void *codec_handle, codec_buffer_s *buffer);
+int codec_v4l2_decode(void *codec_handle, hal_codec_buffer_s *buffer);
 int codec_v4l2_release_output_buffer(void *codec_handle, int buffer_index);
-int codec_v4l2_get_state(void *codec_handle, codec_state_e *state);
-int codec_v4l2_set_command(void *codec_handle, int64_t command, void *value);
-int codec_v4l2_get_command(void *codec_handle, int64_t command, void **value);
-int codec_v4l2_set_batch_command(void *codec_handle, codec_batch_command_control_s *batch_command, int64_t *error_command);
+int codec_v4l2_get_state(void *codec_handle, hal_codec_state_e *state);
+int codec_v4l2_set_command(void *codec_handle, hal_codec_command_e command, void *value);
+int codec_v4l2_get_command(void *codec_handle, hal_codec_command_e command, void **value);
+int codec_v4l2_set_batch_command(void *codec_handle, hal_codec_batch_command_control_s *batch_command, hal_codec_command_e *error_command);
 
 #endif /* __HAL_BACKEND_CODEC_V4L2_PRIVATE_H__ */