summaryrefslogtreecommitdiff
path: root/src/include/mm_player_utils.h
blob: 61e82a34a26784346c04d700b415666dba6a366d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/*
 * libmm-player
 *
 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
 *
 * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
 * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
 *
 * 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 __MM_PLAYER_UTILS_H__
#define __MM_PLAYER_UTILS_H__
#include <limits.h>
#include <glib.h>
#include <gst/gst.h>
#include <dlog.h>
#include <mm_player_ini.h>
#include <mm_types.h>
#include <mm_error.h>
#include <mm_message.h>
#include "mm_player_priv.h"

#ifdef __cplusplus
	extern "C" {
#endif

#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "MM_PLAYER"

/* general */
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#endif

#define MMPLAYER_MIN_INT (INT_MIN)
#define MMPLAYER_MAX_INT (INT_MAX)

#define MMPLAYER_FREEIF(x) \
	do {	\
		if (x) { \
			g_free(x); \
			x = NULL;	\
		} \
	} while (0)

#define MMPLAYER_GET_ATTRS(x_player) ((mm_player_t *)x_player)->attrs

/* command */
#define MMPLAYER_CMD_LOCK(x_player)                          g_mutex_lock(&((mm_player_t *)x_player)->cmd_lock)
#define MMPLAYER_CMD_TRYLOCK(x_player)                       g_mutex_trylock(&((mm_player_t *)x_player)->cmd_lock)
#define MMPLAYER_CMD_UNLOCK(x_player)                        g_mutex_unlock(&((mm_player_t *)x_player)->cmd_lock)

/* playback */
#define MMPLAYER_PLAYBACK_LOCK(x_player)                     g_mutex_lock(&((mm_player_t *)x_player)->playback_lock)
#define MMPLAYER_PLAYBACK_UNLOCK(x_player)                   g_mutex_unlock(&((mm_player_t *)x_player)->playback_lock)

/* capture thread */
#define MMPLAYER_CAPTURE_THREAD_LOCK(x_player)               g_mutex_lock(&((mm_player_t *)x_player)->capture_thread_mutex)
#define MMPLAYER_CAPTURE_THREAD_UNLOCK(x_player)             g_mutex_unlock(&((mm_player_t *)x_player)->capture_thread_mutex)
#define MMPLAYER_CAPTURE_THREAD_WAIT(x_player)               g_cond_wait(&((mm_player_t *)x_player)->capture_thread_cond, &((mm_player_t *)x_player)->capture_thread_mutex)
#define MMPLAYER_CAPTURE_THREAD_SIGNAL(x_player)             g_cond_signal(&((mm_player_t *)x_player)->capture_thread_cond);

/* gapless play thread */
#define MMPLAYER_GAPLESS_PLAY_THREAD_LOCK(x_player)             g_mutex_lock(&((mm_player_t *)x_player)->gapless_play_thread_mutex)
#define MMPLAYER_GAPLESS_PLAY_THREAD_UNLOCK(x_player)           g_mutex_unlock(&((mm_player_t *)x_player)->gapless_play_thread_mutex)
#define MMPLAYER_GAPLESS_PLAY_THREAD_WAIT(x_player)             g_cond_wait(&((mm_player_t *)x_player)->gapless_play_thread_cond, &((mm_player_t *)x_player)->gapless_play_thread_mutex)
#define MMPLAYER_GAPLESS_PLAY_THREAD_SIGNAL(x_player)           g_cond_signal(&((mm_player_t *)x_player)->gapless_play_thread_cond);

/* gst bus msg thread */
#define MMPLAYER_BUS_MSG_THREAD_LOCK(x_player)                   g_mutex_lock(&((mm_player_t *)x_player)->bus_msg_thread_mutex)
#define MMPLAYER_BUS_MSG_THREAD_UNLOCK(x_player)                 g_mutex_unlock(&((mm_player_t *)x_player)->bus_msg_thread_mutex)
#define MMPLAYER_BUS_MSG_THREAD_WAIT(x_player)                   g_cond_wait(&((mm_player_t *)x_player)->bus_msg_thread_cond, &((mm_player_t *)x_player)->bus_msg_thread_mutex)
#define MMPLAYER_BUS_MSG_THREAD_WAIT_UNTIL(x_player, end_time)   g_cond_wait_until(&((mm_player_t *)x_player)->bus_msg_thread_cond, &((mm_player_t *)x_player)->bus_msg_thread_mutex, end_time)
#define MMPLAYER_BUS_MSG_THREAD_SIGNAL(x_player)                 g_cond_signal(&((mm_player_t *)x_player)->bus_msg_thread_cond);

