Replace tbm_key by tbm_fd for buffer protection 72/199272/11 accepted/tizen/unified/20190221.084210 submit/tizen/20190219.074619 submit/tizen/20190220.092629
authorJeongmo Yang <jm80.yang@samsung.com>
Fri, 8 Feb 2019 05:17:14 +0000 (14:17 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Tue, 19 Feb 2019 05:54:58 +0000 (14:54 +0900)
- Any other process can access buffer if it knows its tbm_key,
  but, there is no way to access if it's replaced by tbm_fd.

[Version] 0.4.21
[Profile] Common
[Issue Type] Update
[Dependency module] mmsvc-camera

Change-Id: I18c4560901ec097374854c94c262f6bad7730742
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
include/camera_private.h
packaging/capi-media-camera.spec
src/camera.c

index 4f24b7c..e3603de 100644 (file)
@@ -167,12 +167,14 @@ typedef struct _camera_message_s {
        muse_camera_api_e api;
        muse_camera_event_e event;
        muse_camera_event_class_e event_class;
+       int tfd[MUSE_NUM_FD];
 } camera_message_s;
 
 typedef struct _camera_idle_event_s {
        camera_cb_info_s *cb_info;
        gchar recv_msg[MUSE_CAMERA_MSG_MAX_LENGTH + 1];
        muse_camera_event_e event;
+       int tfd[MUSE_NUM_FD];
 } camera_idle_event_s;
 
 typedef struct _camera_cli_s {
@@ -181,10 +183,13 @@ typedef struct _camera_cli_s {
 } camera_cli_s;
 
 typedef struct _camera_media_packet_data {
-       int tbm_key;
+       int ret_fd;
+       tbm_fd fd;
+       tbm_fd data_fd;
+       tbm_fd buffer_fd[MUSE_NUM_FD];
        tbm_bo bo;
        tbm_bo buffer_bo[BUFFER_MAX_PLANE_NUM];
-       int num_buffer_key;
+       int num_buffer_fd;
        tbm_bo data_bo;
        int ref_cnt;
 } camera_media_packet_data;
index 875c42e..46ca000 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-camera
 Summary:    A Camera API
-Version:    0.4.20
+Version:    0.4.21
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 4237161..1971fe6 100644 (file)
@@ -50,13 +50,14 @@ static void _camera_msg_send_param1(int api, camera_cb_info_s *cb_info,
        int *ret, camera_msg_param *param, int timeout);
 static void _camera_msg_send_param2_int(int api, camera_cb_info_s *cb_info,
        int *ret, camera_msg_param *param0, camera_msg_param *param1, int timeout);
-static int _camera_import_tbm_key(tbm_bufmgr bufmgr, unsigned int tbm_key, tbm_bo *bo, tbm_bo_handle *bo_handle);
+static void _camera_msg_return_buffer(int ret_fd, camera_cb_info_s *cb_info);
+static bool _camera_import_tbm_fd(tbm_bufmgr bufmgr, int fd, tbm_bo *bo, tbm_bo_handle *bo_handle);
 static void _camera_release_imported_bo(tbm_bo *bo);
-static void _camera_preview_frame_create(camera_stream_data_s *stream, int num_buffer_key,
+static void _camera_preview_frame_create(camera_stream_data_s *stream, int num_buffer_fd,
        tbm_bo_handle *buffer_bo_handle, tbm_bo_handle *data_bo_handle, camera_preview_data_s *frame);
 static int _camera_media_packet_create(camera_cb_info_s *cb_info, camera_stream_data_s *stream,
        camera_media_packet_data *mp_data, media_packet_h *packet);
-static int _camera_media_packet_data_create(int tbm_key, int num_buffer_key, tbm_bo bo,
+static int _camera_media_packet_data_create(int ret_fd, int *tfd, int num_buffer_fd, tbm_bo bo,
        tbm_bo *buffer_bo, tbm_bo data_bo, camera_media_packet_data **mp_data);
 static void _camera_media_packet_data_release(camera_media_packet_data *mp_data, camera_cb_info_s *cb_info);
 
@@ -130,16 +131,14 @@ _DONE:
 }
 
 
-static void __camera_event_handler_preview(camera_cb_info_s *cb_info, char *recv_msg)
+static void __camera_event_handler_preview(camera_cb_info_s *cb_info, char *recv_msg, int *tfd)
 {
        int i = 0;
        int ret = 0;
-       int num_buffer_key = 0;
-       int buffer_key[BUFFER_MAX_PLANE_NUM] = {0, };
-       int tbm_key = 0;
-       int data_key = 0;
+       int ret_fd = -1;
+       int preview_fd = -1;
+       int num_buffer_fd = 0;
        unsigned char *buf_pos = NULL;
-       camera_msg_param param;
 
        tbm_bo bo = NULL;
        tbm_bo buffer_bo[BUFFER_MAX_PLANE_NUM] = {NULL, };
@@ -148,47 +147,54 @@ static void __camera_event_handler_preview(camera_cb_info_s *cb_info, char *recv
        tbm_bo data_bo = NULL;
        tbm_bo_handle data_bo_handle = {.ptr = NULL};
 
+       camera_msg_param param;
        camera_preview_data_s frame;
        camera_stream_data_s *stream = NULL;
        camera_media_packet_data *mp_data = NULL;
        media_packet_h pkt = NULL;
        media_packet_h pkt_evas = NULL;
 
-       if (!cb_info || !recv_msg) {
-               LOGE("invalid param %p %p", cb_info, recv_msg);
+       /* tfd[0]: MMCamcorderVideoStreamDataType
+          tfd[1]: data_bo or zero copy bo[0]
+          tfd[2]: zero copy bo[1]
+          tfd[3]: zero copy bo[2] */
+
+       if (!cb_info || !recv_msg || !tfd) {
+               LOGE("invalid param %p %p %p", cb_info, recv_msg, tfd);
                return;
        }
 
-       muse_camera_msg_get(tbm_key, recv_msg);
-       muse_camera_msg_get(num_buffer_key, recv_msg);
-       muse_camera_msg_get_array(buffer_key, recv_msg);
-       muse_camera_msg_get(data_key, recv_msg);
+       muse_camera_msg_get(preview_fd, recv_msg);
+       muse_camera_msg_get(num_buffer_fd, recv_msg);
+
+       /*LOGD("preview_fd %d, num_buffer_fd %d", preview_fd, num_buffer_fd);*/
 
        memset(&frame, 0x0, sizeof(camera_preview_data_s));
 
-       if (tbm_key <= 0) {
-               LOGE("invalid key %d", tbm_key);
+       if (tfd[0] < 0) {
+               LOGE("invalid fd %d", tfd[0]);
                return;
        }
 
-       CAMERA_MSG_PARAM_SET(param, INT, tbm_key);
+       ret_fd = preview_fd;
+       CAMERA_MSG_PARAM_SET(param, INT, ret_fd);
 
-       if (num_buffer_key < 0 || num_buffer_key > BUFFER_MAX_PLANE_NUM) {
-               LOGE("invalid num buffer key %d", num_buffer_key);
+       if (num_buffer_fd < 0 || num_buffer_fd > BUFFER_MAX_PLANE_NUM) {
+               LOGE("invalid num buffer fd %d", num_buffer_fd);
                goto _PREVIEW_CB_HANDLER_DONE;
        }
 
-       if (data_key > 0) {
+       if (num_buffer_fd == 0 && tfd[1] >= 0) {
                /* import tbm data_bo and get virtual address */
-               if (!_camera_import_tbm_key(cb_info->bufmgr, data_key, &data_bo, &data_bo_handle)) {
-                       LOGE("failed to import data key %d", data_key);
+               if (!_camera_import_tbm_fd(cb_info->bufmgr, tfd[1], &data_bo, &data_bo_handle)) {
+                       LOGE("failed to import data fd %d", tfd[1]);
                        goto _PREVIEW_CB_HANDLER_DONE;
                }
        }
 
        /* import tbm bo and get virtual address */
-       if (!_camera_import_tbm_key(cb_info->bufmgr, tbm_key, &bo, &bo_handle)) {
-               LOGE("failed to import key %d", tbm_key);
+       if (!_camera_import_tbm_fd(cb_info->bufmgr, tfd[0], &bo, &bo_handle)) {
+               LOGE("failed to import fd %d", tfd[0]);
                goto _PREVIEW_CB_HANDLER_DONE;
        }
 
@@ -197,24 +203,24 @@ static void __camera_event_handler_preview(camera_cb_info_s *cb_info, char *recv
        /* get stream info */
        stream = (camera_stream_data_s *)buf_pos;
 
-       for (i = 0 ; i < num_buffer_key ; i++) {
+       for (i = 0 ; i < num_buffer_fd ; i++) {
                /* import buffer bo and get virtual address */
-               if (!_camera_import_tbm_key(cb_info->bufmgr, buffer_key[i], &buffer_bo[i], &buffer_bo_handle[i])) {
-                       LOGE("failed to import buffer key %d", buffer_key[i]);
+               if (!_camera_import_tbm_fd(cb_info->bufmgr, tfd[i + 1], &buffer_bo[i], &buffer_bo_handle[i])) {
+                       LOGE("failed to import buffer fd %d", tfd[i + 1]);
                        goto _PREVIEW_CB_HANDLER_DONE;
                }
        }
 
        /* call preview callback */
        if (cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_PREVIEW]) {
-               _camera_preview_frame_create(stream, num_buffer_key, buffer_bo_handle, &data_bo_handle, &frame);
+               _camera_preview_frame_create(stream, num_buffer_fd, buffer_bo_handle, &data_bo_handle, &frame);
 
                ((camera_preview_cb)cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_PREVIEW])(&frame,
                        cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_PREVIEW]);
        }
 
        if (CHECK_PREVIEW_CB(cb_info, PREVIEW_CB_TYPE_EVAS)) {
-               ret = _camera_media_packet_data_create(tbm_key, num_buffer_key, bo, buffer_bo, data_bo, &mp_data);
+               ret = _camera_media_packet_data_create(ret_fd, tfd, num_buffer_fd, bo, buffer_bo, data_bo, &mp_data);
 
                if (ret == CAMERA_ERROR_NONE) {
                        ret = _camera_media_packet_create(cb_info, stream, mp_data, &pkt_evas);
@@ -228,7 +234,7 @@ static void __camera_event_handler_preview(camera_cb_info_s *cb_info, char *recv
 
        /* call media packet callback */
        if (cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW]) {
-               ret = _camera_media_packet_data_create(tbm_key, num_buffer_key, bo, buffer_bo, data_bo, &mp_data);
+               ret = _camera_media_packet_data_create(ret_fd, tfd, num_buffer_fd, bo, buffer_bo, data_bo, &mp_data);
 
                if (ret == CAMERA_ERROR_NONE) {
                        ret = _camera_media_packet_create(cb_info, stream, mp_data, &pkt);
@@ -261,13 +267,23 @@ static void __camera_event_handler_preview(camera_cb_info_s *cb_info, char *recv
 _PREVIEW_CB_HANDLER_DONE:
        if (mp_data == NULL) {
                /* release imported bo */
-               for (i = 0 ; i < num_buffer_key && i < BUFFER_MAX_PLANE_NUM ; i++)
+               for (i = 0 ; i < num_buffer_fd && i < BUFFER_MAX_PLANE_NUM ; i++)
                        _camera_release_imported_bo(&buffer_bo[i]);
 
                /* unmap and unref tbm bo */
                _camera_release_imported_bo(&data_bo);
                _camera_release_imported_bo(&bo);
 
+               /* close imported fd */
+               for (i = 0 ; i < MUSE_NUM_FD ; i++) {
+                       if (tfd[i] >= 0) {
+                               close(tfd[i]);
+                               tfd[i] = -1;
+                       } else {
+                               break;
+                       }
+               }
+
                /* return buffer */
                _camera_msg_send_param1(MUSE_CAMERA_API_RETURN_BUFFER, cb_info, NULL, &param, 0);
 
@@ -278,15 +294,15 @@ _PREVIEW_CB_HANDLER_DONE:
 }
 
 
-static void __camera_event_handler_capture(camera_cb_info_s *cb_info, char *recv_msg)
+static void __camera_event_handler_capture(camera_cb_info_s *cb_info, char *recv_msg, int *tfd)
 {
-       int tbm_key = 0;
-       int tbm_key_main = 0;
-       int tbm_key_post = 0;
-       int tbm_key_thumb = 0;
+       int i = 0;
+       int tfd_index = 0;
+       int capture_fd_main = 0;
+       int capture_fd_post = 0;
+       int capture_fd_thumb = 0;
        unsigned char *buf_pos = NULL;
 
-       camera_msg_param param;
        camera_image_data_s *rImage = NULL;
        camera_image_data_s *rPostview = NULL;
        camera_image_data_s *rThumbnail = NULL;
@@ -298,22 +314,21 @@ static void __camera_event_handler_capture(camera_cb_info_s *cb_info, char *recv
        tbm_bo_handle bo_post_handle = {.ptr = NULL};
        tbm_bo_handle bo_thumb_handle = {.ptr = NULL};
 
-       if (!cb_info || !recv_msg) {
-               LOGE("invalid param %p %p", cb_info, recv_msg);
+       if (!cb_info || !recv_msg || !tfd) {
+               LOGE("invalid param %p %p %p", cb_info, recv_msg, tfd);
                return;
        }
 
-       muse_camera_msg_get(tbm_key_main, recv_msg);
-       muse_camera_msg_get(tbm_key_post, recv_msg);
-       muse_camera_msg_get(tbm_key_thumb, recv_msg);
+       muse_camera_msg_get(capture_fd_main, recv_msg);
+       muse_camera_msg_get(capture_fd_post, recv_msg);
+       muse_camera_msg_get(capture_fd_thumb, recv_msg);
 
-       /*
-       LOGD("camera capture callback came in. tbm_key_main %d, tbm_key_post %d, tbm_key_thumb %d",
-               tbm_key_main, tbm_key_post, tbm_key_thumb);
-       */
+       LOGD("capture fd %d %d %d, received fd %d %d %d",
+               capture_fd_main, capture_fd_post, capture_fd_thumb,
+               tfd[0], tfd[1], tfd[2]);
 
-       if (tbm_key_main <= 0) {
-               LOGE("invalid key %d", tbm_key_main);
+       if (capture_fd_main < 0 || tfd[tfd_index] < 0) {
+               LOGE("invalid main fd %d %d", capture_fd_main, tfd[tfd_index]);
                goto _CAPTURE_CB_HANDLER_DONE;
        }
 
@@ -323,8 +338,8 @@ static void __camera_event_handler_capture(camera_cb_info_s *cb_info, char *recv
        }
 
        /* import tbm bo and get virtual address */
-       if (!_camera_import_tbm_key(cb_info->bufmgr, tbm_key_main, &bo_main, &bo_main_handle)) {
-               LOGE("failed to import key [%d] for main", tbm_key_main);
+       if (!_camera_import_tbm_fd(cb_info->bufmgr, tfd[tfd_index], &bo_main, &bo_main_handle)) {
+               LOGE("failed to import fd [%d] for main", tfd[tfd_index]);
                goto _CAPTURE_CB_HANDLER_DONE;
        }
 
@@ -341,27 +356,29 @@ static void __camera_event_handler_capture(camera_cb_info_s *cb_info, char *recv
        LOGD("image info %dx%d, size %d, EXIF info %p, size %d",
                rImage->width, rImage->height, rImage->size, rImage->exif, rImage->exif_size);
 
-       if (tbm_key_post > 0) {
+       if (capture_fd_post >= 0) {
                /* import tbm bo and get virtual address */
-               if (_camera_import_tbm_key(cb_info->bufmgr, tbm_key_post, &bo_post, &bo_post_handle)) {
+               tfd_index++;
+               if (_camera_import_tbm_fd(cb_info->bufmgr, tfd[tfd_index], &bo_post, &bo_post_handle)) {
                        buf_pos = (unsigned char *)bo_post_handle.ptr;
                        rPostview = (camera_image_data_s *)buf_pos;
                        LOGD("rPostview->size : %d", rPostview->size);
                        rPostview->data = buf_pos + sizeof(camera_image_data_s);
                } else {
-                       LOGE("failed to import key [%d] for postview", tbm_key_post);
+                       LOGE("failed to import fd [i:%d][%d] for postview", tfd_index, tfd[tfd_index]);
                }
        }
 
-       if (tbm_key_thumb > 0) {
+       if (capture_fd_thumb >= 0) {
                /* import tbm bo and get virtual address */
-               if (_camera_import_tbm_key(cb_info->bufmgr, tbm_key_thumb, &bo_thumb, &bo_thumb_handle)) {
+               tfd_index++;
+               if (_camera_import_tbm_fd(cb_info->bufmgr, tfd[tfd_index], &bo_thumb, &bo_thumb_handle)) {
                        buf_pos = (unsigned char *)bo_thumb_handle.ptr;
                        rThumbnail = (camera_image_data_s *)buf_pos;
                        LOGD("rThumbnail->size : %d", rThumbnail->size);
                        rThumbnail->data = buf_pos + sizeof(camera_image_data_s);
                } else {
-                       LOGE("failed to import key [%d] for thumbnail", tbm_key_thumb);
+                       LOGE("failed to import fd [%d] for thumbnail", tfd[tfd_index]);
                }
        }
 
@@ -370,31 +387,29 @@ static void __camera_event_handler_capture(camera_cb_info_s *cb_info, char *recv
 
 _CAPTURE_CB_HANDLER_DONE:
        /* return buffer */
-       if (tbm_key_main > 0) {
+       if (capture_fd_main >= 0) {
                _camera_release_imported_bo(&bo_main);
-
-               tbm_key = tbm_key_main;
-               CAMERA_MSG_PARAM_SET(param, INT, tbm_key);
-
-               _camera_msg_send_param1(MUSE_CAMERA_API_RETURN_BUFFER, cb_info, NULL, &param, 0);
+               _camera_msg_return_buffer(capture_fd_main, cb_info);
        }
 
-       if (tbm_key_post > 0) {
+       if (capture_fd_post >= 0) {
                _camera_release_imported_bo(&bo_post);
-
-               tbm_key = tbm_key_post;
-               CAMERA_MSG_PARAM_SET(param, INT, tbm_key);
-
-               _camera_msg_send_param1(MUSE_CAMERA_API_RETURN_BUFFER, cb_info, NULL, &param, 0);
+               _camera_msg_return_buffer(capture_fd_post, cb_info);
        }
 
-       if (tbm_key_thumb > 0) {
+       if (capture_fd_thumb >= 0) {
                _camera_release_imported_bo(&bo_thumb);
+               _camera_msg_return_buffer(capture_fd_thumb, cb_info);
+       }
 
-               tbm_key = tbm_key_thumb;
-               CAMERA_MSG_PARAM_SET(param, INT, tbm_key);
-
-               _camera_msg_send_param1(MUSE_CAMERA_API_RETURN_BUFFER, cb_info, NULL, &param, 0);
+       for (i = 0 ; i < MUSE_NUM_FD ; i++) {
+               if (tfd[i] >= 0) {
+                       LOGD("close %d", tfd[i]);
+                       close(tfd[i]);
+                       tfd[i] = -1;
+               } else {
+                       break;
+               }
        }
 
        LOGD("return buffer done");
@@ -403,33 +418,34 @@ _CAPTURE_CB_HANDLER_DONE:
 }
 
 
-static void __camera_event_handler_face_detection(camera_cb_info_s *cb_info, char *recv_msg)
+static void __camera_event_handler_face_detection(camera_cb_info_s *cb_info, char *recv_msg, int *tfd)
 {
        int count = 0;
-       int tbm_key = 0;
+       int face_fd = -1;
        camera_detected_face_s *faces = NULL;
-       camera_msg_param param;
 
        tbm_bo bo = NULL;
        tbm_bo_handle bo_handle = {.ptr = NULL};
 
-       if (!cb_info || !recv_msg) {
-               LOGE("invalid param %p %p", cb_info, recv_msg);
+       if (!cb_info || !recv_msg || !tfd) {
+               LOGE("invalid param %p %p %p", cb_info, recv_msg, tfd);
                return;
        }
 
        muse_camera_msg_get(count, recv_msg);
-       muse_camera_msg_get(tbm_key, recv_msg);
+       muse_camera_msg_get(face_fd, recv_msg);
 
        if (count >= 0 && cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_FACE_DETECTION]) {
-               LOGD("FACE_DETECTION - count %d, tbm_key %d", count, tbm_key);
+               LOGD("FACE_DETECTION - count %d, fd %d", count, tfd[0]);
 
-               if (tbm_key > 0) {
-
-                       if (_camera_import_tbm_key(cb_info->bufmgr, tbm_key, &bo, &bo_handle)) {
+               if (tfd[0] >= 0) {
+                       if (_camera_import_tbm_fd(cb_info->bufmgr, tfd[0], &bo, &bo_handle)) {
                                /* set face info */
                                faces = bo_handle.ptr;
                        }
+
+                       close(tfd[0]);
+                       tfd[0] = -1;
                }
 
                ((camera_face_detected_cb)cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_FACE_DETECTION])(faces,
@@ -438,35 +454,31 @@ static void __camera_event_handler_face_detection(camera_cb_info_s *cb_info, cha
                /* release bo */
                _camera_release_imported_bo(&bo);
        } else {
-               LOGW("skip face detection message [count %d, key %d, cb %p",
-                       count, tbm_key, cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_FACE_DETECTION]);
+               LOGW("skip face detection message [count %d, fd %d, cb %p]",
+                       count, tfd[0], cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_FACE_DETECTION]);
        }
 
        /* return buffer */
-       if (tbm_key > 0) {
-               CAMERA_MSG_PARAM_SET(param, INT, tbm_key);
-               _camera_msg_send_param1(MUSE_CAMERA_API_RETURN_BUFFER, cb_info, NULL, &param, 0);
-               /*LOGD("return buffer done");*/
-       }
+       _camera_msg_return_buffer(face_fd, cb_info);
 
        return;
 }
 
 
-static int _camera_import_tbm_key(tbm_bufmgr bufmgr, unsigned int tbm_key, tbm_bo *bo, tbm_bo_handle *bo_handle)
+static bool _camera_import_tbm_fd(tbm_bufmgr bufmgr, int fd, tbm_bo *bo, tbm_bo_handle *bo_handle)
 {
        tbm_bo tmp_bo = NULL;
        tbm_bo_handle tmp_bo_handle = {NULL, };
 
-       if (!bufmgr || !bo || !bo_handle || !tbm_key) {
-               LOGE("invalid parameter - %p %p %p, key %d",
-                    bufmgr, bo, bo_handle, tbm_key);
+       if (!bufmgr || !bo || !bo_handle || fd < 0) {
+               LOGE("invalid parameter - %p %p %p, fd %d",
+                    bufmgr, bo, bo_handle, fd);
                return false;
        }
 
-       tmp_bo = tbm_bo_import(bufmgr, tbm_key);
+       tmp_bo = tbm_bo_import_fd(bufmgr, (tbm_fd)fd);
        if (tmp_bo == NULL) {
-               LOGE("import failed - key %d", tbm_key);
+               LOGE("import failed - fd %d", fd);
                return false;
        }
 
@@ -729,6 +741,23 @@ _SEND_PARAM2_INT_DONE:
 }
 
 
+static void _camera_msg_return_buffer(int ret_fd, camera_cb_info_s *cb_info)
+{
+       camera_msg_param param;
+
+       if (ret_fd < 0) {
+               LOGW("invalid fd %d", ret_fd);
+               return;
+       }
+
+       CAMERA_MSG_PARAM_SET(param, INT, ret_fd);
+
+       _camera_msg_send_param1(MUSE_CAMERA_API_RETURN_BUFFER, cb_info, NULL, &param, 0);
+
+       return;
+}
+
+
 int _camera_get_tbm_surface_format(int in_format, uint32_t *out_format)
 {
        if (in_format <= MM_PIXEL_FORMAT_INVALID ||
@@ -842,7 +871,7 @@ int _camera_get_media_packet_mimetype(int in_format, media_format_mimetype_e *mi
        return CAMERA_ERROR_NONE;
 }
 
-static void _camera_preview_frame_create(camera_stream_data_s *stream, int num_buffer_key,
+static void _camera_preview_frame_create(camera_stream_data_s *stream, int num_buffer_fd,
        tbm_bo_handle *buffer_bo_handle, tbm_bo_handle *data_bo_handle, camera_preview_data_s *frame)
 {
        int total_size = 0;
@@ -864,7 +893,7 @@ static void _camera_preview_frame_create(camera_stream_data_s *stream, int num_b
        frame->timestamp = stream->timestamp;
        frame->num_of_planes = stream->num_planes;
 
-       if (num_buffer_key == 0) {
+       if (num_buffer_fd == 0) {
                /* non-zero copy */
                if (!data_bo_handle || !data_bo_handle->ptr) {
                        LOGE("NULL pointer");
@@ -929,7 +958,7 @@ static void _camera_preview_frame_create(camera_stream_data_s *stream, int num_b
                        break;
                case 2:
                        frame->data.double_plane.y = buffer_bo_handle[0].ptr;
-                       if (stream->num_planes == (unsigned int)num_buffer_key)
+                       if (stream->num_planes == (unsigned int)num_buffer_fd)
                                frame->data.double_plane.uv = buffer_bo_handle[1].ptr;
                        else
                                frame->data.double_plane.uv = buffer_bo_handle[0].ptr + stream->data.yuv420sp.length_y;
@@ -940,7 +969,7 @@ static void _camera_preview_frame_create(camera_stream_data_s *stream, int num_b
                        break;
                case 3:
                        frame->data.triple_plane.y = buffer_bo_handle[0].ptr;
-                       if (stream->num_planes == (unsigned int)num_buffer_key) {
+                       if (stream->num_planes == (unsigned int)num_buffer_fd) {
                                frame->data.triple_plane.u = buffer_bo_handle[1].ptr;
                                frame->data.triple_plane.v = buffer_bo_handle[2].ptr;
                        } else {
@@ -967,24 +996,39 @@ static void _camera_preview_frame_create(camera_stream_data_s *stream, int num_b
        return;
 }
 
-static int _camera_media_packet_data_create(int tbm_key, int num_buffer_key, tbm_bo bo,
+static int _camera_media_packet_data_create(int ret_fd, int *tfd, int num_buffer_fd, tbm_bo bo,
        tbm_bo *buffer_bo, tbm_bo data_bo, camera_media_packet_data **mp_data)
 {
        int i = 0;
        int ret = CAMERA_ERROR_NONE;
        camera_media_packet_data *tmp_mp_data = NULL;
 
+       if (!tfd) {
+               LOGE("NULL tfd");
+               return CAMERA_ERROR_INVALID_PARAMETER;
+       }
+
        if (*mp_data == NULL) {
                tmp_mp_data = g_new0(camera_media_packet_data, 1);
                if (tmp_mp_data) {
-                       tmp_mp_data->tbm_key = tbm_key;
-                       tmp_mp_data->num_buffer_key = num_buffer_key;
+                       tmp_mp_data->ret_fd = ret_fd;
+                       tmp_mp_data->fd = tfd[0];
+                       tmp_mp_data->num_buffer_fd = num_buffer_fd;
                        tmp_mp_data->bo = bo;
-                       tmp_mp_data->data_bo = data_bo;
-                       tmp_mp_data->ref_cnt++;
 
-                       for (i = 0 ; i < num_buffer_key ; i++)
-                               tmp_mp_data->buffer_bo[i] = buffer_bo[i];
+                       if (data_bo) {
+                               /* non-zero copy */
+                               tmp_mp_data->data_bo = data_bo;
+                               tmp_mp_data->data_fd = tfd[1];
+                       } else {
+                               /* zero copy */
+                               for (i = 0 ; i < num_buffer_fd ; i++) {
+                                       tmp_mp_data->buffer_bo[i] = buffer_bo[i];
+                                       tmp_mp_data->buffer_fd[i] = (tbm_fd)tfd[i + 1];
+                               }
+                       }
+
+                       tmp_mp_data->ref_cnt++;
 
                        *mp_data = tmp_mp_data;
                        /*LOGD("mp_data %p", tmp_mp_data);*/
@@ -1002,8 +1046,6 @@ static int _camera_media_packet_data_create(int tbm_key, int num_buffer_key, tbm
 static void _camera_media_packet_data_release(camera_media_packet_data *mp_data, camera_cb_info_s *cb_info)
 {
        int i = 0;
-       int tbm_key = 0;
-       camera_msg_param param;
 
        if (!mp_data || !cb_info) {
                LOGE("NULL pointer %p %p", mp_data, cb_info);
@@ -1014,22 +1056,28 @@ static void _camera_media_packet_data_release(camera_media_packet_data *mp_data,
                mp_data->ref_cnt--;
                LOGD("ref count %d", mp_data->ref_cnt);
        } else {
-               /* release imported bo */
-               for (i = 0 ; i < mp_data->num_buffer_key ; i++) {
+               /* release imported bo and close imported fd */
+               for (i = 0 ; i < mp_data->num_buffer_fd ; i++) {
                        tbm_bo_unref(mp_data->buffer_bo[i]);
                        mp_data->buffer_bo[i] = NULL;
+
+                       close(mp_data->buffer_fd[i]);
+                       mp_data->buffer_fd[i] = -1;
                }
 
-               /* unref tbm bo */
+               /* unref tbm bo and close imported fd */
+               close(mp_data->fd);
+               mp_data->fd = -1;
                _camera_release_imported_bo(&mp_data->bo);
+
+               if (mp_data->data_bo && mp_data->data_fd >= 0) {
+                       close(mp_data->data_fd);
+                       mp_data->data_fd = -1;
+               }
                _camera_release_imported_bo(&mp_data->data_bo);
 
                /* return buffer */
-               tbm_key = mp_data->tbm_key;
-
-               CAMERA_MSG_PARAM_SET(param, INT, tbm_key);
-
-               _camera_msg_send_param1(MUSE_CAMERA_API_RETURN_BUFFER, cb_info, NULL, &param, 0);
+               _camera_msg_return_buffer(mp_data->ret_fd, cb_info);
 
                g_free(mp_data);
                mp_data = NULL;
@@ -1049,7 +1097,7 @@ static int _camera_media_packet_create(camera_cb_info_s *cb_info, camera_stream_
        uint32_t bo_format = 0;
        int ret = 0;
        int i = 0;
-       int num_buffer_key = 0;
+       int num_buffer_fd = 0;
        tbm_bo *buffer_bo = NULL;
 
        if (cb_info == NULL || stream == NULL || mp_data == NULL || packet == NULL) {
@@ -1060,7 +1108,7 @@ static int _camera_media_packet_create(camera_cb_info_s *cb_info, camera_stream_
 
        memset(&tsurf_info, 0x0, sizeof(tbm_surface_info_s));
        buffer_bo = mp_data->buffer_bo;
-       num_buffer_key = mp_data->num_buffer_key;
+       num_buffer_fd = mp_data->num_buffer_fd;
 
        /* create tbm surface */
        for (i = 0 ; i < BUFFER_MAX_PLANE_NUM ; i++)
@@ -1077,14 +1125,14 @@ static int _camera_media_packet_create(camera_cb_info_s *cb_info, camera_stream_
                tsurf_info.bpp = tbm_surface_internal_get_bpp(bo_format);
                tsurf_info.num_planes = tbm_surface_internal_get_num_planes(bo_format);
 
-               if (num_buffer_key > 0) {
+               if (num_buffer_fd > 0) {
                        switch (bo_format) {
                        case TBM_FORMAT_NV12:
                        case TBM_FORMAT_NV21:
                                tsurf_info.planes[0].size = stream->stride[0] * stream->elevation[0];
                                tsurf_info.planes[1].size = stream->stride[1] * stream->elevation[1];
                                tsurf_info.planes[0].offset = 0;
-                               if (num_buffer_key == 1)
+                               if (num_buffer_fd == 1)
                                        tsurf_info.planes[1].offset = tsurf_info.planes[0].size;
                                tsurf_info.size = tsurf_info.planes[0].size + tsurf_info.planes[1].size;
                                break;
@@ -1094,7 +1142,7 @@ static int _camera_media_packet_create(camera_cb_info_s *cb_info, camera_stream_
                                tsurf_info.planes[1].size = stream->stride[1] * stream->elevation[1];
                                tsurf_info.planes[2].size = stream->stride[2] * stream->elevation[2];
                                tsurf_info.planes[0].offset = 0;
-                               if (num_buffer_key == 1) {
+                               if (num_buffer_fd == 1) {
                                        tsurf_info.planes[1].offset = tsurf_info.planes[0].size;
                                        tsurf_info.planes[2].offset = tsurf_info.planes[0].size + tsurf_info.planes[1].size;
                                }
@@ -1110,7 +1158,7 @@ static int _camera_media_packet_create(camera_cb_info_s *cb_info, camera_stream_
                                break;
                        }
 
-                       tsurf = tbm_surface_internal_create_with_bos(&tsurf_info, buffer_bo, num_buffer_key);
+                       tsurf = tbm_surface_internal_create_with_bos(&tsurf_info, buffer_bo, num_buffer_fd);
                } else if (mp_data->data_bo) {
                        switch (bo_format) {
                        case TBM_FORMAT_NV12:
@@ -1191,8 +1239,8 @@ static int _camera_media_packet_create(camera_cb_info_s *cb_info, camera_stream_
                        tsurf = NULL;
                }
        } else {
-               LOGE("tbm surface failed. %dx%d, format %d, num_buffer_key %d, data_bo %p",
-                       stream->width, stream->height, stream->format, num_buffer_key, mp_data->data_bo);
+               LOGE("tbm surface failed. %dx%d, format %d, num_buffer_fd %d, data_bo %p",
+                       stream->width, stream->height, stream->format, num_buffer_fd, mp_data->data_bo);
        }
 
        if (pkt) {
@@ -1258,7 +1306,7 @@ int _camera_media_packet_finalize(media_packet_h pkt, int error_code, void *user
        return MEDIA_PACKET_FINALIZE;
 }
 
-static void _camera_client_user_callback(camera_cb_info_s *cb_info, char *recv_msg, muse_camera_event_e event)
+static void _camera_client_user_callback(camera_cb_info_s *cb_info, char *recv_msg, muse_camera_event_e event, int *tfd)
 {
        int param1 = 0;
        int param2 = 0;
@@ -1325,7 +1373,7 @@ static void _camera_client_user_callback(camera_cb_info_s *cb_info, char *recv_m
                break;
        case MUSE_CAMERA_EVENT_TYPE_PREVIEW:
        case MUSE_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW:
-               __camera_event_handler_preview(cb_info, recv_msg);
+               __camera_event_handler_preview(cb_info, recv_msg, tfd);
                break;
        case MUSE_CAMERA_EVENT_TYPE_HDR_PROGRESS:
                {
@@ -1369,7 +1417,7 @@ static void _camera_client_user_callback(camera_cb_info_s *cb_info, char *recv_m
                }
                break;
        case MUSE_CAMERA_EVENT_TYPE_FACE_DETECTION:
-               __camera_event_handler_face_detection(cb_info, recv_msg);
+               __camera_event_handler_face_detection(cb_info, recv_msg, tfd);
                break;
        case MUSE_CAMERA_EVENT_TYPE_ERROR:
                {
@@ -1439,7 +1487,7 @@ static void _camera_client_user_callback(camera_cb_info_s *cb_info, char *recv_m
                }
                break;
        case MUSE_CAMERA_EVENT_TYPE_CAPTURE:
-               __camera_event_handler_capture(cb_info, recv_msg);
+               __camera_event_handler_capture(cb_info, recv_msg, tfd);
                break;
        default:
                LOGW("unhandled event %d", event);
@@ -1478,7 +1526,7 @@ static gboolean _camera_idle_event_callback(gpointer data)
        g_mutex_unlock(&g_cam_idle_event_lock);
 
        /* user callback */
-       _camera_client_user_callback(cb_info, cam_idle_event->recv_msg, cam_idle_event->event);
+       _camera_client_user_callback(cb_info, cam_idle_event->recv_msg, cam_idle_event->event, cam_idle_event->tfd);
 
 IDLE_EVENT_CALLBACK_DONE:
        /* release event */
@@ -1557,7 +1605,7 @@ static void *_camera_msg_handler_func(gpointer data)
                } else if (api == MUSE_CAMERA_CB_EVENT) {
                        switch (cam_msg->event_class) {
                        case MUSE_CAMERA_EVENT_CLASS_THREAD_SUB:
-                               _camera_client_user_callback(cb_info, cam_msg->recv_msg, cam_msg->event);
+                               _camera_client_user_callback(cb_info, cam_msg->recv_msg, cam_msg->event, cam_msg->tfd);
                                break;
                        case MUSE_CAMERA_EVENT_CLASS_THREAD_MAIN:
                                cam_idle_event = g_new0(camera_idle_event_s, 1);
@@ -1570,6 +1618,7 @@ static void *_camera_msg_handler_func(gpointer data)
                                cam_idle_event->cb_info = cb_info;
 
                                strncpy(cam_idle_event->recv_msg, cam_msg->recv_msg, sizeof(cam_idle_event->recv_msg) - 1);
+                               memcpy(cam_idle_event->tfd, cam_msg->tfd, sizeof(cam_idle_event->tfd));
 
                                /*LOGD("t:%d add camera event[%d, %p] to IDLE", type, cam_msg->event, cam_idle_event);*/
 
@@ -1673,7 +1722,7 @@ static void _camera_deactivate_idle_event_all(camera_cb_info_s *cb_info)
 }
 
 
-static void __camera_add_msg_to_queue(camera_cb_info_s *cb_info, int api, int event, int event_class, char *msg)
+static void __camera_add_msg_to_queue(camera_cb_info_s *cb_info, int api, int event, int event_class, char *msg, int *tfd)
 {
        camera_message_s *cam_msg = NULL;
 
@@ -1692,6 +1741,9 @@ static void __camera_add_msg_to_queue(camera_cb_info_s *cb_info, int api, int ev
        cam_msg->event = event;
        cam_msg->event_class = event_class;
 
+       if (tfd && tfd[0] >= 0)
+               memcpy(cam_msg->tfd, tfd, sizeof(cam_msg->tfd));
+
        strncpy(cam_msg->recv_msg, msg, sizeof(cam_msg->recv_msg) - 1);
 
        /*LOGD("add camera message to queue : api %d, event %d, event_class %d", api, event, event_class);*/
@@ -1719,7 +1771,7 @@ static void __camera_add_msg_to_queue(camera_cb_info_s *cb_info, int api, int ev
 }
 
 
-static void __camera_process_msg(camera_cb_info_s *cb_info, char *msg)
+static void __camera_process_msg(camera_cb_info_s *cb_info, char *msg, int *tfd)
 {
        int ret = CAMERA_ERROR_NONE;
        int api = -1;
@@ -1832,7 +1884,7 @@ static void __camera_process_msg(camera_cb_info_s *cb_info, char *msg)
 
                g_mutex_unlock(&cb_info->api_mutex[api]);
        } else if (api_class == MUSE_CAMERA_API_CLASS_THREAD_SUB || api == MUSE_CAMERA_CB_EVENT) {
-               __camera_add_msg_to_queue(cb_info, api, event, event_class, msg);
+               __camera_add_msg_to_queue(cb_info, api, event, event_class, msg, tfd);
        } else {
                LOGW("unknown camera api %d, class %d", api, api_class);
        }
@@ -1843,15 +1895,10 @@ static void __camera_process_msg(camera_cb_info_s *cb_info, char *msg)
 
 static void *_camera_msg_recv_func(gpointer data)
 {
+       int i = 0;
        int recv_length = 0;
-       int single_length = 0;
-       int remained_length = 0;
+       int tfd[MUSE_NUM_FD] = {-1, -1, -1, -1};
        char *recv_msg = NULL;
-       char *single_msg = NULL;
-       char *remained_msg = NULL;
-       int num_msg = 0;
-       int cur_pos = 0;
-       int prev_pos = 0;
        camera_cb_info_s *cb_info = (camera_cb_info_s *)data;
 
        if (!cb_info) {
@@ -1861,92 +1908,29 @@ static void *_camera_msg_recv_func(gpointer data)
 
        LOGD("start - fd : %d", cb_info->fd);
 
-       single_msg = (char *)malloc(sizeof(char) * MUSE_CAMERA_MSG_MAX_LENGTH);
-       if (!single_msg) {
-               LOGE("single_msg malloc failed");
-               return NULL;
-       }
-
        recv_msg = cb_info->recv_msg;
 
        while (g_atomic_int_get(&cb_info->msg_recv_running)) {
-               recv_length = muse_core_msg_recv(cb_info->fd, recv_msg, MUSE_MSG_MAX_LENGTH);
+               for (i = 0 ; i < MUSE_NUM_FD ; i++)
+                       tfd[i] = -1;
+
+               recv_length = muse_core_msg_recv_fd(cb_info->fd, recv_msg, MUSE_MSG_MAX_LENGTH, tfd);
                if (recv_length <= 0) {
                        cb_info->is_server_connected = FALSE;
                        LOGE("receive msg failed - server disconnected");
                        break;
                }
 
-               cur_pos = 0;
-               prev_pos = 0;
-               num_msg = 0;
-
-               /*LOGD("recv msg : %s, length : %d", recv_msg, recv_length);*/
-
-               /* Need to split the combined entering msgs */
-               for (cur_pos = 0 ; cur_pos < recv_length ; cur_pos++) {
-                       if (recv_msg[cur_pos] == '}') {
-                               single_length = cur_pos - prev_pos + 1;
-
-                               if (single_length < MUSE_CAMERA_MSG_MAX_LENGTH) {
-                                       /* check remained msg */
-                                       if (remained_length > 0) {
-                                               if (remained_msg) {
-                                                       strncpy(single_msg, remained_msg, remained_length);
-                                                       strncpy(single_msg + remained_length, recv_msg + prev_pos, single_length);
-                                                       single_msg[remained_length + single_length] = '\0';
-
-                                                       free(remained_msg);
-                                                       remained_msg = NULL;
-                                               } else {
-                                                       strncpy(single_msg, recv_msg + prev_pos, single_length);
-                                                       single_msg[single_length] = '\0';
-                                                       LOGE("lost msg [%s], skip...", single_msg);
-                                               }
-
-                                               remained_length = 0;
-                                       } else {
-                                               strncpy(single_msg, recv_msg + prev_pos, single_length);
-                                               single_msg[single_length] = '\0';
-                                       }
-
-                                       if (single_msg[0] == '{') {
-                                               num_msg++;
-                                               /*LOGD("splitted msg : [%s], Index : %d", single_msg, num_msg);*/
-                                               /* process each message */
-                                               __camera_process_msg(cb_info, single_msg);
-                                       } else {
-                                               LOGE("invalid msg [%s]", single_msg);
-                                       }
-                               } else {
-                                       LOGE("too long message [len %d] skip...", single_length);
-                               }
-
-                               prev_pos = cur_pos + 1;
-                       }
-               }
-
-               /* check incompleted message */
-               if (recv_msg[recv_length - 1] != '}') {
-                       remained_length = recv_length - prev_pos;
+               /*
+               if (tfd[0] >= 0)
+                       LOGD("%d %d %d %d", tfd[0], tfd[1], tfd[2], tfd[3]);
+               */
 
-                       LOGW("incompleted message [len %d]", remained_length);
+               recv_msg[recv_length] = '\0';
 
-                       if (remained_msg) {
-                               free(remained_msg);
-                               remained_msg = NULL;
-                       }
+               /*LOGD("recv msg : %s, length : %d", recv_msg, recv_length);*/
 
-                       remained_msg = (char *)malloc(remained_length + 1);
-                       if (remained_msg) {
-                               strncpy(remained_msg, recv_msg + prev_pos, remained_length);
-                               remained_msg[remained_length] = '\0';
-                       } else {
-                               LOGE("failed to alloc for remained msg");
-                       }
-               } else {
-                       remained_length = 0;
-               }
+               __camera_process_msg(cb_info, recv_msg, tfd);
        }
 
        LOGD("client cb exit - server connected %d", cb_info->is_server_connected);
@@ -1974,7 +1958,8 @@ static void *_camera_msg_recv_func(gpointer data)
                        MUSE_CAMERA_CB_EVENT,
                        MUSE_CAMERA_EVENT_TYPE_ERROR,
                        MUSE_CAMERA_EVENT_CLASS_THREAD_MAIN,
-                       error_msg);
+                       error_msg,
+                       NULL);
 
                muse_core_msg_free(error_msg);
                error_msg = NULL;
@@ -1983,16 +1968,6 @@ static void *_camera_msg_recv_func(gpointer data)
        }
 
 CB_HANDLER_EXIT:
-       if (single_msg) {
-               free(single_msg);
-               single_msg = NULL;
-       }
-
-       if (remained_msg) {
-               free(remained_msg);
-               remained_msg = NULL;
-       }
-
        return NULL;
 }