* @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
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
/**
* @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
/**
* @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
/**
* @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
/**
* @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
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.
int int_data;
char *buf;
callback_cb_info_s *cb_info;
+ GMutex event_mutex;
} _player_cb_data;
typedef struct {
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;
}
}
__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)
}
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) {
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);
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);
}
+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);
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)
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);
}
}
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));
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;
#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);
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);
#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;
#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);
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);
#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
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);