/* handling fakesink */
#define MMPLAYER_FSINK_LOCK(x_player)                        g_mutex_lock(&((mm_player_t *)x_player)->fsink_lock)
#define MMPLAYER_FSINK_UNLOCK(x_player)                      g_mutex_unlock(&((mm_player_t *)x_player)->fsink_lock)

/* handling update tag */
#define MMPLAYER_UPDATE_TAG_LOCK(x_player)                   g_mutex_lock(&((mm_player_t *)x_player)->update_tag_lock)
#define MMPLAYER_UPDATE_TAG_UNLOCK(x_player)                 g_mutex_unlock(&((mm_player_t *)x_player)->update_tag_lock)

/* video stream bo */
#define MMPLAYER_VIDEO_BO_LOCK(x_player)                     g_mutex_lock(&((mm_player_t *)x_player)->video_bo_mutex)
#define MMPLAYER_VIDEO_BO_UNLOCK(x_player)                   g_mutex_unlock(&((mm_player_t *)x_player)->video_bo_mutex)
#define MMPLAYER_VIDEO_BO_WAIT(x_player)                     g_cond_wait(&((mm_player_t *)x_player)->video_bo_cond, &((mm_player_t *)x_player)->video_bo_mutex)
#define MMPLAYER_VIDEO_BO_WAIT_UNTIL(x_player, end_time)     g_cond_wait_until(&((mm_player_t *)x_player)->video_bo_cond, &((mm_player_t *)x_player)->video_bo_mutex, end_time)
#define MMPLAYER_VIDEO_BO_SIGNAL(x_player)                   g_cond_signal(&((mm_player_t *)x_player)->video_bo_cond);

/* media stream lock */
#define MMPLAYER_MEDIA_STREAM_CALLBACK_LOCK(x_player)        g_mutex_lock(&((mm_player_t *)x_player)->media_stream_cb_lock)
#define MMPLAYER_MEDIA_STREAM_CALLBACK_UNLOCK(x_player)      g_mutex_unlock(&((mm_player_t *)x_player)->media_stream_cb_lock)

/* subtitle info */
#define MMPLAYER_SUBTITLE_INFO_LOCK(x_player)                     g_mutex_lock(&((mm_player_t *)x_player)->subtitle_info_mutex)
#define MMPLAYER_SUBTITLE_INFO_UNLOCK(x_player)                   g_mutex_unlock(&((mm_player_t *)x_player)->subtitle_info_mutex)
#define MMPLAYER_SUBTITLE_INFO_WAIT(x_player)                     g_cond_wait(&((mm_player_t *)x_player)->subtitle_info_cond, &((mm_player_t *)x_player)->subtitle_info_mutex)
#define MMPLAYER_SUBTITLE_INFO_WAIT_UNTIL(x_player, end_time)     g_cond_wait_until(&((mm_player_t *)x_player)->subtitle_info_cond, &((mm_player_t *)x_player)->subtitle_info_mutex, end_time)
#define MMPLAYER_SUBTITLE_INFO_SIGNAL(x_player)                   g_cond_signal(&((mm_player_t *)x_player)->subtitle_info_cond);

#if 0
#define MMPLAYER_FENTER();					LOGD("<ENTER>");
#define MMPLAYER_FLEAVE();					LOGD("<LEAVE>");
#else
#define MMPLAYER_FENTER();
#define MMPLAYER_FLEAVE();
#endif

