4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
7 * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <unicode/ucsdet.h>
34 #include <tzplatform_config.h>
35 #include "mm_player_utils.h"
36 #include "media_format.h"
38 #define MEDIA_PATH_EXTERNAL tzplatform_getenv(TZ_SYS_STORAGE) /* external storage, sd card, usb */
39 #define FD_NUM_FOR_DEBUG 10
40 #define CMD_LOCK_TICKET_MAX (G_MAXUINT - 1)
43 _mmplayer_get_stream_type_name(int type)
46 case MM_PLAYER_STREAM_TYPE_AUDIO:
48 case MM_PLAYER_STREAM_TYPE_VIDEO:
50 case MM_PLAYER_STREAM_TYPE_TEXT:
52 case MM_PLAYER_STREAM_TYPE_DEFAULT: /* fall through */
53 case MM_PLAYER_STREAM_TYPE_MAX: /* fall through */
60 _mmplayer_get_state_name(int state)
63 case MM_PLAYER_STATE_NULL:
65 case MM_PLAYER_STATE_READY:
67 case MM_PLAYER_STATE_PAUSED:
69 case MM_PLAYER_STATE_PLAYING:
71 case MM_PLAYER_STATE_NONE:
79 _mmplayer_is_rtsp_streaming(mmplayer_t *player)
81 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
83 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP) ? TRUE : FALSE;
87 _mmplayer_is_http_streaming(mmplayer_t *player)
89 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
91 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP) ? TRUE : FALSE;
95 _mmplayer_is_streaming(mmplayer_t *player)
97 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
99 return (_mmplayer_is_rtsp_streaming(player) || _mmplayer_is_http_streaming(player)
100 || _mmplayer_is_http_live_streaming(player) || _mmplayer_is_dash_streaming(player)
101 || _mmplayer_is_smooth_streaming(player)) ? TRUE : FALSE;
105 _mmplayer_is_live_streaming(mmplayer_t *player)
107 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
109 return (_mmplayer_is_rtsp_streaming(player) && player->streaming_type == STREAMING_SERVICE_LIVE) ? TRUE : FALSE;
113 _mmplayer_is_http_live_streaming(mmplayer_t *player)
115 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
117 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS) ? TRUE : FALSE;
121 _mmplayer_is_dash_streaming(mmplayer_t *player)
123 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
125 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH) ? TRUE : FALSE;
129 _mmplayer_is_smooth_streaming(mmplayer_t *player)
131 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
133 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS) ? TRUE : FALSE;
137 _mmplayer_is_adaptive_streaming(mmplayer_t *player)
139 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
140 return (_mmplayer_is_http_live_streaming(player) || _mmplayer_is_dash_streaming(player)
141 || _mmplayer_is_smooth_streaming(player)) ? TRUE : FALSE;
145 _mmplayer_is_ms_buff_src(mmplayer_t *player)
147 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
149 return (player->profile.uri_type == MM_PLAYER_URI_TYPE_MS_BUFF) ? TRUE : FALSE;
153 _mmplayer_has_suffix(mmplayer_t *player, const gchar *suffix)
155 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
156 MMPLAYER_RETURN_VAL_IF_FAIL(suffix, FALSE);
158 gboolean ret = FALSE;
159 gchar *t_url = g_ascii_strdown(player->profile.uri, -1);
160 gchar *t_suffix = g_ascii_strdown(suffix, -1);
161 gchar *opt = strchr(t_url, '?');
166 ret = g_str_has_suffix(t_url, t_suffix);
168 MMPLAYER_FREEIF(t_url);
169 MMPLAYER_FREEIF(t_suffix);
175 _mmplayer_is_videosink_ready(mmplayer_t *player, int surface_type)
177 int curr_type = MM_DISPLAY_SURFACE_NUM;
181 !player->pipeline->mainbin ||
182 !player->pipeline->videobin ||
183 !player->pipeline->videobin[MMPLAYER_V_BIN].gst ||
184 !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
185 LOGW("videosink is not ready yet");
189 if (surface_type == MM_DISPLAY_SURFACE_NUM) /* don't care the surface type */
192 mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &curr_type);
194 if (curr_type != surface_type) {
195 LOGW("surface type is mismatched %d, %d", curr_type, surface_type);
203 _mmplayer_post_message(mmplayer_t *player, enum MMMessageType msgtype, MMMessageParamType *param)
205 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
210 LOGD("Message (type : %d) will be posted using msg-cb(%p).", msgtype, player->msg_cb);
213 player->msg_cb(msgtype, param, player->msg_cb_param);
219 _mmplayer_dump_pipeline_state(mmplayer_t *player)
221 GstIterator *iter = NULL;
222 gboolean done = FALSE;
225 GstElement *element = NULL;
226 GstElementFactory *factory = NULL;
228 GstState state = GST_STATE_VOID_PENDING;
229 GstState pending = GST_STATE_VOID_PENDING;
230 GstClockTime time = 200 * GST_MSECOND;
234 MMPLAYER_RETURN_VAL_IF_FAIL(player &&
236 player->pipeline->mainbin,
239 MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-error-dump");
241 iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
245 switch (gst_iterator_next(iter, &item)) {
246 case GST_ITERATOR_OK:
247 element = g_value_get_object(&item);
249 gst_element_get_state(element, &state, &pending, time);
251 factory = gst_element_get_factory(element) ;
253 LOGE("%s:%s : From:%s To:%s refcount : %d", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(element) ,
254 gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(element));
256 g_value_reset(&item);
258 case GST_ITERATOR_RESYNC:
259 gst_iterator_resync(iter);
261 case GST_ITERATOR_ERROR:
264 case GST_ITERATOR_DONE:
271 element = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
273 gst_element_get_state(element, &state, &pending, time);
275 factory = gst_element_get_factory(element) ;
278 LOGE("%s:%s : From:%s To:%s refcount : %d",
279 GST_OBJECT_NAME(factory),
280 GST_ELEMENT_NAME(element),
281 gst_element_state_get_name(state),
282 gst_element_state_get_name(pending),
283 GST_OBJECT_REFCOUNT_VALUE(element));
286 g_value_unset(&item);
289 gst_iterator_free(iter);
297 _mmplayer_exist_file_path(const char *file_path)
300 struct stat stat_results = {0, };
302 if (!file_path || !strlen(file_path))
303 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
305 fd = open(file_path, O_RDONLY);
309 strerror_r(errno, str_error, sizeof(str_error));
310 LOGE("failed to open file by %s (%d)", str_error, errno);
313 return MM_ERROR_PLAYER_PERMISSION_DENIED;
315 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
318 if (fstat(fd, &stat_results) < 0) {
319 LOGE("failed to get file status");
320 } else if (stat_results.st_size == 0) {
321 LOGE("file size is zero");
322 if (fd < FD_NUM_FOR_DEBUG)
323 LOGW("close fd %d", fd);
325 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
327 LOGW("file size : %lld bytes", (long long)stat_results.st_size);
330 if (fd < FD_NUM_FOR_DEBUG)
331 LOGW("close fd %d", fd);
334 return MM_ERROR_NONE;
338 _mmplayer_get_cookie_list(const char *cookies)
340 char **cookie_list = NULL;
344 if (!cookies || !strlen(cookies))
347 SECURE_LOGD("cookies : %zu[bytes] - %s", strlen(cookies), cookies);
349 temp = g_strdup(cookies);
351 /* trimming. it works inplace */
355 cookie_list = g_strsplit(temp, ";", 100);
358 LOGE("failed to get cookie list");
362 for (i = 0; i < g_strv_length(cookie_list); i++) {
363 if (cookie_list[i]) {
364 if (strlen(cookie_list[i])) {
365 g_strstrip(cookie_list[i]);
366 SECURE_LOGD("cookie_list[%d] : %zu[bytes] - %s", i, strlen(cookie_list[i]), cookie_list[i]);
368 cookie_list[i][0] = '\0';
374 MMPLAYER_FREEIF(temp);
379 /* check the given path is indicating sdp file */
381 _mmplayer_is_sdp_file(const char *path)
383 gboolean ret = FALSE;
388 MMPLAYER_RETURN_VAL_IF_FAIL(path, FALSE);
390 uri = g_ascii_strdown(path, -1);
398 /* strlen(".sdp") == 4 */
399 if (strlen(uri) <= 4) {
400 LOGW("path is too short.");
401 MMPLAYER_FREEIF(uri);
405 /* first, check extension name */
406 ret = g_str_has_suffix(uri, "sdp");
408 /* second, if no suffix is there, check it's contents */
410 /* FIXIT : do it soon */
413 MMPLAYER_FREEIF(uri);
419 _mmplayer_get_charset(const char *file_path)
421 UCharsetDetector *ucsd;
422 const UCharsetMatch *ucm;
423 UErrorCode status = U_ZERO_ERROR;
425 const char *charset = NULL;
430 fin = fopen(file_path, "r");
432 SECURE_LOGE("fail to open file %s", file_path);
436 ucsd = ucsdet_open(&status);
437 if (U_FAILURE(status)) {
438 LOGE("fail to ucsdet_open");
442 ucsdet_enableInputFilter(ucsd, TRUE);
444 buf = g_try_malloc(1024 * 1024);
446 LOGE("fail to alloc");
450 n_size = fread(buf, 1, 1024*1024, fin);
451 buf[1024 * 1024 - 1] = '\0';
455 ucsdet_setText(ucsd, buf, strlen(buf), &status);
456 if (U_FAILURE(status)) {
457 LOGE("fail to ucsdet_setText");
461 ucm = ucsdet_detect(ucsd, &status);
462 if (U_FAILURE(status)) {
463 LOGE("fail to ucsdet_detect");
467 charset = ucsdet_getName(ucm, &status);
468 if (U_FAILURE(status)) {
469 LOGE("fail to ucsdet_getName");
473 /* CP949 encoding is an extension of the EUC-KR and it is backwards compatible.*/
474 if (charset && !strcmp(charset, "EUC-KR"))
484 MMPLAYER_FREEIF(buf);
490 _mmplayer_get_pixtype(unsigned int fourcc)
492 int pixtype = MM_PIXEL_FORMAT_INVALID;
495 char *pfourcc = (char *)&fourcc;
497 LOGD("fourcc(%c%c%c%c)",
498 pfourcc[0], pfourcc[1], pfourcc[2], pfourcc[3]);
502 case GST_MAKE_FOURCC('S', 'N', '1', '2'):
503 case GST_MAKE_FOURCC('N', 'V', '1', '2'):
504 pixtype = MM_PIXEL_FORMAT_NV12;
506 case GST_MAKE_FOURCC('S', 'T', '1', '2'):
507 pixtype = MM_PIXEL_FORMAT_NV12T;
509 case GST_MAKE_FOURCC('S', 'N', '2', '1'):
510 case GST_MAKE_FOURCC('N', 'V', '2', '1'):
511 pixtype = MM_PIXEL_FORMAT_NV21;
513 case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
514 case GST_MAKE_FOURCC('Y', 'U', 'Y', 'V'):
515 case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'):
516 pixtype = MM_PIXEL_FORMAT_YUYV;
518 case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
519 case GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'):
520 pixtype = MM_PIXEL_FORMAT_UYVY;
522 case GST_MAKE_FOURCC('S', '4', '2', '0'):
523 case GST_MAKE_FOURCC('I', '4', '2', '0'):
524 pixtype = MM_PIXEL_FORMAT_I420;
526 case GST_MAKE_FOURCC('Y', 'V', '1', '2'):
527 pixtype = MM_PIXEL_FORMAT_YV12;
529 case GST_MAKE_FOURCC('4', '2', '2', 'P'):
530 pixtype = MM_PIXEL_FORMAT_422P;
532 case GST_MAKE_FOURCC('R', 'G', 'B', 'P'):
533 pixtype = MM_PIXEL_FORMAT_RGB565;
535 case GST_MAKE_FOURCC('R', 'G', 'B', '3'):
536 pixtype = MM_PIXEL_FORMAT_RGB888;
538 case GST_MAKE_FOURCC('A', 'R', 'G', 'B'):
539 case GST_MAKE_FOURCC('x', 'R', 'G', 'B'):
540 pixtype = MM_PIXEL_FORMAT_ARGB;
542 case GST_MAKE_FOURCC('B', 'G', 'R', 'A'):
543 case GST_MAKE_FOURCC('B', 'G', 'R', 'x'):
544 case GST_MAKE_FOURCC('S', 'R', '3', '2'):
545 pixtype = MM_PIXEL_FORMAT_RGBA;
547 case GST_MAKE_FOURCC('J', 'P', 'E', 'G'):
548 case GST_MAKE_FOURCC('P', 'N', 'G', ' '):
549 pixtype = MM_PIXEL_FORMAT_ENCODED;
551 case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
552 pixtype = MM_PIXEL_FORMAT_ITLV_JPEG_UYVY;
555 LOGE("Not supported fourcc type(%c%c%c%c)",
556 fourcc, fourcc>>8, fourcc>>16, fourcc>>24);
557 pixtype = MM_PIXEL_FORMAT_INVALID;
565 __mmplayer_storage_supported_cb(int storage_id, storage_type_e type,
566 storage_state_e state, const char *path, void *user_data)
568 mmplayer_storage_info_t *storage_info = (mmplayer_storage_info_t *)user_data;
570 MMPLAYER_RETURN_VAL_IF_FAIL(storage_info, FALSE);
572 if (type == storage_info->type && strstr(storage_info->path, path)) {
573 storage_info->id = storage_id;
574 storage_info->state = state;
582 _mmplayer_get_storage_info(const char *path, mmplayer_storage_info_t *storage_info)
585 const char *file_path = path;
587 MMPLAYER_RETURN_VAL_IF_FAIL(file_path && storage_info, false);
589 if (strncmp(file_path, "file://", strlen("file://")) == 0)
590 file_path = path + 7; /* remove file prefix */
592 if (strncmp(file_path, MEDIA_PATH_EXTERNAL, strlen(MEDIA_PATH_EXTERNAL)) == 0) {
593 storage_info->type = STORAGE_TYPE_EXTERNAL;
595 memset(storage_info->path, 0x00, MM_MAX_URL_LEN);
596 g_snprintf(storage_info->path, MM_MAX_URL_LEN, "%s", file_path);
598 ret = storage_foreach_device_supported((storage_device_supported_cb)__mmplayer_storage_supported_cb, storage_info);
599 if (ret != STORAGE_ERROR_NONE) {
600 LOGE("failed to check supported storage 0x%x", ret);
604 if (storage_info->state <= STORAGE_STATE_REMOVED) {
605 LOGE("need to check the external storage state %d:%d", storage_info->id, storage_info->state);
609 storage_info->type = STORAGE_TYPE_INTERNAL;
610 storage_info->state = STORAGE_STATE_MOUNTED;
613 LOGD("storage info %d:%d:%d", storage_info->type, storage_info->id, storage_info->state);
617 media_format_mimetype_e _mmplayer_convert_audio_pcm_str_to_media_format_mime(const gchar *audio_pcm_str)
619 if (!audio_pcm_str) {
620 LOGW("audio pcm str is NULL");
621 return MEDIA_FORMAT_MAX;
624 if (strstr(audio_pcm_str, "S16LE"))
625 return MEDIA_FORMAT_PCM_S16LE;
626 else if (strstr(audio_pcm_str, "S24LE"))
627 return MEDIA_FORMAT_PCM_S24LE;
628 else if (strstr(audio_pcm_str, "S32LE"))
629 return MEDIA_FORMAT_PCM_S32LE;
630 else if (strstr(audio_pcm_str, "S16BE"))
631 return MEDIA_FORMAT_PCM_S16BE;
632 else if (strstr(audio_pcm_str, "S24BE"))
633 return MEDIA_FORMAT_PCM_S24BE;
634 else if (strstr(audio_pcm_str, "S32BE"))
635 return MEDIA_FORMAT_PCM_S32BE;
636 else if (strstr(audio_pcm_str, "F32LE"))
637 return MEDIA_FORMAT_PCM_F32LE;
638 else if (strstr(audio_pcm_str, "F32BE"))
639 return MEDIA_FORMAT_PCM_F32BE;
640 else if (strstr(audio_pcm_str, "U16LE"))
641 return MEDIA_FORMAT_PCM_U16LE;
642 else if (strstr(audio_pcm_str, "U24LE"))
643 return MEDIA_FORMAT_PCM_U24LE;
644 else if (strstr(audio_pcm_str, "U32LE"))
645 return MEDIA_FORMAT_PCM_U32LE;
646 else if (strstr(audio_pcm_str, "U16BE"))
647 return MEDIA_FORMAT_PCM_U16BE;
648 else if (strstr(audio_pcm_str, "U24BE"))
649 return MEDIA_FORMAT_PCM_U24BE;
650 else if (strstr(audio_pcm_str, "U32BE"))
651 return MEDIA_FORMAT_PCM_U32BE;
653 LOGW("Not supported audio pcm format str : %s", audio_pcm_str);
654 return MEDIA_FORMAT_MAX;
658 gboolean _mmplayer_use_decodebin(mmplayer_t *player) /* MMPLAYER_USE_DECODEBIN(player) */
660 int audio_offload = 0;
661 MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
663 mm_attrs_get_int_by_name(player->attrs, MM_PLAYER_AUDIO_OFFLOAD, &audio_offload); /* user requirement */
665 if (MMPLAYER_IS_MS_BUFF_SRC(player) || player->ini.use_decodebin || audio_offload)
671 void _mmplayer_cmd_lock_init(mmplayer_t *player)
673 MMPLAYER_RETURN_IF_FAIL(player);
674 player->cmd_lock = g_new0(mmplayer_ticket_lock_t, 1);
675 g_mutex_init(&player->cmd_lock->ticket_mutex);
676 g_cond_init(&player->cmd_lock->ticket_cond);
677 player->cmd_lock->ticket_queue_head = 0;
678 player->cmd_lock->ticket_queue_tail = 0;
681 void _mmplayer_cmd_lock_deinit(mmplayer_t *player)
683 MMPLAYER_RETURN_IF_FAIL(player && player->cmd_lock);
684 g_mutex_clear(&player->cmd_lock->ticket_mutex);
685 g_cond_clear(&player->cmd_lock->ticket_cond);
686 player->cmd_lock->ticket_queue_head = 0;
687 player->cmd_lock->ticket_queue_tail = 0;
688 g_free(player->cmd_lock);
691 void _mmplayer_cmd_lock(mmplayer_t *player)
697 MMPLAYER_RETURN_IF_FAIL(player && player->cmd_lock);
699 cond = &player->cmd_lock->ticket_cond;
700 mutex = &player->cmd_lock->ticket_mutex;
702 queue_me = player->cmd_lock->ticket_queue_tail;
703 player->cmd_lock->ticket_queue_tail = (queue_me + 1) % CMD_LOCK_TICKET_MAX;
704 while (queue_me != player->cmd_lock->ticket_queue_head)
705 g_cond_wait(cond, mutex);
706 g_mutex_unlock(mutex);
709 gboolean _mmplayer_cmd_trylock(mmplayer_t *player)
713 MMPLAYER_RETURN_VAL_IF_FAIL(player && player->cmd_lock, FALSE);
715 mutex = &player->cmd_lock->ticket_mutex;
717 if (!g_mutex_trylock(mutex))
720 if (player->cmd_lock->ticket_queue_tail != player->cmd_lock->ticket_queue_head) {
721 g_mutex_unlock(mutex);
724 g_mutex_unlock(mutex);
726 _mmplayer_cmd_lock(player);
730 void _mmplayer_cmd_unlock(mmplayer_t *player)
735 MMPLAYER_RETURN_IF_FAIL(player && player->cmd_lock);
737 cond = &player->cmd_lock->ticket_cond;
738 mutex = &player->cmd_lock->ticket_mutex;
741 player->cmd_lock->ticket_queue_head =
742 (player->cmd_lock->ticket_queue_head + 1) % CMD_LOCK_TICKET_MAX;
743 g_cond_broadcast(cond);
744 g_mutex_unlock(mutex);