From: Eunhae Choi Date: Tue, 27 Sep 2016 10:58:50 +0000 (+0900) Subject: [v0.3.23] sync cb invoke context with tizen 2.4 and apply tizen coding rule X-Git-Tag: accepted/tizen/common/20160928.163904^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=708cdc3e3320245f9b1cd3bbc8b5ca08f24ced94;p=platform%2Fcore%2Fapi%2Fplayer.git [v0.3.23] sync cb invoke context with tizen 2.4 and apply tizen coding rule Change-Id: I234bad689b578303024bb896d8430363d2609144 --- diff --git a/include/common/player_internal.h b/include/common/player_internal.h index 91675d5..5f267c2 100644 --- a/include/common/player_internal.h +++ b/include/common/player_internal.h @@ -187,6 +187,7 @@ int player_set_streaming_playback_rate(player_h player, float rate); * @brief Registers a callback function to be invoked when buffer underrun or overflow is occurred. * @since_tizen 3.0 * @remarks This API is used for media stream playback only. + * @remarks The registered callback is issued in the internal thread of the player. * @param[in] player The handle to the media player * @param[in] type The type of target stream * @param[in] callback The buffer status callback function to register @@ -277,14 +278,6 @@ typedef void (*player_buffer_enough_data_cb) (void *user_data); typedef void (*player_buffer_need_data_cb) (unsigned int size, void *user_data); /** - * @brief Called to notify the resource conflict - * @since_tizen 3.0 - * @param[in] user_data The user data passed from the callback registration function - * @see player_set_resourceconflict_cb() - */ -typedef void (*player_resourceconflict_cb)(void *user_data); - -/** * @brief Submits packet to appsrc, used in external demux mode * @since_tizen 3.0 * @param[in] player The handle to media player @@ -317,6 +310,7 @@ int player_set_audio_stream_info(player_h player, player_audio_stream_info_s *in /** * @brief Registers the callback function. * @since_tizen 3.0 + * @remarks The registered callback is issued in the internal thread of the player. * @param[in] player The handle to media player * @param[in] callback The callback function to register * @param[in] user_data The user data to be passed to the callback function @@ -330,6 +324,7 @@ int player_set_buffer_enough_video_data_cb(player_h player, player_buffer_enough /** * @brief Registers the callback function. * @since_tizen 3.0 + * @remarks The registered callback is issued in the internal thread of the player. * @param[in] player The handle to media player * @param[in] callback The callback function to register * @param[in] user_data The user data to be passed to the callback function @@ -343,6 +338,7 @@ int player_set_buffer_enough_audio_data_cb(player_h player, player_buffer_enough /** * @brief Registers the callback function. * @since_tizen 3.0 + * @remarks The registered callback is issued in the internal thread of the player. * @param[in] player The handle to media player * @param[in] callback The callback function to register * @param[in] user_data The user data to be passed to the callback function @@ -356,6 +352,7 @@ int player_set_buffer_need_video_data_cb(player_h player, player_buffer_need_dat /** * @brief Registers the callback function. * @since_tizen 3.0 + * @remarks The registered callback is issued in the internal thread of the player. * @param[in] player The handle to media player * @param[in] callback The callback function to register * @param[in] user_data The user data to be passed to the callback function @@ -367,33 +364,6 @@ int player_set_buffer_need_video_data_cb(player_h player, player_buffer_need_dat int player_set_buffer_need_audio_data_cb(player_h player, player_buffer_need_data_cb callback, void *user_data); /** - * @brief Registers a callback function to be invoked when the resource conflict is detected. - * @since_tizen 3.0 - * @param[in] player The handle to the media player - * @param[in] callback The callback function to register - * @param[in] user_data The user data to be passed to the callback function - * @return @c 0 on success, - * otherwise a negative error value - * @retval #PLAYER_ERROR_NONE Successful - * @retval #PLAYER_ERROR_INVALID_PARAMETER Invalid parameter - * @post player_resourceconflict_cb() will be invoked. - * @see player_unset_resourceconflict_cb() - */ -int player_set_resourceconflict_cb(player_h player, player_resourceconflict_cb callback, void *user_data); - -/** - * @brief Unregisters the callback function. - * @since_tizen 3.0 - * @param[in] player The handle to the media player - * @return @c 0 on success, - * otherwise a negative error value - * @retval #PLAYER_ERROR_NONE Successful - * @retval #PLAYER_ERROR_INVALID_PARAMETER Invalid parameter - * @see player_set_resourceconflict_cb() - */ -int player_unset_resourceconflict_cb(player_h player); - -/** * @brief Display the first video frame at the player_prepare() function to improve the playback performance. * @since_tizen 3.0 * @details This is only availble when you want to start playback from 0 position. diff --git a/include/player_private.h b/include/player_private.h index b97357a..24beb65 100644 --- a/include/player_private.h +++ b/include/player_private.h @@ -78,6 +78,9 @@ typedef struct { GMutex mutex; GCond cond; gboolean running; + + GMutex idle_ev_mutex; + GList *idle_ev_list; } player_event_queue; typedef struct { diff --git a/include/wearable/player_internal.h b/include/wearable/player_internal.h index 33d9961..a1b01dd 100644 --- a/include/wearable/player_internal.h +++ b/include/wearable/player_internal.h @@ -123,6 +123,7 @@ int player_set_streaming_playback_rate(player_h player, float rate); * @brief Registers a callback function to be invoked when buffer underrun or overflow is occurred. * @since_tizen 3.0 * @remarks This API is used for media stream playback only. + * @remarks The registered callback is issued in the internal thread of the player. * @param[in] player The handle to the media player * @param[in] type The type of target stream * @param[in] callback The buffer status callback function to register diff --git a/packaging/capi-media-player.spec b/packaging/capi-media-player.spec index 782770c..89699da 100644 --- a/packaging/capi-media-player.spec +++ b/packaging/capi-media-player.spec @@ -1,6 +1,6 @@ Name: capi-media-player Summary: A Media Player API -Version: 0.3.22 +Version: 0.3.23 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/player.c b/src/player.c index 026b0e1..f6769a4 100644 --- a/src/player.c +++ b/src/player.c @@ -51,6 +51,7 @@ typedef struct { int int_data; char *buf; callback_cb_info_s *cb_info; + GMutex event_mutex; } _player_cb_data; typedef struct { @@ -424,25 +425,25 @@ static void __complete_cb_handler(callback_cb_info_s * cb_info, char *recvMsg) static char* _convert_code_to_str(int code) { switch (code) { - case PLAYER_INTERRUPTED_COMPLETED: /* Deprecated since 3.0 */ - return "PLAYER_INTERRUPTED_COMPLETED"; - case PLAYER_INTERRUPTED_BY_MEDIA: /* Deprecated since 3.0 */ - return "PLAYER_INTERRUPTED_BY_MEDIA"; - case PLAYER_INTERRUPTED_BY_CALL: /* Deprecated since 3.0 */ - return "PLAYER_INTERRUPTED_BY_CALL"; - case PLAYER_INTERRUPTED_BY_EARJACK_UNPLUG: /* Deprecated since 3.0 */ - return "PLAYER_INTERRUPTED_BY_EARJACK_UNPLUG"; - case PLAYER_INTERRUPTED_BY_RESOURCE_CONFLICT: - return "PLAYER_INTERRUPTED_BY_RESOURCE_CONFLICT"; - case PLAYER_INTERRUPTED_BY_ALARM: /* Deprecated since 3.0 */ - return "PLAYER_INTERRUPTED_BY_ALARM"; - case PLAYER_INTERRUPTED_BY_EMERGENCY: /* Deprecated since 3.0 */ - return "PLAYER_INTERRUPTED_BY_EMERGENCY"; - case PLAYER_INTERRUPTED_BY_NOTIFICATION: /* Deprecated since 3.0 */ - return "PLAYER_INTERRUPTED_BY_NOTIFICATION"; - default: - LOGE("Invalid interrupted code %d (Never enter here)", code); - return NULL; + case PLAYER_INTERRUPTED_COMPLETED: /* Deprecated since 3.0 */ + return "PLAYER_INTERRUPTED_COMPLETED"; + case PLAYER_INTERRUPTED_BY_MEDIA: /* Deprecated since 3.0 */ + return "PLAYER_INTERRUPTED_BY_MEDIA"; + case PLAYER_INTERRUPTED_BY_CALL: /* Deprecated since 3.0 */ + return "PLAYER_INTERRUPTED_BY_CALL"; + case PLAYER_INTERRUPTED_BY_EARJACK_UNPLUG: /* Deprecated since 3.0 */ + return "PLAYER_INTERRUPTED_BY_EARJACK_UNPLUG"; + case PLAYER_INTERRUPTED_BY_RESOURCE_CONFLICT: + return "PLAYER_INTERRUPTED_BY_RESOURCE_CONFLICT"; + case PLAYER_INTERRUPTED_BY_ALARM: /* Deprecated since 3.0 */ + return "PLAYER_INTERRUPTED_BY_ALARM"; + case PLAYER_INTERRUPTED_BY_EMERGENCY: /* Deprecated since 3.0 */ + return "PLAYER_INTERRUPTED_BY_EMERGENCY"; + case PLAYER_INTERRUPTED_BY_NOTIFICATION: /* Deprecated since 3.0 */ + return "PLAYER_INTERRUPTED_BY_NOTIFICATION"; + default: + LOGE("Invalid interrupted code %d (Never enter here)", code); + return NULL; } } @@ -992,16 +993,54 @@ static void (*_user_callbacks[MUSE_PLAYER_EVENT_TYPE_NUM]) (callback_cb_info_s * __video_stream_changed_cb_handler, /* MUSE_PLAYER_EVENT_TYPE_VIDEO_STREAM_CHANGED */ }; -static void _player_event_job_function(_player_cb_data * data) +gboolean _player_event_job_function(void *user_data) { + _player_cb_data *data = (_player_cb_data *)user_data; + + if (data == NULL) { + LOGE("data is null"); + return FALSE; + } + + LOGD("enter ev:%d", data->int_data); + + g_mutex_lock(&data->event_mutex); + muse_player_event_e ev = data->int_data; + + /* remove event from list */ + g_mutex_lock(&data->cb_info->event_queue.idle_ev_mutex); + LOGD("remove idle event %p, %p", data, data->cb_info->event_queue.idle_ev_list); + if (data->cb_info->event_queue.idle_ev_list) + data->cb_info->event_queue.idle_ev_list = g_list_remove(data->cb_info->event_queue.idle_ev_list, (gpointer)data); + g_mutex_unlock(&data->cb_info->event_queue.idle_ev_mutex); + if (data->cb_info->user_cb[ev]) _user_callbacks[ev] (data->cb_info, data->buf); else LOGW("user callback is unset. type : %d", ev); + /* unlock and release event */ + g_mutex_unlock(&data->event_mutex); + g_mutex_clear(&data->event_mutex); + g_free(data->buf); g_free(data); + + return FALSE; /* remove from the event list */ +} + +static bool _player_need_sync_context(int event_id) +{ + if ((event_id == MUSE_PLAYER_EVENT_TYPE_INTERRUPT) || + (event_id == MUSE_PLAYER_EVENT_TYPE_BUFFERING) || + (event_id == MUSE_PLAYER_EVENT_TYPE_PD) || + (event_id == MUSE_PLAYER_EVENT_TYPE_COMPLETE)) { + LOGD("%d callback will be issued in the mainloop.", event_id); + return TRUE; + } else { + return FALSE; + } } static void *_player_event_queue_loop(void *param) @@ -1012,7 +1051,7 @@ static void *_player_event_queue_loop(void *param) } callback_cb_info_s *cb_info = param; player_event_queue *ev = &cb_info->event_queue; - _player_cb_data *event_data; + _player_cb_data *event_data = NULL; g_mutex_lock(&ev->mutex); while (ev->running) { @@ -1029,10 +1068,24 @@ static void *_player_event_queue_loop(void *param) g_mutex_lock(&ev->qlock); event_data = (_player_cb_data *) g_queue_pop_head(ev->queue); g_mutex_unlock(&ev->qlock); - if (event_data) - _player_event_job_function(event_data); - else + if (event_data) { + if (_player_need_sync_context(event_data->int_data)) { + g_mutex_lock(&ev->idle_ev_mutex); + ev->idle_ev_list = g_list_append(ev->idle_ev_list, (gpointer)event_data); + g_mutex_unlock(&ev->idle_ev_mutex); + + LOGD("add ev %d to main loop", event_data->int_data); + + g_idle_add_full(G_PRIORITY_DEFAULT, + (GSourceFunc)_player_event_job_function, + (gpointer)event_data, + NULL); + } else { + _player_event_job_function(event_data); + } + } else { break; + } } } g_mutex_unlock(&ev->mutex); @@ -1052,6 +1105,9 @@ static gboolean _player_event_queue_new(callback_cb_info_s * cb_info) g_mutex_init(&ev->mutex); g_cond_init(&ev->cond); ev->running = TRUE; + + g_mutex_init(&ev->idle_ev_mutex); + ev->thread = g_thread_new("cb_event_thread", _player_event_queue_loop, (gpointer) cb_info); g_return_val_if_fail(ev->thread, FALSE); LOGI("event queue thread %p", ev->thread); @@ -1060,6 +1116,67 @@ static gboolean _player_event_queue_new(callback_cb_info_s * cb_info) } +static void _player_remove_idle_event_all(callback_cb_info_s *cb_info) +{ + g_return_if_fail(cb_info); + player_event_queue *ev = &cb_info->event_queue; + _player_cb_data *event_data = NULL; + + g_mutex_lock(&ev->idle_ev_mutex); + + if (ev->idle_ev_list == NULL) { + LOGD("No idle event is remained."); + } else { + GList *list = NULL; + list = ev->idle_ev_list; + + while (list) { + event_data = list->data; + + if (!event_data) { + list = g_list_next(list); + LOGW("Fail to remove idle event. The data is NULL"); + } else { + if (g_mutex_trylock(&event_data->event_mutex)) { + bool ret = FALSE; + + list = g_list_next(list); + ret = g_idle_remove_by_data(event_data); + + LOGD("remove idle event [%p], ret[%d]", event_data, ret); + + if (ret == FALSE) { + event_data->cb_info = NULL; + LOGW("idle callback for event %p will be called later", event_data); + } + + ev->idle_ev_list = g_list_remove(ev->idle_ev_list, (gpointer)event_data); + + g_mutex_unlock(&event_data->event_mutex); + + if (ret == TRUE) { + g_mutex_clear(&event_data->event_mutex); + + g_free(event_data); + event_data = NULL; + + LOGD("remove idle event done"); + } + } else { + LOGW("event(%d) lock failed. it's being called...", event_data->int_data); + } + } + } + + g_list_free(ev->idle_ev_list); + ev->idle_ev_list = NULL; + } + + g_mutex_unlock(&ev->idle_ev_mutex); + + return; +} + static void _player_event_queue_destroy(callback_cb_info_s * cb_info) { g_return_if_fail(cb_info); @@ -1087,7 +1204,7 @@ static void _player_event_queue_destroy(callback_cb_info_s * cb_info) g_mutex_clear(&ev->qlock); g_mutex_clear(&ev->mutex); g_cond_clear(&ev->cond); - + g_mutex_clear(&ev->idle_ev_mutex); } static void _player_event_queue_remove(player_event_queue * ev_queue, int ev) @@ -1138,6 +1255,7 @@ static void _user_callback_handler(callback_cb_info_s * cb_info, muse_player_eve data->int_data = (int)event; data->cb_info = cb_info; data->buf = buffer; + g_mutex_init(&data->event_mutex); _player_event_queue_add(&cb_info->event_queue, data); } } @@ -1537,6 +1655,7 @@ int player_destroy(player_h player) if (CALLBACK_INFO(pc)) { __player_remove_tsurf_list(pc); + _player_remove_idle_event_all(CALLBACK_INFO(pc)); _player_event_queue_destroy(CALLBACK_INFO(pc)); tbm_bufmgr_deinit(TBM_BUFMGR(pc)); @@ -1644,11 +1763,10 @@ void _player_replace_old_path(const char *in_path, char *out_path) LOGD("input file_path : %s", in_path); - if (strncmp(in_path, old_path, strlen(old_path)) == 0) { + if (strncmp(in_path, old_path, strlen(old_path)) == 0) snprintf(out_path, MAX_URL_LEN, "%s%s", tzplatform_getenv(TZ_USER_CONTENT), in_path+strlen(old_path)); - } else { + else snprintf(out_path, MAX_URL_LEN, "%s", in_path); - } LOGD("replaced path : %s", out_path); return; @@ -2260,11 +2378,10 @@ int player_set_display_mode(player_h player, player_display_mode_e mode) #ifdef TIZEN_FEATURE_EVAS_RENDERER if (EVAS_HANDLE(pc)) { ret = mm_evas_renderer_set_geometry(EVAS_HANDLE(pc), mode); - if (ret != MM_ERROR_NONE) { + if (ret != MM_ERROR_NONE) return PLAYER_ERROR_INVALID_OPERATION; - } else { + else return PLAYER_ERROR_NONE; - } } #endif player_msg_send1(api, pc, ret_buf, ret, INT, mode); @@ -2287,11 +2404,10 @@ int player_get_display_mode(player_h player, player_display_mode_e * pmode) if (EVAS_HANDLE(pc)) { ret = mm_evas_renderer_get_geometry(EVAS_HANDLE(pc), &mode); *pmode = (player_display_mode_e) mode; - if (ret != MM_ERROR_NONE) { + if (ret != MM_ERROR_NONE) return PLAYER_ERROR_INVALID_OPERATION; - } else { + else return PLAYER_ERROR_NONE; - } } #endif player_msg_send(api, pc, ret_buf, ret); @@ -2322,13 +2438,12 @@ int player_set_display_roi_area(player_h player, int x, int y, int width, int he #ifdef TIZEN_FEATURE_EVAS_RENDERER if (EVAS_HANDLE(pc)) { ret = mm_evas_renderer_set_roi_area(EVAS_HANDLE(pc), x, y, width, height); - if (ret == MM_ERROR_INVALID_ARGUMENT) { + if (ret == MM_ERROR_INVALID_ARGUMENT) return PLAYER_ERROR_INVALID_PARAMETER; - } else if (ret != MM_ERROR_NONE) { + else if (ret != MM_ERROR_NONE) return PLAYER_ERROR_INVALID_OPERATION; - } else { + else return PLAYER_ERROR_NONE; - } } #endif wl_win.wl_window_x = x; @@ -2369,11 +2484,10 @@ int player_set_display_rotation(player_h player, player_display_rotation_e rotat #ifdef TIZEN_FEATURE_EVAS_RENDERER if (EVAS_HANDLE(pc)) { ret = mm_evas_renderer_set_rotation(EVAS_HANDLE(pc), rotation); - if (ret != MM_ERROR_NONE) { + if (ret != MM_ERROR_NONE) return PLAYER_ERROR_INVALID_OPERATION; - } else { + else return PLAYER_ERROR_NONE; - } } #endif player_msg_send1(api, pc, ret_buf, ret, INT, rotation); @@ -2396,11 +2510,10 @@ int player_get_display_rotation(player_h player, player_display_rotation_e * pro if (EVAS_HANDLE(pc)) { ret = mm_evas_renderer_get_rotation(EVAS_HANDLE(pc), &rotation); *protation = (player_display_rotation_e) rotation; - if (ret != MM_ERROR_NONE) { + if (ret != MM_ERROR_NONE) return PLAYER_ERROR_INVALID_OPERATION; - } else { + else return PLAYER_ERROR_NONE; - } } #endif player_msg_send(api, pc, ret_buf, ret); @@ -2425,11 +2538,10 @@ int player_set_display_visible(player_h player, bool visible) #ifdef TIZEN_FEATURE_EVAS_RENDERER if (EVAS_HANDLE(pc)) { ret = mm_evas_renderer_set_visible(EVAS_HANDLE(pc), visible); - if (ret != MM_ERROR_NONE) { + if (ret != MM_ERROR_NONE) return PLAYER_ERROR_INVALID_OPERATION; - } else { + else return PLAYER_ERROR_NONE; - } } #endif @@ -2459,11 +2571,10 @@ int player_is_display_visible(player_h player, bool * pvisible) else *pvisible = FALSE; - if (ret != MM_ERROR_NONE) { + if (ret != MM_ERROR_NONE) return PLAYER_ERROR_INVALID_OPERATION; - } else { + else return PLAYER_ERROR_NONE; - } } #endif player_msg_send(api, pc, ret_buf, ret);