#define MMPLAYER_RETURN_IF_FAIL(expr) \
	do { \
		if (!(expr)) { \
			LOGW("failed [%s]", #expr); \
			return; \
		} \
	} while (0)

#define MMPLAYER_RETURN_VAL_IF_FAIL(expr, var) \
	do { \
		if (!(expr)) { \
			LOGW("failed [%s]", #expr); \
			return (var); \
		} \
	} while (0)

/* debug caps string */
#define MMPLAYER_LOG_GST_CAPS_TYPE(x_caps) \
	do { \
		gchar *caps_type = NULL; \
		if (x_caps) { \
			caps_type = gst_caps_to_string(x_caps); \
			LOGD("caps: %s", caps_type); \
			MMPLAYER_FREEIF(caps_type); \
		} else {\
			LOGW("caps is null"); \
		} \
	} while (0)

/* message posting */
#define MMPLAYER_POST_MSG(x_player, x_msgtype, x_msg_param) \
	do { \
		LOGD("[handle: %p] posting %s to application", x_player, #x_msgtype); \
		__mmplayer_post_message(x_player, x_msgtype, x_msg_param); \
	} while (0)

/* setting player state */
#define MMPLAYER_SET_STATE(x_player, x_state) \
	do { \
		LOGD("[handle: %p] update state machine to %d", x_player, x_state); \
		__mmplayer_set_state(x_player, x_state); \
	} while (0)

#define MMPLAYER_CHECK_STATE(x_player, x_command) \
	do {	\
		LOGD("[handle: %p] checking player state before doing %s", x_player, #x_command); \
		switch (__mmplayer_check_state(x_player, x_command)) { \
		case MM_ERROR_PLAYER_INVALID_STATE: \
			return MM_ERROR_PLAYER_INVALID_STATE; \
			break; \
			/* NOTE : for robustness of player. we won't treat it as an error */ \
		case MM_ERROR_PLAYER_NO_OP: \
			return MM_ERROR_NONE; \
			break; \
		case MM_ERROR_PLAYER_DOING_SEEK: \
			return MM_ERROR_PLAYER_DOING_SEEK; \
		default: \
			break; \
		}	\
	} while (0)

/* setting element state */
#define MMPLAYER_ELEMENT_SET_STATE(x_element, x_state) \
	do {	\
		LOGD("setting state [%s:%d] to [%s]", #x_state, x_state, GST_ELEMENT_NAME(x_element)); \
		if (GST_STATE_CHANGE_FAILURE == gst_element_set_state(x_element, x_state)) { \
			LOGE("failed to set state %s to %s", #x_state, GST_ELEMENT_NAME(x_element)); \
			goto STATE_CHANGE_FAILED; \
		}	\
	} while (0)

#define MMPLAYER_CHECK_NULL(x_var) \
	do { \
		if (!x_var) { \
			LOGE("[%s] is NULL", #x_var); \
			goto ERROR; \
		} \
	} while (0)

/* generating dot */
#define MMPLAYER_GENERATE_DOT_IF_ENABLED(x_player, x_name) \
	do { \
		if (x_player->ini.generate_dot) { \
			GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), \
			GST_DEBUG_GRAPH_SHOW_ALL, x_name); \
		} \
	} while (0)

/* signal manipulation */
#define MMPLAYER_SIGNAL_CONNECT(x_player, x_object, x_type, x_signal, x_callback, x_arg) \
	do { \
		MMPlayerSignalItem *item = NULL; \
		item = (MMPlayerSignalItem *)g_malloc(sizeof(MMPlayerSignalItem)); \
		if (!item) { \
			LOGE("cannot connect signal [%s]", x_signal); \
		} else { \
			item->obj = G_OBJECT(x_object); \
			item->sig = g_signal_connect(G_OBJECT(x_object), x_signal, \
						x_callback, x_arg); \
			if ((x_type >= MM_PLAYER_SIGNAL_TYPE_AUTOPLUG) && (x_type < MM_PLAYER_SIGNAL_TYPE_MAX)) \
				x_player->signals[x_type] = g_list_append(x_player->signals[x_type], item); \
			else \
				LOGE("wrong signal type [%d]", x_type); \
		} \
	} while (0)

/* release element resource */
#define MMPLAYER_RELEASE_ELEMENT(x_player, x_bin, x_id) \
	do { \
		if (x_bin[x_id].gst) { \
			gst_element_set_state(x_bin[x_id].gst, GST_STATE_NULL); \
			gst_bin_remove(GST_BIN(x_player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), x_bin[x_id].gst); \
			x_bin[x_id].gst = NULL; \
			LOGD("release done [element %d]", x_id); \
		} \
	} while (0)

/* state */
#define MMPLAYER_PREV_STATE(x_player) ((mm_player_t *)x_player)->prev_state
#define MMPLAYER_CURRENT_STATE(x_player) ((mm_player_t *)x_player)->state
#define MMPLAYER_PENDING_STATE(x_player) ((mm_player_t *)x_player)->pending_state
#define MMPLAYER_TARGET_STATE(x_player) ((mm_player_t *)x_player)->target_state
#define MMPLAYER_STATE_GET_NAME(state) __get_state_name(state)

#define MMPLAYER_PRINT_STATE(x_player) \
	do { \
		LOGD("-- prev %s, current %s, pending %s, target %s --", \
			MMPLAYER_STATE_GET_NAME(MMPLAYER_PREV_STATE(x_player)), \
			MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(x_player)), \
			MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(x_player)), \
			MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(x_player))); \
	} while (0)

#define MMPLAYER_STATE_CHANGE_TIMEOUT(x_player) ((mm_player_t *)x_player)->state_change_timeout

/* streaming */
#define MMPLAYER_IS_STREAMING(x_player) __is_streaming(x_player)
#define MMPLAYER_IS_RTSP_STREAMING(x_player) __is_rtsp_streaming(x_player)
#define MMPLAYER_IS_HTTP_STREAMING(x_player) __is_http_streaming(x_player)
#define MMPLAYER_IS_HTTP_LIVE_STREAMING(x_player) __is_http_live_streaming(x_player)
#define MMPLAYER_IS_LIVE_STREAMING(x_player) __is_live_streaming(x_player)
#define MMPLAYER_IS_DASH_STREAMING(x_player) __is_dash_streaming(x_player)
#define MMPLAYER_IS_SMOOTH_STREAMING(x_player) __is_smooth_streaming(x_player)
#define MMPLAYER_IS_MS_BUFF_SRC(x_player) __is_ms_buff_src(x_player)

#define MMPLAYER_URL_HAS_DASH_SUFFIX(x_player) __has_suffix(x_player, "mpd")
#define MMPLAYER_URL_HAS_HLS_SUFFIX(x_player) __has_suffix(x_player, "m3u8")

#define MMPLAYER_STREAM_TYPE_GET_NAME(type) __get_stream_type_name(type)

/*===========================================================================================
|																							|
|  GLOBAL FUNCTION PROTOTYPES																|
|																							|
========================================================================================== */

const gchar *__get_state_name(int state);
const gchar *__get_stream_type_name(int type);

gboolean __is_streaming(mm_player_t *player);
gboolean __is_rtsp_streaming(mm_player_t *player);
gboolean __is_live_streaming(mm_player_t *player);
gboolean __is_http_streaming(mm_player_t *player);
gboolean __is_http_live_streaming(mm_player_t *player);
gboolean __is_dash_streaming(mm_player_t *player);
gboolean __is_smooth_streaming(mm_player_t *player);
gboolean __is_ms_buff_src(mm_player_t *player);
gboolean __has_suffix(mm_player_t *player, const gchar *suffix);

gboolean __mmplayer_post_message(mm_player_t *player, enum MMMessageType msgtype, MMMessageParamType *param);
gboolean __mmplayer_dump_pipeline_state(mm_player_t *player);

bool util_is_sdp_file(const char *path);
int util_exist_file_path(const char *file_path);
char **util_get_cookie_list(const char *cookies);
const char *util_get_charset(const char *file_path);
int util_get_pixtype(unsigned int fourcc);
bool util_get_storage_info(const char *path, MMPlayerStorageInfo *storage_info);

#ifdef __cplusplus
	}
#endif

#endif /* __MM_PLAYER_UTILS_H__ */