Release version 0.2.12 10/51610/4 accepted/tizen/mobile/20151117.005439 accepted/tizen/tv/20151117.005455 accepted/tizen/wearable/20151117.005506 submit/tizen/20151116.054236
authorJeongmo Yang <jm80.yang@samsung.com>
Wed, 11 Nov 2015 07:16:04 +0000 (16:16 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Wed, 11 Nov 2015 08:47:28 +0000 (17:47 +0900)
1. Update code for preview callback - support zero copy
2. Add code for media packet preview callback

Change-Id: Iff095cd3f04a041334acca14d029b9042c068d26
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
legacy/include/legacy_camera.h
legacy/include/legacy_camera_private.h
legacy/src/legacy_camera.c
muse/CMakeLists.txt
muse/include/muse_camera.h
muse/include/muse_camera_msg.h
muse/src/muse_camera_dispatcher.c
packaging/mmsvc-camera.spec

index d6331ff..b7ce85f 100755 (executable)
@@ -19,6 +19,7 @@
 
 #include <tizen.h>
 #include <media_packet.h>
+#include <mm_camcorder.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -553,24 +554,7 @@ typedef void (*camera_focus_changed_cb)(camera_focus_state_e state, void *user_d
  * @see        camera_set_preview_cb()
  * @see        camera_unset_preview_cb()
  */
-typedef void (*camera_preview_cb)(camera_preview_data_s *frame, void *user_data);
-
-/**
- * @brief Called to register for notifications about delivering media packet when every preview frame is displayed.
- * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif
- *
- * @remarks This function is issued in the context of gstreamer so the UI update code should not be directly invoked.\n
- *          If the camera is used as a recorder then this callback function won't be called.\n
- *          and the packet should be released by media_packet_destroy() after use.
- *
- * @param[in] pkt Reference pointer to media packet
- * @param[in] user_data The user data passed from the callback registration function
- * @pre        camera_start_preview() will invoke this callback function if you register this callback using camera_set_media_packet_preview_cb().
- * @see        camera_start_preview()
- * @see        camera_set_media_packet_preview_cb()
- * @see        camera_unset_media_packet_preview_cb()
- */
-typedef void (*camera_media_packet_preview_cb)(media_packet_h pkt, void *user_data);
+typedef void (*camera_preview_cb)(MMCamcorderVideoStreamDataType *frame, void *user_data);
 
 /**
  * @brief Called to get information about image data taken by the camera once per frame while capturing.
@@ -1636,7 +1620,7 @@ int legacy_camera_unset_preview_cb(camera_h camera);
  * @see        camera_unset_media_packet_preview_cb()
  * @see        camera_media_packet_preview_cb()
  */
-int legacy_camera_set_media_packet_preview_cb(camera_h camera, camera_media_packet_preview_cb callback, void *user_data);
+int legacy_camera_set_media_packet_preview_cb(camera_h camera, camera_preview_cb callback, void *user_data);
 
 /**
  * @brief Unregisters the media packet callback function.
index 7f3e856..5f7596d 100755 (executable)
@@ -90,9 +90,6 @@ int __camera_start_continuous_focusing(camera_h camera);
 int _camera_set_use(camera_h camera, bool used);
 bool _camera_is_used(camera_h camera);
 void _camera_remove_cb_message(camera_s *handle);
-int _camera_get_tbm_surface_format(int in_format, uint32_t *out_format);
-int _camera_get_media_packet_mimetype(int in_format, media_format_mimetype_e *mimetype);
-int _camera_media_packet_finalize(media_packet_h pkt, int error_code, void *user_data);
 int __convert_camera_error_code(const char* func, int code);
 
 #ifdef __cplusplus
index f8bb72a..48a88d8 100755 (executable)
@@ -211,196 +211,9 @@ static gboolean __mm_videostream_callback(MMCamcorderVideoStreamDataType *stream
 
        camera_s *handle = (camera_s *)user_data;
 
-       if (handle->user_cb[_CAMERA_EVENT_TYPE_PREVIEW]) {
-               camera_preview_data_s frame;
-
-               if (stream->format == MM_PIXEL_FORMAT_ITLV_JPEG_UYVY) {
-                       frame.format  = MM_PIXEL_FORMAT_UYVY;
-               } else {
-                       frame.format = stream->format;
-               }
-               frame.width = stream->width;
-               frame.height = stream->height;
-               frame.timestamp = stream->timestamp;
-               frame.num_of_planes = stream->num_planes;
-
-               switch (stream->data_type) {
-               case MM_CAM_STREAM_DATA_YUV420:
-                       frame.data.single_plane.yuv = stream->data.yuv420.yuv;
-                       frame.data.single_plane.size = stream->data.yuv420.length_yuv;
-                       break;
-               case MM_CAM_STREAM_DATA_YUV422:
-                       frame.data.single_plane.yuv = stream->data.yuv422.yuv;
-                       frame.data.single_plane.size = stream->data.yuv422.length_yuv;
-                       break;
-               case MM_CAM_STREAM_DATA_YUV420SP:
-                       frame.data.double_plane.y = stream->data.yuv420sp.y;
-                       frame.data.double_plane.uv = stream->data.yuv420sp.uv;
-                       frame.data.double_plane.y_size = stream->data.yuv420sp.length_y;
-                       frame.data.double_plane.uv_size = stream->data.yuv420sp.length_uv;
-                       break;
-               case MM_CAM_STREAM_DATA_YUV420P:
-                       frame.data.triple_plane.y = stream->data.yuv420p.y;
-                       frame.data.triple_plane.u = stream->data.yuv420p.u;
-                       frame.data.triple_plane.v = stream->data.yuv420p.v;
-                       frame.data.triple_plane.y_size = stream->data.yuv420p.length_y;
-                       frame.data.triple_plane.u_size = stream->data.yuv420p.length_u;
-                       frame.data.triple_plane.v_size = stream->data.yuv420p.length_v;
-                       break;
-               case MM_CAM_STREAM_DATA_YUV422P:
-                       frame.data.triple_plane.y = stream->data.yuv422p.y;
-                       frame.data.triple_plane.u = stream->data.yuv422p.u;
-                       frame.data.triple_plane.v = stream->data.yuv422p.v;
-                       frame.data.triple_plane.y_size = stream->data.yuv422p.length_y;
-                       frame.data.triple_plane.u_size = stream->data.yuv422p.length_u;
-                       frame.data.triple_plane.v_size = stream->data.yuv422p.length_v;
-                       break;
-               default :
-                       break;
-               }
-
-               ((camera_preview_cb)handle->user_cb[_CAMERA_EVENT_TYPE_PREVIEW])(&frame, handle->user_data[_CAMERA_EVENT_TYPE_PREVIEW]);
-       }
-
-       if (handle->user_cb[_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW]) {
-               media_packet_h pkt = NULL;
-               tbm_surface_h tsurf = NULL;
-               uint32_t bo_format = 0;
-               int i;
-               int bo_num;
-               int ret = 0;
-               media_format_mimetype_e mimetype = MEDIA_FORMAT_NV12;
-               bool make_pkt_fmt = false;
-               tbm_surface_info_s tsurf_info;
-
-               memset(&tsurf_info, 0x0, sizeof(tbm_surface_info_s));
-
-               /* create tbm surface */
-               for (i = 0, bo_num = 0 ; i < BUFFER_MAX_PLANE_NUM ; i++) {
-                       if (stream->bo[i]) {
-                               bo_num++;
-                       }
-                       tsurf_info.planes[i].stride = stream->stride[i];
-               }
-
-               /* get tbm surface format */
-               ret = _camera_get_tbm_surface_format(stream->format, &bo_format);
-               ret |= _camera_get_media_packet_mimetype(stream->format, &mimetype);
-
-               if (bo_num > 0 && ret == CAMERA_ERROR_NONE) {
-                       tsurf_info.width = stream->width;
-                       tsurf_info.height = stream->height;
-                       tsurf_info.format = bo_format;
-                       tsurf_info.bpp = tbm_surface_internal_get_bpp(bo_format);
-                       tsurf_info.num_planes = tbm_surface_internal_get_num_planes(bo_format);
-
-                       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 (bo_num == 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;
-                       case TBM_FORMAT_YUV420:
-                       case TBM_FORMAT_YVU420:
-                               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[2].size = stream->stride[2] * stream->elevation[2];
-                               tsurf_info.planes[0].offset = 0;
-                               if (bo_num == 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;
-                               }
-                               tsurf_info.size = tsurf_info.planes[0].size + tsurf_info.planes[1].size + tsurf_info.planes[2].size;
-                               break;
-                       case TBM_FORMAT_UYVY:
-                       case TBM_FORMAT_YUYV:
-                               tsurf_info.planes[0].size = (stream->stride[0] * stream->elevation[0]) << 1;
-                               tsurf_info.planes[0].offset = 0;
-                               tsurf_info.size = tsurf_info.planes[0].size;
-                               break;
-                       default:
-                               break;
-                       }
-
-                       tsurf = tbm_surface_internal_create_with_bos(&tsurf_info, (tbm_bo *)stream->bo, bo_num);
-                       /*LOGD("tbm surface %p", tsurf);*/
-               }
-
-               if (tsurf) {
-                       /* check media packet format */
-                       if (handle->pkt_fmt) {
-                               int pkt_fmt_width = 0;
-                               int pkt_fmt_height = 0;
-                               media_format_mimetype_e pkt_fmt_mimetype = MEDIA_FORMAT_NV12;
-
-                               media_format_get_video_info(handle->pkt_fmt, &pkt_fmt_mimetype, &pkt_fmt_width, &pkt_fmt_height, NULL, NULL);
-                               if (pkt_fmt_mimetype != mimetype ||
-                                   pkt_fmt_width != stream->width ||
-                                   pkt_fmt_height != stream->height) {
-                                       LOGW("different format. current 0x%x, %dx%d, new 0x%x, %dx%d",
-                                            pkt_fmt_mimetype, pkt_fmt_width, pkt_fmt_height, mimetype, stream->width, stream->height);
-                                       media_format_unref(handle->pkt_fmt);
-                                       handle->pkt_fmt = NULL;
-                                       make_pkt_fmt = true;
-                               }
-                       } else {
-                               make_pkt_fmt = true;
-                       }
-
-                       /* create packet format */
-                       if (make_pkt_fmt) {
-                               LOGW("make new pkt_fmt - mimetype 0x%x, %dx%d", mimetype, stream->width, stream->height);
-                               ret = media_format_create(&handle->pkt_fmt);
-                               if (ret == MEDIA_FORMAT_ERROR_NONE) {
-                                       ret = media_format_set_video_mime(handle->pkt_fmt, mimetype);
-                                       ret |= media_format_set_video_width(handle->pkt_fmt, stream->width);
-                                       ret |= media_format_set_video_height(handle->pkt_fmt, stream->height);
-                                       LOGW("media_format_set_video_mime,width,height ret : 0x%x", ret);
-                               } else {
-                                       LOGW("media_format_create failed");
-                               }
-                       }
-
-                       /* create media packet */
-                       ret = media_packet_create_from_tbm_surface(handle->pkt_fmt, tsurf, (media_packet_finalize_cb)_camera_media_packet_finalize, (void *)handle, &pkt);
-                       if (ret != MEDIA_PACKET_ERROR_NONE) {
-                               LOGE("media_packet_create_from_tbm_surface failed");
-
-                               tbm_surface_destroy(tsurf);
-                               tsurf = NULL;
-                       }
-               } else {
-                       LOGE("failed to create tbm surface %dx%d, format %d, bo_num %d", stream->width, stream->height, stream->format, bo_num);
-               }
-
-               if (pkt) {
-                       /*LOGD("media packet %p, internal buffer %p", pkt, stream->internal_buffer);*/
-
-                       /* set internal buffer */
-                       ret = media_packet_set_extra(pkt, stream->internal_buffer);
-                       if (ret != MEDIA_PACKET_ERROR_NONE) {
-                               LOGE("media_packet_set_extra failed");
-
-                               media_packet_destroy(pkt);
-                               pkt = NULL;
-                       } else {
-                               /* set timestamp : msec -> nsec */
-                               if (media_packet_set_pts(pkt, (uint64_t)(stream->timestamp) * 1000000) != MEDIA_PACKET_ERROR_NONE) {
-                                       LOGW("media_packet_set_pts failed");
-                               }
-
-                               /* increase ref count of gst buffer */
-                               gst_buffer_ref((GstBuffer *)stream->internal_buffer);
-
-                               /* call media packet callback */
-                               ((camera_media_packet_preview_cb)handle->user_cb[_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW])(pkt, handle->user_data[_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW]);
-                       }
-               }
+       if (handle->user_cb[_CAMERA_EVENT_TYPE_PREVIEW] ||
+           handle->user_cb[_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW]) {
+               ((camera_preview_cb)handle->user_cb[_CAMERA_EVENT_TYPE_PREVIEW])(stream, handle->user_data[_CAMERA_EVENT_TYPE_PREVIEW]);
        }
 
        return 1;
@@ -1955,7 +1768,7 @@ int legacy_camera_unset_preview_cb(camera_h camera)
 }
 
 
