From a6cb1df5d449b7b1ab9c5d8c2e032bcb63736bc2 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Fri, 15 Apr 2016 15:55:53 +0900 Subject: [PATCH] [Release version 0.2.50] 1. Update code for EVAS surface rendering, 2. Update camera_test - Fix display issues, 3. Add internal API for video recorder Change-Id: Ic4aae56e68371dbd5235d0cb71b781dfa9962d1a Signed-off-by: Jeongmo Yang --- include/camera.h | 29 ++-- include/camera_internal.h | 73 ++++++++++ include/camera_private.h | 4 + packaging/capi-media-camera.spec | 3 +- src/camera.c | 303 +++++++++++++++++++++++++++++++-------- src/camera_internal.c | 41 ++++++ test/CMakeLists.txt | 2 +- test/camera_test.c | 283 ++++++++++++++++++++++-------------- 8 files changed, 558 insertions(+), 180 deletions(-) create mode 100644 include/camera_internal.h create mode 100644 src/camera_internal.c diff --git a/include/camera.h b/include/camera.h index 8ae9956..a702ff4 100644 --- a/include/camera.h +++ b/include/camera.h @@ -1,18 +1,18 @@ /* -* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #ifndef __TIZEN_MULTIMEDIA_CAMERA_H__ #define __TIZEN_MULTIMEDIA_CAMERA_H__ @@ -974,6 +974,7 @@ int camera_cancel_focusing(camera_h camera); * @retval #CAMERA_ERROR_NONE Successful * @retval #CAMERA_ERROR_INVALID_PARAMETER Invalid parameter * @retval #CAMERA_ERROR_INVALID_STATE Invalid state + * @retval #CAMERA_ERROR_INVALID_OPERATION Invalid operation * @retval #CAMERA_ERROR_PERMISSION_DENIED The access to the resources can not be granted * @retval #CAMERA_ERROR_NOT_SUPPORTED The feature is not supported * @pre The camera state must be set to #CAMERA_STATE_CREATED. diff --git a/include/camera_internal.h b/include/camera_internal.h new file mode 100644 index 0000000..f1728d4 --- /dev/null +++ b/include/camera_internal.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_MULTIMEDIA_CAMERA_INTERNAL_H__ +#define __TIZEN_MULTIMEDIA_CAMERA_INTERNAL_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file camera_internal.h + * @brief This file contains the internal Camera API, related structures and enumerations. + * @since_tizen 3.0 + */ + +/** + * @addtogroup CAPI_MEDIA_CAMERA_INTERNAL_MODULE + * @{ + */ + +/** + * @brief Start the evas rendering. + * + * @since_tizen 3.0 + * @param[in] camera The handle to the camera + * @return @c 0 on success, otherwise a negative error value + * @retval #CAMERA_ERROR_NONE Successful + * @retval #CAMERA_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CAMERA_ERROR_INVALID_STATE Invalid state + * @retval #CAMERA_ERROR_INVALID_OPERATION Invalid operation + * @retval #CAMERA_ERROR_NOT_SUPPORTED The feature is not supported + */ +int camera_start_evas_rendering(camera_h camera); + +/** + * @brief Stop the evas rendering. + * + * @since_tizen 3.0 + * @param[in] camera The handle to the camera + * @param[in] keep_screen If @c true keep last frame on display, otherwise @c false + * @return @c 0 on success, otherwise a negative error value + * @retval #CAMERA_ERROR_NONE Successful + * @retval #CAMERA_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #CAMERA_ERROR_INVALID_STATE Invalid state + * @retval #CAMERA_ERROR_INVALID_OPERATION Invalid operation + * @retval #CAMERA_ERROR_NOT_SUPPORTED The feature is not supported + */ +int camera_stop_evas_rendering(camera_h camera, bool keep_screen); + +/** + * @} + */ +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_MULTIMEDIA_CAMERA_INTERNAL_H__ */ diff --git a/include/camera_private.h b/include/camera_private.h index 1191bd1..bc56434 100644 --- a/include/camera_private.h +++ b/include/camera_private.h @@ -105,6 +105,8 @@ typedef struct _camera_cb_info_s { int preview_cb_flag; GMutex mp_data_mutex; void *evas_info; + GMutex evas_mutex; + gboolean run_evas_render; } camera_cb_info_s; typedef struct _camera_message_s { @@ -151,6 +153,8 @@ typedef struct _camera_media_packet_data { 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 _camera_start_evas_rendering(camera_h camera); +int _camera_stop_evas_rendering(camera_h camera, bool keep_screen); #ifdef __cplusplus } diff --git a/packaging/capi-media-camera.spec b/packaging/capi-media-camera.spec index bc9764d..c3b332a 100644 --- a/packaging/capi-media-camera.spec +++ b/packaging/capi-media-camera.spec @@ -3,7 +3,7 @@ Name: capi-media-camera Summary: A Camera API -Version: 0.2.49 +Version: 0.2.50 Release: 0 Group: Multimedia/API License: Apache-2.0 @@ -91,5 +91,6 @@ cp LICENSE.APLv2 %{buildroot}%{_datadir}/license/%{name} %files devel %{_includedir}/media/camera.h +%{_includedir}/media/camera_internal.h %{_libdir}/pkgconfig/*.pc %{_libdir}/libcapi-media-camera.so diff --git a/src/camera.c b/src/camera.c index 8529f63..159957f 100644 --- a/src/camera.c +++ b/src/camera.c @@ -1,18 +1,18 @@ /* -* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include @@ -741,6 +741,7 @@ int _camera_media_packet_finalize(media_packet_h pkt, int error_code, void *user /*LOGD("mp_data %p", mp_data);*/ g_mutex_lock(&cb_info->mp_data_mutex); + if (mp_data) { if (mp_data->ref_cnt > 1) { mp_data->ref_cnt--; @@ -764,6 +765,7 @@ int _camera_media_packet_finalize(media_packet_h pkt, int error_code, void *user mp_data = NULL; } } + g_mutex_unlock(&cb_info->mp_data_mutex); ret = media_packet_get_tbm_surface(pkt, &tsurf); @@ -931,7 +933,18 @@ static void _client_user_callback(camera_cb_info_s *cb_info, char *recv_msg, mus ret = _camera_media_packet_create(cb_info, stream, mp_data, &pkt); if (ret == CAMERA_ERROR_NONE) { - mm_evas_renderer_write(pkt, cb_info->evas_info); + g_mutex_lock(&cb_info->evas_mutex); + + if (cb_info->run_evas_render) + mm_evas_renderer_write(pkt, cb_info->evas_info); + else { + LOGW("evas renderer is stopped, skip this buffer..."); + media_packet_destroy(pkt); + } + + pkt = NULL; + + g_mutex_unlock(&cb_info->evas_mutex); } else { g_free(mp_data); mp_data = NULL; @@ -1743,6 +1756,7 @@ static camera_cb_info_s *_client_callback_new(gint sockfd) g_mutex_init(&cb_info->idle_event_mutex); g_cond_init(&cb_info->idle_event_cond); g_mutex_init(&cb_info->mp_data_mutex); + g_mutex_init(&cb_info->evas_mutex); for (i = 0 ; i < MUSE_CAMERA_API_MAX ; i++) { g_mutex_init(&cb_info->api_mutex[i]); @@ -1779,7 +1793,7 @@ static camera_cb_info_s *_client_callback_new(gint sockfd) cb_info->api_activating = tmp_activating; cb_info->api_ret = tmp_ret; cb_info->preview_cb_flag = 0; - cb_info->evas_info = g_new0(mm_evas_info, 1); + cb_info->evas_info = NULL; g_atomic_int_set(&cb_info->msg_recv_running, 1); cb_info->msg_recv_thread = g_thread_try_new("camera_msg_recv", @@ -1814,6 +1828,7 @@ ErrorExit: g_mutex_clear(&cb_info->idle_event_mutex); g_cond_clear(&cb_info->idle_event_cond); g_mutex_clear(&cb_info->mp_data_mutex); + g_mutex_clear(&cb_info->evas_mutex); if (cb_info->msg_queue) { g_queue_free(cb_info->msg_queue); @@ -1872,6 +1887,7 @@ static void _client_callback_destroy(camera_cb_info_s *cb_info) g_mutex_clear(&cb_info->idle_event_mutex); g_cond_clear(&cb_info->idle_event_cond); g_mutex_clear(&cb_info->mp_data_mutex); + g_mutex_clear(&cb_info->evas_mutex); LOGD("event thread removed"); @@ -1897,10 +1913,8 @@ static void _client_callback_destroy(camera_cb_info_s *cb_info) cb_info->pkt_fmt = NULL; } - if (cb_info->evas_info) { - g_free(cb_info->evas_info); - cb_info->evas_info = NULL; - } + if (cb_info->evas_info) + mm_evas_renderer_destroy(&cb_info->evas_info); cb_info->preview_cb_flag = 0; @@ -1910,6 +1924,79 @@ static void _client_callback_destroy(camera_cb_info_s *cb_info) return; } + +int _camera_start_evas_rendering(camera_h camera) +{ + int ret = CAMERA_ERROR_NONE; + camera_cli_s *pc = (camera_cli_s *)camera; + + if (camera == NULL) { + LOGE("INVALID_PARAMETER(0x%08x)", CAMERA_ERROR_INVALID_PARAMETER); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (pc->cb_info == NULL) { + LOGE("INVALID_PARAMETER(0x%08x)", CAMERA_ERROR_INVALID_PARAMETER); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("start"); + + if (!CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) { + LOGE("EVAS surface is not set"); + return CAMERA_ERROR_NONE; + } + + g_mutex_lock(&pc->cb_info->evas_mutex); + + /* set evas render flag as RUN */ + pc->cb_info->run_evas_render = true; + ret = CAMERA_ERROR_NONE; + + g_mutex_unlock(&pc->cb_info->evas_mutex); + + return ret; +} + + +int _camera_stop_evas_rendering(camera_h camera, bool keep_screen) +{ + int ret = CAMERA_ERROR_NONE; + camera_cli_s *pc = (camera_cli_s *)camera; + + if (camera == NULL) { + LOGE("INVALID_PARAMETER(0x%08x)", CAMERA_ERROR_INVALID_PARAMETER); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (pc->cb_info == NULL) { + LOGE("INVALID_PARAMETER(0x%08x)", CAMERA_ERROR_INVALID_PARAMETER); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + LOGD("stop - keep screen %d", keep_screen); + + if (!CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) { + LOGE("EVAS surface is not set"); + return CAMERA_ERROR_NONE; + } + + g_mutex_lock(&pc->cb_info->evas_mutex); + + /* set evas render flag as STOP and release buffers */ + pc->cb_info->run_evas_render = false; + ret = mm_evas_renderer_retrieve_all_packets(pc->cb_info->evas_info, keep_screen); + if (ret != MM_ERROR_NONE) { + LOGE("mm_evas_renderer_retrieve_all_packets failed 0x%x", ret); + ret = CAMERA_ERROR_INVALID_OPERATION; + } + + g_mutex_unlock(&pc->cb_info->evas_mutex); + + return ret; +} + + int camera_create(camera_device_e device, camera_h *camera) { int sock_fd = -1; @@ -2073,6 +2160,8 @@ int camera_start_preview(camera_h camera) if (ret != CAMERA_ERROR_NONE) { LOGE("start preview failed 0x%x", ret); return ret; + } else if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) { + ret = _camera_start_evas_rendering(camera); } LOGD("ret : 0x%x", ret); @@ -2103,6 +2192,22 @@ int camera_stop_preview(camera_h camera) LOGD("Enter"); + if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) { + camera_state_e current_state = CAMERA_STATE_NONE; + + ret = camera_get_state(camera, ¤t_state); + if (ret != CAMERA_ERROR_NONE) { + LOGE("failed to get current state 0x%x", ret); + return ret; + } + + if (current_state == CAMERA_STATE_PREVIEW) { + ret = _camera_stop_evas_rendering(camera, false); + if (ret != CAMERA_ERROR_NONE) + return ret; + } + } + /* send stop preview message */ muse_camera_msg_send(api, sock_fd, pc->cb_info, ret); @@ -2381,7 +2486,7 @@ int camera_stop_face_detection(camera_h camera) return ret; } -int camera_get_state(camera_h camera, camera_state_e * state) +int camera_get_state(camera_h camera, camera_state_e *state) { if (camera == NULL || state == NULL) { LOGE("INVALID_PARAMETER(0x%08x)", CAMERA_ERROR_INVALID_PARAMETER); @@ -2468,6 +2573,11 @@ int camera_set_display(camera_h camera, camera_display_type_e type, camera_displ #ifdef HAVE_WAYLAND camera_wl_info_s *wl_info = NULL; #endif /* HAVE_WAYLAND */ + camera_cli_s *pc = (camera_cli_s *)camera; + camera_cb_info_s *cb_info = NULL; + muse_camera_api_e api = MUSE_CAMERA_API_SET_DISPLAY; + camera_state_e current_state = CAMERA_STATE_NONE; + int sock_fd = 0; if (camera == NULL) { LOGE("INVALID_PARAMETER(0x%08x)", CAMERA_ERROR_INVALID_PARAMETER); @@ -2484,15 +2594,24 @@ int camera_set_display(camera_h camera, camera_display_type_e type, camera_displ return CAMERA_ERROR_INVALID_PARAMETER; } - camera_cli_s *pc = (camera_cli_s *)camera; - camera_cb_info_s *cb_info = (camera_cb_info_s *)pc->cb_info; - muse_camera_api_e api = MUSE_CAMERA_API_SET_DISPLAY; - int sock_fd; if (pc->cb_info == NULL) { LOGE("INVALID_PARAMETER(0x%08x)", CAMERA_ERROR_INVALID_PARAMETER); return CAMERA_ERROR_INVALID_PARAMETER; } - sock_fd = pc->cb_info->fd; + + cb_info = (camera_cb_info_s *)pc->cb_info; + sock_fd = cb_info->fd; + + ret = camera_get_state(camera, ¤t_state); + if (ret != CAMERA_ERROR_NONE) { + LOGE("failed to get current state 0x%x", ret); + return ret; + } + + if (current_state != CAMERA_STATE_CREATED) { + LOGE("INVALID_STATE : current %d", current_state); + return CAMERA_ERROR_INVALID_STATE; + } LOGD("Enter, remote_handle : %x display : 0x%x", pc->remote_handle, display); @@ -2520,15 +2639,48 @@ int camera_set_display(camera_h camera, camera_display_type_e type, camera_displ } else if (type == CAMERA_DISPLAY_TYPE_EVAS && !strcmp(object_type, "image")) { /* evas object surface */ set_display_handle = (void *)display; - SET_PREVIEW_CB_TYPE(cb_info, PREVIEW_CB_TYPE_EVAS); + LOGD("display type EVAS : handle %p", set_display_handle); + + g_mutex_lock(&cb_info->evas_mutex); + + if (cb_info->evas_info) { + LOGW("destroy existed evas renderer %p", cb_info->evas_info); + ret = mm_evas_renderer_destroy(&cb_info->evas_info); + if (ret != MM_ERROR_NONE) { + LOGE("failed to destroy evas renderer %p", cb_info->evas_info); + g_mutex_unlock(&cb_info->evas_mutex); + return CAMERA_ERROR_INVALID_OPERATION; + } + } - if (mm_evas_renderer_create(&cb_info->evas_info, obj) != MM_ERROR_NONE) { - UNSET_PREVIEW_CB_TYPE(cb_info, PREVIEW_CB_TYPE_EVAS); - LOGE("failed to create mm evas renderer"); + /* create evas renderer */ + ret = mm_evas_renderer_create(&cb_info->evas_info, (Evas_Object *)set_display_handle); + if (ret == MM_ERROR_NONE) { + camera_flip_e flip = CAMERA_FLIP_NONE; + camera_display_mode_e mode = CAMERA_DISPLAY_MODE_LETTER_BOX; + camera_rotation_e rotation = CAMERA_ROTATION_NONE; + bool visible = 0; + + camera_get_display_flip(camera, &flip); + camera_get_display_mode(camera, &mode); + camera_get_display_rotation(camera, &rotation); + camera_is_display_visible(camera, &visible); + + LOGD("current setting : flip %d, mode %d, rotation %d, visible %d", + flip, mode, rotation, visible); + + ret = mm_evas_renderer_set_geometry(cb_info->evas_info, mode); + ret |= mm_evas_renderer_set_rotation(cb_info->evas_info, rotation); + ret |= mm_evas_renderer_set_visible(cb_info->evas_info, visible); + } + + g_mutex_unlock(&cb_info->evas_mutex); + + if (ret != MM_ERROR_NONE) { + LOGE("mm_evas_renderer error 0x%x", ret); return CAMERA_ERROR_INVALID_OPERATION; } - LOGD("display type EVAS : handle %p", set_display_handle); } else { LOGE("unknown evas object [%p,%s] or type [%d] mismatch", obj, object_type, type); return CAMERA_ERROR_INVALID_PARAMETER; @@ -2544,25 +2696,24 @@ int camera_set_display(camera_h camera, camera_display_type_e type, camera_displ if (type == CAMERA_DISPLAY_TYPE_OVERLAY) { #ifdef HAVE_WAYLAND wl_info = &pc->wl_info; - muse_camera_msg_send_array_and_value(api, sock_fd, pc->cb_info, ret, + muse_camera_msg_send_array_and_value(api, sock_fd, cb_info, ret, wl_info, 5, sizeof(int), INT, type); LOGD("wayland parent id : %d, window %d,%d,%dx%d", wl_info->parent_id, wl_info->window_x, wl_info->window_y, wl_info->window_width, wl_info->window_height); #else /* HAVE_WAYLAND */ - muse_camera_msg_send2(api, sock_fd, pc->cb_info, ret, INT, type, INT, set_display_handle); + muse_camera_msg_send2(api, sock_fd, cb_info, ret, INT, type, INT, set_display_handle); LOGD("x id : %d", (int)set_display_handle); #endif /* HAVE_WAYLAND */ } else - muse_camera_msg_send1(api, sock_fd, pc->cb_info, ret, INT, type); + muse_camera_msg_send1(api, sock_fd, cb_info, ret, INT, type); if (ret != CAMERA_ERROR_NONE) { - if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) - UNSET_PREVIEW_CB_TYPE(cb_info, PREVIEW_CB_TYPE_EVAS); - LOGE("set display error 0x%x", ret); + } else if (type == CAMERA_DISPLAY_TYPE_EVAS) { + SET_PREVIEW_CB_TYPE(cb_info, PREVIEW_CB_TYPE_EVAS); } return ret; @@ -2724,15 +2875,21 @@ int camera_set_display_rotation(camera_h camera, camera_rotation_e rotation) } if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) { - if (mm_evas_renderer_set_rotation(pc->cb_info->evas_info, rotation) != MM_ERROR_NONE) { - LOGE("failed to set rotation for evas surface."); + g_mutex_lock(&pc->cb_info->evas_mutex); + + ret = mm_evas_renderer_set_rotation(pc->cb_info->evas_info, rotation); + + g_mutex_unlock(&pc->cb_info->evas_mutex); + + if (ret!= MM_ERROR_NONE) { + LOGE("failed to set rotation for evas surface 0x%x", ret); return CAMERA_ERROR_INVALID_OPERATION; } - } else { - muse_camera_msg_send1(MUSE_CAMERA_API_SET_DISPLAY_ROTATION, - pc->cb_info->fd, pc->cb_info, ret, INT, set_rotation); } + muse_camera_msg_send1(MUSE_CAMERA_API_SET_DISPLAY_ROTATION, + pc->cb_info->fd, pc->cb_info, ret, INT, set_rotation); + return ret; } @@ -2755,8 +2912,14 @@ int camera_get_display_rotation(camera_h camera, camera_rotation_e *rotation) } if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) { - if (mm_evas_renderer_get_rotation(pc->cb_info->evas_info, (int *)rotation) != MM_ERROR_NONE) { - LOGE("failed to get rotation for evas surface."); + g_mutex_lock(&pc->cb_info->evas_mutex); + + ret = mm_evas_renderer_get_rotation(pc->cb_info->evas_info, (int *)rotation); + + g_mutex_unlock(&pc->cb_info->evas_mutex); + + if (ret != MM_ERROR_NONE) { + LOGE("failed to get rotation for evas surface 0x%x", ret); return CAMERA_ERROR_INVALID_OPERATION; } } else { @@ -2849,15 +3012,21 @@ int camera_set_display_visible(camera_h camera, bool visible) } if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) { - if (mm_evas_renderer_set_visible(pc->cb_info->evas_info, visible) != MM_ERROR_NONE) { - LOGE("failed to set visible for evas surface."); + g_mutex_lock(&pc->cb_info->evas_mutex); + + ret = mm_evas_renderer_set_visible(pc->cb_info->evas_info, visible); + + g_mutex_unlock(&pc->cb_info->evas_mutex); + + if (ret != MM_ERROR_NONE) { + LOGE("failed to set visible for evas surface 0x%x", ret); return CAMERA_ERROR_INVALID_OPERATION; } - } else { - muse_camera_msg_send1(MUSE_CAMERA_API_SET_DISPLAY_VISIBLE, - pc->cb_info->fd, pc->cb_info, ret, INT, set_visible); } + muse_camera_msg_send1(MUSE_CAMERA_API_SET_DISPLAY_VISIBLE, + pc->cb_info->fd, pc->cb_info, ret, INT, set_visible); + return ret; } @@ -2880,8 +3049,14 @@ int camera_is_display_visible(camera_h camera, bool *visible) } if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) { - if (mm_evas_renderer_get_visible(pc->cb_info->evas_info, visible) != MM_ERROR_NONE) { - LOGE("failed to get visible for evas surface."); + g_mutex_lock(&pc->cb_info->evas_mutex); + + ret = mm_evas_renderer_get_visible(pc->cb_info->evas_info, visible); + + g_mutex_unlock(&pc->cb_info->evas_mutex); + + if (ret != MM_ERROR_NONE) { + LOGE("failed to get visible for evas surface 0x%x", ret); return CAMERA_ERROR_INVALID_OPERATION; } } else { @@ -2921,15 +3096,21 @@ int camera_set_display_mode(camera_h camera, camera_display_mode_e mode) } if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) { - if (mm_evas_renderer_set_geometry(pc->cb_info->evas_info, mode) != MM_ERROR_NONE) { - LOGE("failed to set geometry for evas surface."); + g_mutex_lock(&pc->cb_info->evas_mutex); + + ret = mm_evas_renderer_set_geometry(pc->cb_info->evas_info, mode); + + g_mutex_unlock(&pc->cb_info->evas_mutex); + + if (ret != MM_ERROR_NONE) { + LOGE("failed to set geometry for evas surface 0x%x", ret); return CAMERA_ERROR_INVALID_OPERATION; } - } else { - muse_camera_msg_send1(MUSE_CAMERA_API_SET_DISPLAY_MODE, - pc->cb_info->fd, pc->cb_info, ret, INT, set_mode); } + muse_camera_msg_send1(MUSE_CAMERA_API_SET_DISPLAY_MODE, + pc->cb_info->fd, pc->cb_info, ret, INT, set_mode); + return ret; } @@ -2952,8 +3133,14 @@ int camera_get_display_mode(camera_h camera, camera_display_mode_e *mode) } if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) { - if (mm_evas_renderer_get_geometry(pc->cb_info->evas_info, (int *)mode) != MM_ERROR_NONE) { - LOGE("failed to get geometry for evas surface."); + g_mutex_lock(&pc->cb_info->evas_mutex); + + ret = mm_evas_renderer_get_geometry(pc->cb_info->evas_info, (int *)mode); + + g_mutex_unlock(&pc->cb_info->evas_mutex); + + if (ret != MM_ERROR_NONE) { + LOGE("failed to get geometry for evas surface 0x%x", ret); return CAMERA_ERROR_INVALID_OPERATION; } } else { diff --git a/src/camera_internal.c b/src/camera_internal.c new file mode 100644 index 0000000..b783041 --- /dev/null +++ b/src/camera_internal.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "TIZEN_N_CAMERA" + + +int camera_start_evas_rendering(camera_h camera) +{ + return _camera_start_evas_rendering(camera); +} + +int camera_stop_evas_rendering(camera_h camera, bool keep_screen) +{ + return _camera_stop_evas_rendering(camera, keep_screen); +} \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6f469b2..11b9936 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,7 +5,7 @@ SET(fw_test "${fw_name}-test") #link_directories(${CMAKE_SOURCE_DIR}/../) INCLUDE(FindPkgConfig) -pkg_check_modules(${fw_test} REQUIRED elementary evas ecore) +pkg_check_modules(${fw_test} REQUIRED elementary evas ecore appcore-efl) FOREACH(flag ${${fw_test}_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") MESSAGE(${flag}) diff --git a/test/camera_test.c b/test/camera_test.c index bb2e3f9..a4d0d3e 100644 --- a/test/camera_test.c +++ b/test/camera_test.c @@ -30,18 +30,36 @@ #include #include #include +#include /*----------------------------------------------------------------------- | GLOBAL VARIABLE DEFINITIONS: | -----------------------------------------------------------------------*/ #define EXPORT_API __attribute__((__visibility__("default"))) +#ifdef PACKAGE +#undef PACKAGE +#endif +#define PACKAGE "camera_test" + + +static int app_create(void *data); +static int app_terminate(void *data); + +struct _appdata { + Evas_Object *win; + Evas_Object *eo; + Evas_Object *bg; + Evas_Object *rect; +}; +typedef struct _appdata appdata; -Evas_Object *eo; -Evas_Object *win; -Evas_Object *bg; -Evas_Object *rect; -GMainLoop *g_loop; +struct appcore_ops ops = { + .create = app_create, + .terminate = app_terminate, +}; + +appdata ad; GIOChannel *stdin_channel; camera_device_e cam_info; int resolution_set; @@ -148,6 +166,7 @@ enum { }; enum { + MENU_STATE_INIT, MENU_STATE_MAIN, MENU_STATE_SETTING, MENU_STATE_NUM, @@ -419,7 +438,7 @@ const char *facing_direction[] = { ---------------------------------------------------------------------------*/ static void print_menu(); static gboolean cmd_input(GIOChannel *channel); -static gboolean mode_change(); +static gboolean mode_change(gchar buf); int camcordertest_set_attr_int(const char* attr_subcategory, int value); bool preview_resolution_cb(int width, int height, void *user_data); @@ -635,6 +654,17 @@ void capture_completed_cb(void *user_data) static void print_menu() { switch (hcamcorder->menu_state) { + case MENU_STATE_INIT: + g_print("\n\t=======================================\n"); + g_print("\t CAMERA_TESTSUITE\n"); + g_print("\t=======================================\n"); + g_print("\t '1' Video Capture - Front Camera\n"); + g_print("\t '2' Video Capture - Rear Camera\n"); + g_print("\t 'q' Exit\n"); + g_print("\t=======================================\n"); + + g_print("\t Enter the media type:\n\t"); + break; case MENU_STATE_MAIN: if (hcamcorder->mode == MODE_VIDEO_CAPTURE) { g_print("\n\t=======================================\n"); @@ -694,7 +724,7 @@ static void print_menu() g_print("\t=======================================\n"); break; default: - LOGE("unknow menu state !!\n"); + g_print("\n\tunknow menu state !!\n"); break; } @@ -737,8 +767,8 @@ static void main_menu(gchar buf) camera_stop_preview(hcamcorder->camera); camera_destroy(hcamcorder->camera); hcamcorder->camera = NULL; - hcamcorder->menu_state = MENU_STATE_MAIN; - mode_change(); + hcamcorder->menu_state = MENU_STATE_INIT; + print_menu(); break; default: g_print("\t Invalid input \n"); @@ -746,8 +776,8 @@ static void main_menu(gchar buf) } } else { g_print("\t Invalid mode, back to upper menu \n"); - hcamcorder->menu_state = MENU_STATE_MAIN; - mode_change(); + hcamcorder->menu_state = MENU_STATE_INIT; + print_menu(); } return; @@ -1168,11 +1198,11 @@ static gboolean cmd_input(GIOChannel *channel) gsize read_size; GError *g_error = NULL; - LOGD("ENTER"); + g_print("\n\tENTER\n"); g_io_channel_read_line(channel, &buf, &read_size, NULL, &g_error); if (g_error) { - LOGD("g_io_channel_read_chars error"); + g_print("\n\tg_io_channel_read_chars error\n"); g_error_free(g_error); g_error = NULL; } @@ -1180,8 +1210,11 @@ static gboolean cmd_input(GIOChannel *channel) if (buf) { g_strstrip(buf); - LOGD("Menu Status : %d", hcamcorder->menu_state); + g_print("\n\tMenu Status : %d\n", hcamcorder->menu_state); switch (hcamcorder->menu_state) { + case MENU_STATE_INIT: + mode_change(buf[0]); + break; case MENU_STATE_MAIN: main_menu(buf[0]); break; @@ -1197,7 +1230,7 @@ static gboolean cmd_input(GIOChannel *channel) print_menu(); } else { - LOGD("No read input"); + g_print("\n\tNo read input\n"); } return TRUE; @@ -1211,7 +1244,7 @@ static gboolean init_handle() hcamcorder->multishot_count = 0; /* total multishot count */ hcamcorder->stillshot_filename = STILL_CAPTURE_FILE_PATH_NAME; /* stored filename of stillshot */ hcamcorder->multishot_filename = MULTI_CAPTURE_FILE_PATH_NAME; /* stored filename of multishot */ - hcamcorder->menu_state = MENU_STATE_MAIN; + hcamcorder->menu_state = MENU_STATE_INIT; hcamcorder->isMute = FALSE; hcamcorder->elapsed_time = 0; multishot_num = IMAGE_CAPTURE_COUNT_MULTI; @@ -1257,117 +1290,134 @@ void _preview_cb(camera_preview_data_s *frame, void *user_data) /** * This function is to change camcorder mode. * - * @param type [in] image(capture)/video(recording) mode + * @param buf [in] user input * * @return This function returns TRUE/FALSE * @remark * @see other functions */ -static gboolean mode_change() +static gboolean mode_change(gchar buf) { int err = 0; - char media_type = '\0'; + char display_type = '\0'; bool check = FALSE; - camera_display_type_e display_type = CAMERA_DISPLAY_TYPE_EVAS; - init_handle(); - while (!check) { - g_print("\n\t=======================================\n"); - g_print("\t CAMERA_TESTSUITE\n"); - g_print("\t=======================================\n"); - g_print("\t '1' Video Capture - Front Camera\n"); - g_print("\t '2' Video Capture - Rear Camera\n"); - g_print("\t 'q' Exit\n"); - g_print("\t=======================================\n"); + switch (buf) { + case '1': + hcamcorder->mode = MODE_VIDEO_CAPTURE; + cam_info = CAMERA_DEVICE_CAMERA1; + check = TRUE; + break; + case '2': + hcamcorder->mode = MODE_VIDEO_CAPTURE; + cam_info = CAMERA_DEVICE_CAMERA0; + check = TRUE; + break; + case 'q': + g_print("\t Quit Camcorder Testsuite!!\n"); + hcamcorder->mode = -1; + elm_exit(); + return FALSE; + default: + g_print("\t Invalid media type(%c)\n", buf); + return FALSE; + } - g_print("\t Enter the media type:\n\t"); + g_print("\n[camcorder_create - type %d]\n", cam_info); + + g_get_current_time(&previous_time); + + g_timer_reset(timer); + + err = camera_create(cam_info, &hcamcorder->camera); + + g_print("[camera_create() : %12.6lfs]\n", g_timer_elapsed(timer, NULL)); + + if (err != 0) { + g_print("\n\tmmcamcorder_create = 0x%x\n", err); + return -1; + } + + camera_print_state = CAMERA_STATE_CREATED; - err = scanf("%c", &media_type); + check = FALSE; + while (!check) { + g_print("\n\tEnter the Display Type\n"); + g_print("\t'1' OVERLAY surface\n"); + g_print("\t'2' EVAS surface\n"); + g_print("\t'3' NONE surface\n"); + + err = scanf("%c", &display_type); if (err == EOF) { g_print("\t!!!read input error!!!\n"); continue; } - switch (media_type) { + switch (display_type) { case '1': - hcamcorder->mode = MODE_VIDEO_CAPTURE; - cam_info = CAMERA_DEVICE_CAMERA1; + camera_set_display(hcamcorder->camera, CAMERA_DISPLAY_TYPE_OVERLAY, GET_DISPLAY(ad.win)); check = TRUE; break; case '2': - hcamcorder->mode = MODE_VIDEO_CAPTURE; - cam_info = CAMERA_DEVICE_CAMERA0; + camera_set_display(hcamcorder->camera, CAMERA_DISPLAY_TYPE_EVAS, GET_DISPLAY(ad.eo)); + check = TRUE; + break; + case '3': + camera_set_display(hcamcorder->camera, CAMERA_DISPLAY_TYPE_NONE, NULL); check = TRUE; break; - case 'q': - g_print("\t Quit Camcorder Testsuite!!\n"); - hcamcorder->mode = -1; - if (g_main_loop_is_running(g_loop)) - g_main_loop_quit(g_loop); - - return FALSE; default: - g_print("\t Invalid media type(%d)\n", media_type); - continue; + g_print("\t Invalid display type(%c)\n", display_type); + break; } } - LOGD("camcorder_create"); - g_get_current_time(&previous_time); - g_timer_reset(timer); - - err = camera_create(cam_info, &hcamcorder->camera); - LOGD("camera_create() : %12.6lfs", g_timer_elapsed(timer, NULL)); - - if (err != 0) { - LOGE("mmcamcorder_create = %x", err); - return -1; - } else { - camera_state = CAMERA_STATE_NONE; - } - camera_print_state = CAMERA_STATE_CREATED; - camera_set_state_changed_cb(hcamcorder->camera, _camera_state_changed_cb, NULL); camera_set_interrupted_cb(hcamcorder->camera, _camera_interrupted_cb, NULL); - camera_set_display(hcamcorder->camera, display_type, - (display_type == CAMERA_DISPLAY_TYPE_OVERLAY)?GET_DISPLAY(win):GET_DISPLAY(eo)); camera_set_display_mode(hcamcorder->camera, CAMERA_DISPLAY_MODE_LETTER_BOX); /*camera_set_display_rotation(hcamcorder->camera, CAMERA_ROTATION_90);*/ /*camera_set_display_flip(hcamcorder->camera, CAMERA_FLIP_VERTICAL);*/ - /*camera_set_preview_cb(hcamcorder->camera, _preview_cb, hcamcorder->camera);*/ camera_start_preview(hcamcorder->camera); + g_get_current_time(¤t_time); timersub(¤t_time, &previous_time, &res); - LOGD("Camera Starting Time : %ld.%lds", res.tv_sec, res.tv_usec); + + g_print("\n\tCamera Starting Time : %ld.%lds\n", res.tv_sec, res.tv_usec); + camera_print_state = CAMERA_STATE_PREVIEW; + hcamcorder->menu_state = MENU_STATE_MAIN; + + print_menu(); return TRUE; } - -/** - * This function is the example main function for mmcamcorder API. - * - * @param - * - * @return This function returns 0. - * @remark - * @see other functions - */ -int main(int argc, char **argv) +static int app_create(void *data) { + appdata *app_data = data; + int w = 0; + int h = 0; + Evas_Object *win = NULL; + Evas_Object *eo = NULL; + Evas_Object *bg = NULL; + Evas_Object *rect = NULL; + + if (app_data == NULL) { + g_print("\t\nappdata is NULL\n"); + return 0; + } - int bret; - int w, h; - elm_init(argc, argv); + /* use gl backend */ + elm_config_accel_preference_set("opengl"); - win = elm_win_add(NULL, "VIDEO OVERLAY", ELM_WIN_BASIC); + win = elm_win_add(NULL, "camera_test", ELM_WIN_BASIC); if (win) { - elm_win_title_set(win, "TITLE"); + elm_win_title_set(win, "camera_test"); elm_win_borderless_set(win, EINA_TRUE); elm_win_screen_size_get(win, NULL, NULL, &w, &h); + g_print("\n\tscreen size %dx%d\n\n", w, h); evas_object_resize(win, w, h); elm_win_autodel_set(win, EINA_TRUE); #ifdef HAVE_WAYLAND @@ -1400,57 +1450,78 @@ int main(int argc, char **argv) elm_win_resize_object_add(win, rect); evas_object_size_hint_weight_set(rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); evas_object_show(rect); - elm_win_activate(win); - evas_object_show(win); /* Create evas image object for EVAS surface */ eo = evas_object_image_add(evas_object_evas_get(win)); - evas_object_image_size_set(eo, 960, 720); - evas_object_image_fill_set(eo, 0, 0, 960, 720); - evas_object_resize(eo, 960, 720); + evas_object_image_size_set(eo, w, h); + evas_object_image_fill_set(eo, 0, 0, w, h); + evas_object_resize(eo, w, h); + evas_object_show(eo); elm_win_activate(win); evas_object_show(win); -#if !GLIB_CHECK_VERSION(2, 35, 0) - if (!g_thread_supported()) - g_thread_init(NULL); -#endif + app_data->win = win; + app_data->eo = eo; timer = g_timer_new(); - - hcamcorder = (cam_handle_t *) g_malloc0(sizeof(cam_handle_t)); - camera_state = CAMERA_STATE_NONE; - g_timer_reset(timer); - bret = mode_change(); - if (!bret) - return bret; + init_handle(); print_menu(); - g_loop = g_main_loop_new(NULL, FALSE); - - stdin_channel = g_io_channel_unix_new(fileno(stdin));/* read from stdin */ - g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)cmd_input, NULL); - - LOGD("RUN main loop"); + return 0; +} - g_main_loop_run(g_loop); +static int app_terminate(void *data) +{ + appdata *app_data = data; - LOGD("STOP main loop"); + if (app_data == NULL) { + g_print("\n\tappdata is NULL\n"); + return 0; + } if (timer) { g_timer_stop(timer); g_timer_destroy(timer); timer = NULL; } + + return 0; +} + + +/** + * This function is the example main function for mmcamcorder API. + * + * @param + * + * @return This function returns 0. + * @remark + * @see other functions + */ +int main(int argc, char **argv) +{ + int bret; + + hcamcorder = (cam_handle_t *) g_malloc0(sizeof(cam_handle_t)); + camera_state = CAMERA_STATE_NONE; + + stdin_channel = g_io_channel_unix_new(fileno(stdin));/* read from stdin */ + g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)cmd_input, NULL); + + memset(&ad, 0x0, sizeof(appdata)); + ops.data = &ad; + + bret = appcore_efl_main(PACKAGE, &argc, &argv, &ops); + + g_print("\n\treturn appcore_efl : %d\n\n", bret); + g_free(hcamcorder); - g_main_loop_unref(g_loop); g_io_channel_unref(stdin_channel); return bret; } - /*EOF*/ -- 2.7.4