-int legacy_camera_set_media_packet_preview_cb(camera_h camera, camera_media_packet_preview_cb callback, void *user_data)
+int legacy_camera_set_media_packet_preview_cb(camera_h camera, camera_preview_cb callback, void *user_data)
 {
        if (camera == NULL) {
                LOGE("INVALID_PARAMETER(0x%08x) - handle", CAMERA_ERROR_INVALID_PARAMETER);
@@ -3822,159 +3635,6 @@ int _camera_set_relay_mm_message_callback(camera_h camera, MMMessageCallback cal
 }
 
 
-int _camera_get_tbm_surface_format(int in_format, uint32_t *out_format)
-{
-       if (in_format <= MM_PIXEL_FORMAT_INVALID ||
-           in_format >= MM_PIXEL_FORMAT_NUM ||
-           out_format == NULL) {
-               LOGE("INVALID_PARAMETER : in_format %d, out_format ptr %p", in_format, out_format);
-               return CAMERA_ERROR_INVALID_PARAMETER;
-       }
-
-       switch (in_format) {
-       case MM_PIXEL_FORMAT_NV12:
-       case MM_PIXEL_FORMAT_NV12T:
-               *out_format = TBM_FORMAT_NV12;
-               break;
-       case MM_PIXEL_FORMAT_NV16:
-               *out_format = TBM_FORMAT_NV16;
-               break;
-       case MM_PIXEL_FORMAT_NV21:
-               *out_format = TBM_FORMAT_NV21;
-               break;
-       case MM_PIXEL_FORMAT_YUYV:
-               *out_format = TBM_FORMAT_YUYV;
-               break;
-       case MM_PIXEL_FORMAT_UYVY:
-       case MM_PIXEL_FORMAT_ITLV_JPEG_UYVY:
-               *out_format = TBM_FORMAT_UYVY;
-               break;
-       case MM_PIXEL_FORMAT_422P:
-               *out_format = TBM_FORMAT_YUV422;
-               break;
-       case MM_PIXEL_FORMAT_I420:
-               *out_format = TBM_FORMAT_YUV420;
-               break;
-       case MM_PIXEL_FORMAT_YV12:
-               *out_format = TBM_FORMAT_YVU420;
-               break;
-       case MM_PIXEL_FORMAT_RGB565:
-               *out_format = TBM_FORMAT_RGB565;
-               break;
-       case MM_PIXEL_FORMAT_RGB888:
-               *out_format = TBM_FORMAT_RGB888;
-               break;
-       case MM_PIXEL_FORMAT_RGBA:
-               *out_format = TBM_FORMAT_RGBA8888;
-               break;
-       case MM_PIXEL_FORMAT_ARGB:
-               *out_format = TBM_FORMAT_ARGB8888;
-               break;
-       default:
-               LOGE("invalid in_format %d", in_format);
-               return CAMERA_ERROR_INVALID_PARAMETER;
-       }
-
-       return CAMERA_ERROR_NONE;
-}
-
-
-int _camera_get_media_packet_mimetype(int in_format, media_format_mimetype_e *mimetype)
-{
-       if (in_format <= MM_PIXEL_FORMAT_INVALID ||
-           in_format >= MM_PIXEL_FORMAT_NUM ||
-           mimetype == NULL) {
-               LOGE("INVALID_PARAMETER : in_format %d, mimetype ptr %p", in_format, mimetype);
-               return CAMERA_ERROR_INVALID_PARAMETER;
-       }
-
-       switch (in_format) {
-       case MM_PIXEL_FORMAT_NV12:
-       case MM_PIXEL_FORMAT_NV12T:
-               *mimetype = MEDIA_FORMAT_NV12;
-               break;
-       case MM_PIXEL_FORMAT_NV16:
-               *mimetype = MEDIA_FORMAT_NV16;
-               break;
-       case MM_PIXEL_FORMAT_NV21:
-               *mimetype = MEDIA_FORMAT_NV21;
-               break;
-       case MM_PIXEL_FORMAT_YUYV:
-               *mimetype = MEDIA_FORMAT_YUYV;
-               break;
-       case MM_PIXEL_FORMAT_UYVY:
-       case MM_PIXEL_FORMAT_ITLV_JPEG_UYVY:
-               *mimetype = MEDIA_FORMAT_UYVY;
-               break;
-       case MM_PIXEL_FORMAT_422P:
-               *mimetype = MEDIA_FORMAT_422P;
-               break;
-       case MM_PIXEL_FORMAT_I420:
-               *mimetype = MEDIA_FORMAT_I420;
-               break;
-       case MM_PIXEL_FORMAT_YV12:
-               *mimetype = MEDIA_FORMAT_YV12;
-               break;
-       case MM_PIXEL_FORMAT_RGB565:
-               *mimetype = MEDIA_FORMAT_RGB565;
-               break;
-       case MM_PIXEL_FORMAT_RGB888:
-               *mimetype = MEDIA_FORMAT_RGB888;
-               break;
-       case MM_PIXEL_FORMAT_RGBA:
-               *mimetype = MEDIA_FORMAT_RGBA;
-               break;
-       case MM_PIXEL_FORMAT_ARGB:
-               *mimetype = MEDIA_FORMAT_ARGB;
-               break;
-       default:
-               LOGE("invalid in_format %d", in_format);
-               return CAMERA_ERROR_INVALID_PARAMETER;
-       }
-
-       return CAMERA_ERROR_NONE;
-}
-
-
-int _camera_media_packet_finalize(media_packet_h pkt, int error_code, void *user_data)
-{
-       int ret = 0;
-       void *internal_buffer = NULL;
-       tbm_surface_h tsurf = NULL;
-
-       if (pkt == NULL || user_data == NULL) {
-               LOGE("invalid parameter buffer %p, user_data %p", pkt, user_data);
-               return MEDIA_PACKET_FINALIZE;
-       }
-
-       ret = media_packet_get_extra(pkt, &internal_buffer);
-       if (ret != MEDIA_PACKET_ERROR_NONE) {
-               LOGE("media_packet_get_extra failed 0x%x", ret);
-               return MEDIA_PACKET_FINALIZE;
-       }
-
-       /*LOGD("pointer gst buffer %p, ret 0x%x", internal_buffer, ret);*/
-
-       if (internal_buffer) {
-               gst_buffer_unref((GstBuffer *)internal_buffer);
-               internal_buffer = NULL;
-       }
-
-       ret = media_packet_get_tbm_surface(pkt, &tsurf);
-       if (ret != MEDIA_PACKET_ERROR_NONE) {
-               LOGE("media_packet_get_tbm_surface failed 0x%x", ret);
-               return MEDIA_PACKET_FINALIZE;
-       }
-
-       if (tsurf) {
-               tbm_surface_destroy(tsurf);
-               tsurf = NULL;
-       }
-
-       return MEDIA_PACKET_FINALIZE;
-}
-
-
 int legacy_camera_attr_set_hdr_mode(camera_h camera, camera_attr_hdr_mode_e mode)
 {
        if (camera == NULL) {
index 421953b..25cdcdb 100644 (file)
@@ -2,7 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
 SET(service "muse")
 SET(submodule "camera")
 
-SET(dependents "dlog glib-2.0 mused mm-common libtbm")
+SET(dependents "dlog glib-2.0 mused mm-common libtbm gstreamer-1.0")
 SET(fw_name "${service}-${submodule}")
 
 PROJECT(${fw_name})
index 3d0fe24..b0d130a 100644 (file)
@@ -166,6 +166,7 @@ typedef enum {
        MUSE_CAMERA_API_ATTR_IS_SUPPORTED_AUTO_CONTRAST,
        MUSE_CAMERA_API_ATTR_DISABLE_SHUTTER_SOUND,
        MUSE_CAMERA_API_RETURN_BUFFER,
+       MUSE_CAMERA_API_PREVIEW_CB_RETURN,
        MUSE_CAMERA_API_MAX
 } muse_camera_api_e;
 
@@ -216,6 +217,7 @@ typedef enum {
 typedef struct {
        tbm_bo bo;
        int key;
+       void *internal_buffer;
 } muse_camera_export_data;
 
 typedef struct {
@@ -223,17 +225,10 @@ typedef struct {
        tbm_bufmgr bufmgr;
        GList *data_list;
        GMutex list_lock;
+       GMutex preview_cb_lock;
+       GCond preview_cb_cond;
 } muse_camera_handle_s;
 
-/**
- * @brief The structure type for data transport for the muse camera
- */
-typedef struct {
-       int data_size;
-       int tbm_key;
-       tbm_bo bo;
-       tbm_bo_handle bo_handle;
-} muse_camera_transport_info_s;
 
 /**
  * @brief The structure type for muse camera errors.
index 628bd2c..c22ffdf 100755 (executable)
@@ -165,6 +165,24 @@ typedef const char* STRING;
        }while(0)
 
 /**
+ * @brief Send the message from proxy to module via ipc.
+ * @param[in] api The enumeration of the corresponding api.
+ * @param[in] fd The socket fd that connected to the module via ipc.
+ * @param[in] cb_info The callback information, waiting for the ack from the module.
+ */
+#define muse_camera_msg_send_no_return(api, fd, cb_info) \
+       do{     \
+               char *__sndMsg__; \
+               int __len__; \
+               __sndMsg__ = muse_core_msg_json_factory_new(api, 0); \
+               __len__ = muse_core_ipc_send_msg(fd, __sndMsg__); \
+               if (__len__ <= 0) { \
+                       LOGE("sending message failed"); \
+               } \
+               muse_core_msg_json_factory_free(__sndMsg__); \
+       } while(0)
+
+/**
  * @brief Send the message from proxy to module via ipc, waits more period of time for the ack.
  * @param[in] api The enumeration of the corresponding api.
  * @param[in] fd The socket fd that connected to the module via ipc.
index e2650ec..0cb1e77 100755 (executable)
@@ -28,6 +28,7 @@
 #include <muse_core_ipc.h>
 #include <mm_types.h>
 #include <muse_core_security.h>
+#include <gst/gst.h>
 
 #ifdef LOG_TAG
 #undef LOG_TAG
@@ -275,17 +276,27 @@ static int _camera_remove_export_data(muse_module_h module, int key, int remove_
                export_data = (muse_camera_export_data *)tmp_list->data;
                if (export_data) {
                        if (export_data->key == key || remove_all) {
-                               LOGD("key %d matched, remove it (remove_all %d)", key, remove_all);
+                               /*LOGD("key %d matched, remove it (remove_all %d)", key, remove_all);*/
 
-                               tbm_bo_unref(export_data->bo);
-                               export_data->bo = NULL;
+                               if (export_data->bo) {
+                                       tbm_bo_unref(export_data->bo);
+                                       export_data->bo = NULL;
+                               } else {
+                                       LOGW("bo for key %d is NULL", key);
+                               }
                                export_data->key = 0;
+                               if (export_data->internal_buffer) {
+                                       gst_buffer_unref((GstBuffer *)export_data->internal_buffer);
+                                       export_data->internal_buffer = NULL;
+                               }
+
                                muse_camera->data_list = g_list_remove(muse_camera->data_list, export_data);
+
                                g_free(export_data);
                                export_data = NULL;
 
                                if (remove_all == FALSE) {
-                                       LOGD("key %d, remove done");
+                                       /*LOGD("key %d, remove done");*/
                                        g_mutex_unlock(&muse_camera->list_lock);
                                        return TRUE;
                                } else {
@@ -313,7 +324,9 @@ static int _camera_remove_export_data(muse_module_h module, int key, int remove_
 void _camera_dispatcher_capturing_cb(camera_image_data_s* image, camera_image_data_s* postview, camera_image_data_s* thumbnail, void *user_data)
 {
        muse_camera_handle_s *muse_camera = NULL;
-       muse_camera_transport_info_s transport_info;
+       int data_size = 0;
+       tbm_bo bo = NULL;
+       tbm_bo_handle bo_handle = {.ptr = NULL};
        muse_camera_export_data *export_data = NULL;
        int tbm_key = 0;
        muse_module_h module = (muse_module_h)user_data;
@@ -335,44 +348,42 @@ void _camera_dispatcher_capturing_cb(camera_image_data_s* image, camera_image_da
                return;
        }
 
-       memset(&transport_info, 0x0, sizeof(muse_camera_transport_info_s));
-
        if (image != NULL) {
                if (image->size > 0) {
-                       transport_info.data_size += (sizeof(camera_image_data_s) + image->size);
+                       data_size += (sizeof(camera_image_data_s) + image->size);
                }
        }
        if (postview != NULL) {
                if (postview->size > 0) {
-                       transport_info.data_size += (sizeof(camera_image_data_s) + postview->size);
+                       data_size += (sizeof(camera_image_data_s) + postview->size);
                        is_postview = 1;
                }
        }
        if (thumbnail != NULL) {
                if (thumbnail->size > 0) {
-                       transport_info.data_size += (sizeof(camera_image_data_s) + thumbnail->size);
+                       data_size += (sizeof(camera_image_data_s) + thumbnail->size);
                        is_thumbnail = 1;
                }
        }
 
-       transport_info.bo = tbm_bo_alloc(muse_camera->bufmgr, transport_info.data_size, TBM_BO_DEFAULT);
-       if (transport_info.bo == NULL) {
+       bo = tbm_bo_alloc(muse_camera->bufmgr, data_size, TBM_BO_DEFAULT);
+       if (bo == NULL) {
                LOGE("bo alloc failed");
                g_free(export_data);
                export_data = NULL;
                return;
        }
 
-       transport_info.bo_handle = tbm_bo_map(transport_info.bo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
-       if (transport_info.bo_handle.ptr == NULL) {
+       bo_handle = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
+       if (bo_handle.ptr == NULL) {
                LOGE("bo map Error!");
-               tbm_bo_unref(transport_info.bo);
+               tbm_bo_unref(bo);
                g_free(export_data);
                export_data = NULL;
                return;
        }
 
-       buf_pos = (unsigned char *)transport_info.bo_handle.ptr;
+       buf_pos = (unsigned char *)bo_handle.ptr;
        if (image != NULL) {
                if (image->size > 0) {
                        memcpy(buf_pos, image, sizeof(camera_image_data_s));
@@ -395,28 +406,25 @@ void _camera_dispatcher_capturing_cb(camera_image_data_s* image, camera_image_da
                memcpy(buf_pos + sizeof(camera_image_data_s), image->data, thumbnail->size);
        }
 
-       tbm_bo_unmap(transport_info.bo);
+       tbm_bo_unmap(bo);
 
-       tbm_key = tbm_bo_export(transport_info.bo);
+       tbm_key = tbm_bo_export(bo);
 
        if(tbm_key == 0) {
                LOGE("Create key_info ERROR!!");
-               tbm_bo_unref(transport_info.bo);
-               transport_info.bo = NULL;
+               tbm_bo_unref(bo);
+               bo = NULL;
                g_free(export_data);
                export_data = NULL;
                return;
        }
 
        LOGD("bo %p, vaddr %p, size %d, key %d",
-            transport_info.bo,
-            transport_info.bo_handle.ptr,
-            transport_info.data_size,
-            tbm_key);
+            bo, bo_handle.ptr, data_size, tbm_key);
 
        /* set bo info */
        export_data->key = tbm_key;
-       export_data->bo = transport_info.bo;
+       export_data->bo = bo;
 
        /* add bo info to list */
        g_mutex_lock(&muse_camera->list_lock);
@@ -470,19 +478,26 @@ void _camera_dispatcher_interrupted_cb(camera_policy_e policy, camera_state_e pr
        return;
 }
 
-void _camera_dispatcher_preview_cb(camera_preview_data_s *frame, void *user_data)
+void _camera_dispatcher_preview_cb(MMCamcorderVideoStreamDataType *stream, void *user_data)
 {
        muse_camera_handle_s *muse_camera = NULL;
-       muse_camera_transport_info_s transport_info;
+       int data_size = 0;
+       tbm_bo bo = NULL;
+       tbm_bo_handle bo_handle = {.ptr = NULL};
        muse_camera_export_data *export_data = NULL;
+       int i = 0;
        int tbm_key = 0;
+       int buffer_key[BUFFER_MAX_PLANE_NUM] = {0, };
+       int num_buffer_key = 0;
        muse_module_h module = (muse_module_h)user_data;
        unsigned char *buf_pos = NULL;
+       char *send_message = NULL;
+       gint64 end_time;
 
-       LOGD("Enter!!");
+       /*LOGD("Enter");*/
 
-       if (frame == NULL) {
-               LOGE("NULL data");
+       if (module == NULL || stream == NULL) {
+               LOGE("NULL data %p, %p", module, stream);
                return;
        }
 
@@ -498,109 +513,164 @@ void _camera_dispatcher_preview_cb(camera_preview_data_s *frame, void *user_data
                return;
        }
 
-       memset(&transport_info, 0x0, sizeof(muse_camera_transport_info_s));
-
-       transport_info.data_size += sizeof(camera_preview_data_s);
-       switch (frame->num_of_planes) {
-               case 1:
-                       transport_info.data_size += frame->data.single_plane.size;
-               case 2:
-                       transport_info.data_size += frame->data.double_plane.y_size + \
-                                                   frame->data.double_plane.uv_size;
-               case 3:
-                       transport_info.data_size += frame->data.triple_plane.y_size + \
-                                                   frame->data.triple_plane.u_size + \
-                                                   frame->data.triple_plane.v_size;
-               default:
+       data_size = sizeof(MMCamcorderVideoStreamDataType);
+
+       if (stream->bo[0] == NULL) {
+               switch (stream->data_type) {
+               case MM_CAM_STREAM_DATA_YUV420:
+                       data_size += stream->data.yuv420.length_yuv;
+                       break;
+               case MM_CAM_STREAM_DATA_YUV422:
+                       data_size += stream->data.yuv422.length_yuv;
+                       break;
+               case MM_CAM_STREAM_DATA_YUV420SP:
+                       data_size += stream->data.yuv420sp.length_y;
+                       data_size += stream->data.yuv420sp.length_uv;
+                       break;
+               case MM_CAM_STREAM_DATA_YUV420P:
+                       data_size += stream->data.yuv420p.length_y;
+                       data_size += stream->data.yuv420p.length_u;
+                       data_size += stream->data.yuv420p.length_v;
                        break;
+               case MM_CAM_STREAM_DATA_YUV422P:
+                       data_size += stream->data.yuv422p.length_y;
+                       data_size += stream->data.yuv422p.length_u;
+                       data_size += stream->data.yuv422p.length_v;
+                       break;
+               default :
+                       LOGW("unknown data type %d", stream->data_type);
+                       break;
+               }
        }
 
-       transport_info.bo = tbm_bo_alloc(muse_camera->bufmgr, transport_info.data_size, TBM_BO_DEFAULT);
-       if (transport_info.bo == NULL) {
+       bo = tbm_bo_alloc(muse_camera->bufmgr, data_size, TBM_BO_DEFAULT);
+       if (bo == NULL) {
                LOGE("bo alloc failed");
                g_free(export_data);
                export_data = NULL;
                return;
        }
 
-       transport_info.bo_handle = tbm_bo_map(transport_info.bo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
-       if (transport_info.bo_handle.ptr == NULL) {
+       bo_handle = tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
+       if (bo_handle.ptr == NULL) {
                LOGE("bo map Error!");
-               tbm_bo_unref(transport_info.bo);
+               tbm_bo_unref(bo);
                g_free(export_data);
                export_data = NULL;
                return;
        }
 
-       buf_pos = (unsigned char *)transport_info.bo_handle.ptr;
-
-       memcpy(buf_pos, frame, sizeof(camera_preview_data_s));
-       buf_pos += sizeof(camera_preview_data_s);
-
-       switch (frame->num_of_planes) {
-               case 1:
-                       memcpy(buf_pos, frame->data.single_plane.yuv, frame->data.single_plane.size);
-               case 2:
-                       memcpy(buf_pos, frame->data.double_plane.y, frame->data.double_plane.y_size);
-                       buf_pos += frame->data.double_plane.y_size;
-                       memcpy(buf_pos, frame->data.double_plane.uv, frame->data.double_plane.uv_size);
-               case 3:
-                       memcpy(buf_pos, frame->data.triple_plane.y, frame->data.triple_plane.y_size);
-                       buf_pos += frame->data.triple_plane.y_size;
-                       memcpy(buf_pos, frame->data.triple_plane.u, frame->data.triple_plane.u_size);
-                       buf_pos += frame->data.triple_plane.u_size;
-                       memcpy(buf_pos, frame->data.triple_plane.v, frame->data.triple_plane.v_size);
-               default:
+       buf_pos = (unsigned char *)bo_handle.ptr;
+
+       memcpy(buf_pos, stream, sizeof(MMCamcorderVideoStreamDataType));
+       buf_pos += sizeof(MMCamcorderVideoStreamDataType);
+
+       if (stream->bo[0] == NULL) {
+               /* non-zero copy */
+               switch (stream->data_type) {
+               case MM_CAM_STREAM_DATA_YUV420:
+                       memcpy(buf_pos, stream->data.yuv420.yuv, stream->data.yuv420.length_yuv);
+                       break;
+               case MM_CAM_STREAM_DATA_YUV422:
+                       memcpy(buf_pos, stream->data.yuv422.yuv, stream->data.yuv422.length_yuv);
+                       break;
+               case MM_CAM_STREAM_DATA_YUV420SP:
+                       memcpy(buf_pos, stream->data.yuv420sp.y, stream->data.yuv420sp.length_y);
+                       memcpy(buf_pos + stream->data.yuv420sp.length_y, stream->data.yuv420sp.uv, stream->data.yuv420sp.length_uv);
+                       break;
+               case MM_CAM_STREAM_DATA_YUV420P:
+                       memcpy(buf_pos, stream->data.yuv420p.y, stream->data.yuv420p.length_y);
+                       memcpy(buf_pos + stream->data.yuv420p.length_y, stream->data.yuv420p.u, stream->data.yuv420p.length_u);
+                       memcpy(buf_pos + stream->data.yuv420p.length_y + stream->data.yuv420p.length_u, stream->data.yuv420p.v, stream->data.yuv420p.length_v);
                        break;
+               case MM_CAM_STREAM_DATA_YUV422P:
+                       memcpy(buf_pos, stream->data.yuv422p.y, stream->data.yuv422p.length_y);
+                       memcpy(buf_pos + stream->data.yuv422p.length_y, stream->data.yuv422p.u, stream->data.yuv422p.length_u);
+                       memcpy(buf_pos + stream->data.yuv422p.length_y + stream->data.yuv422p.length_u, stream->data.yuv422p.v, stream->data.yuv422p.length_v);
+                       break;
+               default :
+                       break;
+               }
+       } else {
+               /* zero copy */
+               for (i = 0 ; i < BUFFER_MAX_PLANE_NUM ; i++) {
+                       if (stream->bo[i]) {
+                               buffer_key[i] = tbm_bo_export(stream->bo[i]);
+                               if (buffer_key[i] == 0) {
+                                       LOGE("failed to export bo %p", stream->bo[i]);
+                                       tbm_bo_unmap(bo);
+                                       tbm_bo_unref(bo);
+                                       bo = NULL;
+                                       g_free(export_data);
+                                       export_data = NULL;
+                                       return;
+                               }
+                               num_buffer_key++;
+                       } else {
+                               LOGD("num_buffer_key %d", num_buffer_key);
+                               break;
+                       }
+               }
        }
 
-       tbm_bo_unmap(transport_info.bo);
+       tbm_bo_unmap(bo);
 
-       tbm_key = tbm_bo_export(transport_info.bo);
+       tbm_key = tbm_bo_export(bo);
 
        if(tbm_key == 0) {
                LOGE("Create key_info ERROR!!");
-               tbm_bo_unref(transport_info.bo);
-               transport_info.bo = NULL;
+               tbm_bo_unref(bo);
+               bo = NULL;
                g_free(export_data);
                export_data = NULL;
                return;
        }
 
+       /*
        LOGD("bo %p, vaddr %p, size %d, key %d",
-            transport_info.bo,
-            transport_info.bo_handle.ptr,
-            transport_info.data_size,
-            tbm_key);
+            bo, bo_handle.ptr, data_size, tbm_key);
+       */
 
        /* set bo info */
        export_data->key = tbm_key;
-       export_data->bo = transport_info.bo;
+       export_data->bo = bo;
+       if (stream->internal_buffer) {
+               export_data->internal_buffer = stream->internal_buffer;
+               gst_buffer_ref((GstBuffer *)export_data->internal_buffer);
+       }
 
        /* add bo info to list */
        g_mutex_lock(&muse_camera->list_lock);
        muse_camera->data_list = g_list_append(muse_camera->data_list, (gpointer)export_data);
        g_mutex_unlock(&muse_camera->list_lock);
 
-       /* add bo and key to list */
-       muse_camera_msg_event1(MUSE_CAMERA_CB_EVENT,
-                              MUSE_CAMERA_EVENT_TYPE_PREVIEW,
-                              MUSE_CAMERA_EVENT_CLASS_NORMAL,
-                              module,
-                              INT, tbm_key);
-       return;
-}
+       g_mutex_lock(&muse_camera->preview_cb_lock);
 
-void _camera_dispatcher_media_packet_preview_cb(media_packet_h pkt, void *user_data)
-{
-       muse_module_h module = (muse_module_h)user_data;
+       /* send message */
+       send_message = muse_core_msg_json_factory_new(MUSE_CAMERA_CB_EVENT,
+                                                     MUSE_TYPE_INT, PARAM_EVENT, MUSE_CAMERA_EVENT_TYPE_PREVIEW,
+                                                     MUSE_TYPE_INT, PARAM_CLASS, MUSE_CAMERA_EVENT_CLASS_NORMAL,
+                                                     MUSE_TYPE_INT, "tbm_key", tbm_key,
+                                                     MUSE_TYPE_INT, "num_buffer_key", num_buffer_key,
+                                                     MUSE_TYPE_ARRAY, "buffer_key", BUFFER_MAX_PLANE_NUM, buffer_key,
+                                                     0);
 
-       LOGD("Enter");
+       muse_core_ipc_send_msg(muse_core_client_get_msg_fd(module), send_message);
+
+       muse_core_msg_json_factory_free(send_message);
+
+       /*LOGD("wait preview callback return message");*/
+
+       end_time = g_get_monotonic_time () + G_TIME_SPAN_SECOND;
+
+       if (!g_cond_wait_until(&muse_camera->preview_cb_cond, &muse_camera->preview_cb_lock, end_time)) {
+               LOGW("preview callback return message timeout");
+       } else {
+               /*LOGD("preview callback return message received");*/
+       }
+
+       g_mutex_unlock(&muse_camera->preview_cb_lock);
 
-       muse_camera_msg_event(MUSE_CAMERA_CB_EVENT,
-                             MUSE_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW,
-                             MUSE_CAMERA_EVENT_CLASS_NORMAL,
-                             module);
        return;
 }
 
@@ -789,6 +859,8 @@ int camera_dispatcher_create(muse_module_h module)
        memset(muse_camera, 0x0, sizeof(muse_camera_handle_s));
 
        g_mutex_init(&muse_camera->list_lock);
+       g_mutex_init(&muse_camera->preview_cb_lock);
+       g_cond_init(&muse_camera->preview_cb_cond);
 
        if (muse_core_ipc_get_bufmgr(&muse_camera->bufmgr) != MM_ERROR_NONE) {
                LOGE("muse_core_ipc_get_bufmgr failed");
@@ -846,8 +918,14 @@ int camera_dispatcher_destroy(muse_module_h module)
        muse_camera_msg_return(api, ret, module);
 
        if (ret == CAMERA_ERROR_NONE) {
+               _camera_remove_export_data(module, 0, TRUE);
+
                g_mutex_clear(&muse_camera->list_lock);
+               g_mutex_clear(&muse_camera->preview_cb_lock);
+               g_cond_clear(&muse_camera->preview_cb_cond);
+
                muse_camera->bufmgr = NULL;
+
                free(muse_camera);
                muse_camera = NULL;
        }
@@ -1602,7 +1680,7 @@ int camera_dispatcher_set_media_packet_preview_cb(muse_module_h module)
        LOGD("handle : %p", muse_camera);
 
        ret = legacy_camera_set_media_packet_preview_cb(muse_camera->camera_handle,
-                                                       (camera_media_packet_preview_cb)_camera_dispatcher_media_packet_preview_cb,
+                                                       (camera_preview_cb)_camera_dispatcher_preview_cb,
                                                        (void *)module);
 
        LOGD("ret : 0x%x", ret);
@@ -3552,15 +3630,38 @@ int camera_dispatcher_return_buffer(muse_module_h module)
 
        muse_camera_msg_get(tbm_key, muse_core_client_get_msg(module));
 
-       LOGD("handle : %p, key : %d", muse_camera, tbm_key);
+       /*LOGD("handle : %p, key : %d", muse_camera, tbm_key);*/
 
-       if (_camera_remove_export_data(module, tbm_key, FALSE)) {
-               LOGD("done");
+       if (!_camera_remove_export_data(module, tbm_key, FALSE)) {
+               LOGE("remove export data failed : key %d", tbm_key);
        }
 
        return MUSE_CAMERA_ERROR_NONE;
 }
 
+int camera_dispatcher_preview_cb_return(muse_module_h module)
+{
+       muse_camera_handle_s *muse_camera = NULL;
+
+       muse_camera = (muse_camera_handle_s *)muse_core_ipc_get_handle(module);
+
+       if (muse_camera == NULL) {
+               LOGE("NULL handle");
+               return MUSE_CAMERA_ERROR_NONE;
+       }
+
+       /*LOGD("ENTER");*/
+
+       g_mutex_lock(&muse_camera->preview_cb_lock);
+       g_cond_signal(&muse_camera->preview_cb_cond);
+       /*LOGD("send signal for preview callback");*/
+       g_mutex_unlock(&muse_camera->preview_cb_lock);
+
+       /*LOGD("DONE");*/
+
+       return MUSE_CAMERA_ERROR_NONE;
+}
+
 
 int (*dispatcher[MUSE_CAMERA_API_MAX]) (muse_module_h module) = {
        camera_dispatcher_create, /* MUSE_CAMERA_API_CREATE */
@@ -3692,4 +3793,5 @@ int (*dispatcher[MUSE_CAMERA_API_MAX]) (muse_module_h module) = {
        camera_dispatcher_attr_is_supported_auto_contrast, /* MUSE_CAMERA_API_ATTR_IS_SUPPORTED_AUTO_CONTRAST, */
        camera_dispatcher_attr_disable_shutter_sound, /* MUSE_CAMERA_API_ATTR_DISABLE_SHUTTER_SOUND, */
        camera_dispatcher_return_buffer, /* MUSE_CAMERA_API_RETURN_BUFFER, */
+       camera_dispatcher_preview_cb_return, /* MUSE_CAMERA_API_PREVIEW_CB_RETURN, */
 };
index 20065b7..beb35e0 100644 (file)
@@ -3,7 +3,7 @@
 
 Name:       mmsvc-camera
 Summary:    A Camera module for muse server
-Version:    0.2.11
+Version:    0.2.12
 Release:    0
 Group:      Multimedia/Libraries
 License:    Apache-2.0