c412f24bead5ab80db882520f3c04369e5a9973e
[platform/core/multimedia/libmm-player.git] / src / mm_player_utils.c
1 /*
2  * libmm-player
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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>
8  *
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
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
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.
20  *
21  */
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <sys/time.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <unicode/ucsdet.h>
32 #include <dlog.h>
33 #include <storage.h>
34 #include <tzplatform_config.h>
35 #include "mm_player_utils.h"
36 #include "media_format.h"
37
38 #define MEDIA_PATH_EXTERNAL tzplatform_getenv(TZ_SYS_STORAGE) /* external storage, sd card, usb */
39
40 const gchar *
41 _mmplayer_get_stream_type_name(int type)
42 {
43         switch (type) {
44         case MM_PLAYER_STREAM_TYPE_AUDIO:
45                 return "AUDIO";
46         case MM_PLAYER_STREAM_TYPE_VIDEO:
47                 return "VIDEO";
48         case MM_PLAYER_STREAM_TYPE_TEXT:
49                 return "TEXT";
50         case MM_PLAYER_STREAM_TYPE_DEFAULT: /* fall through */
51         case MM_PLAYER_STREAM_TYPE_MAX:     /* fall through */
52         default:
53                 return "INVAID";
54         }
55 }
56
57 const gchar *
58 _mmplayer_get_state_name(int state)
59 {
60         switch (state) {
61         case MM_PLAYER_STATE_NULL:
62                 return "NULL";
63         case MM_PLAYER_STATE_READY:
64                 return "READY";
65         case MM_PLAYER_STATE_PAUSED:
66                 return "PAUSED";
67         case MM_PLAYER_STATE_PLAYING:
68                 return "PLAYING";
69         case MM_PLAYER_STATE_NONE:
70                 return "NONE";
71         default:
72                 return "INVAID";
73         }
74 }
75
76 gboolean
77 _mmplayer_is_rtsp_streaming(mmplayer_t *player)
78 {
79         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
80
81         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP) ? TRUE : FALSE;
82 }
83
84 gboolean
85 _mmplayer_is_http_streaming(mmplayer_t *player)
86 {
87         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
88
89         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP) ? TRUE : FALSE;
90 }
91
92 gboolean
93 _mmplayer_is_streaming(mmplayer_t *player)
94 {
95         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
96
97         return (_mmplayer_is_rtsp_streaming(player) || _mmplayer_is_http_streaming(player)
98                 || _mmplayer_is_http_live_streaming(player) || _mmplayer_is_dash_streaming(player)
99                 || _mmplayer_is_smooth_streaming(player)) ? TRUE : FALSE;
100 }
101
102 gboolean
103 _mmplayer_is_live_streaming(mmplayer_t *player)
104 {
105         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
106
107         return (_mmplayer_is_rtsp_streaming(player) && player->streaming_type == STREAMING_SERVICE_LIVE) ? TRUE : FALSE;
108 }
109
110 gboolean
111 _mmplayer_is_http_live_streaming(mmplayer_t *player)
112 {
113         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
114
115         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS) ? TRUE : FALSE;
116 }
117
118 gboolean
119 _mmplayer_is_dash_streaming(mmplayer_t *player)
120 {
121         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
122
123         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_DASH) ? TRUE : FALSE;
124 }
125
126 gboolean
127 _mmplayer_is_smooth_streaming(mmplayer_t *player)
128 {
129         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
130
131         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_SS) ? TRUE : FALSE;
132 }
133
134 gboolean
135 _mmplayer_is_ms_buff_src(mmplayer_t *player)
136 {
137         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
138
139         return (player->profile.uri_type == MM_PLAYER_URI_TYPE_MS_BUFF) ? TRUE : FALSE;
140 }
141
142 gboolean
143 _mmplayer_has_suffix(mmplayer_t *player, const gchar *suffix)
144 {
145         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
146         MMPLAYER_RETURN_VAL_IF_FAIL(suffix, FALSE);
147
148         gboolean ret = FALSE;
149         gchar *t_url = g_ascii_strdown(player->profile.uri, -1);
150         gchar *t_suffix = g_ascii_strdown(suffix, -1);
151         gchar *opt = strchr(t_url, '?');
152
153         if (opt)
154                 *opt = '\0';
155
156         ret = g_str_has_suffix(t_url, t_suffix);
157
158         MMPLAYER_FREEIF(t_url);
159         MMPLAYER_FREEIF(t_suffix);
160
161         return ret;
162 }
163
164 gboolean
165 _mmplayer_is_videosink_ready(mmplayer_t *player, int surface_type)
166 {
167         int curr_type = MM_DISPLAY_SURFACE_NUM;
168
169         if (!player ||
170                 !player->pipeline ||
171                 !player->pipeline->mainbin ||
172                 !player->pipeline->videobin ||
173                 !player->pipeline->videobin[MMPLAYER_V_BIN].gst ||
174                 !player->pipeline->videobin[MMPLAYER_V_SINK].gst) {
175                 LOGW("videosink is not ready yet");
176                 return FALSE;
177         }
178
179         if (surface_type == MM_DISPLAY_SURFACE_NUM) /* don't care the surface type */
180                 return TRUE;
181
182         mm_attrs_get_int_by_name(player->attrs, "display_surface_type", &curr_type);
183
184         if (curr_type != surface_type) {
185                 LOGW("surface type is mismatched %d, %d", curr_type, surface_type);
186                 return FALSE;
187         }
188
189         return TRUE;
190 }
191
192 gboolean
193 _mmplayer_post_message(mmplayer_t *player, enum MMMessageType msgtype, MMMessageParamType *param)
194 {
195         MMPLAYER_RETURN_VAL_IF_FAIL(player, FALSE);
196
197         if (!player->msg_cb)
198                 return FALSE;
199 #ifdef __DEBUG__
200         LOGD("Message (type : %d)  will be posted using msg-cb(%p).", msgtype, player->msg_cb);
201 #endif
202
203         player->msg_cb(msgtype, param, player->msg_cb_param);
204
205         return TRUE;
206 }
207
208 gboolean
209 _mmplayer_dump_pipeline_state(mmplayer_t *player)
210 {
211         GstIterator *iter = NULL;
212         gboolean done = FALSE;
213
214         GValue item = {0, };
215         GstElement *element = NULL;
216         GstElementFactory *factory = NULL;
217
218         GstState state = GST_STATE_VOID_PENDING;
219         GstState pending = GST_STATE_VOID_PENDING;
220         GstClockTime time = 200 * GST_MSECOND;
221
222         MMPLAYER_FENTER();
223
224         MMPLAYER_RETURN_VAL_IF_FAIL(player &&
225                 player->pipeline &&
226                 player->pipeline->mainbin,
227                 FALSE);
228
229         MMPLAYER_GENERATE_DOT_IF_ENABLED(player, "pipeline-status-error-dump");
230
231         iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst));
232
233         if (iter != NULL) {
234                 while (!done) {
235                         switch (gst_iterator_next(iter, &item)) {
236                         case GST_ITERATOR_OK:
237                                 element = g_value_get_object(&item);
238                                 gst_element_get_state(element, &state, &pending, time);
239
240                                 factory = gst_element_get_factory(element) ;
241                                 if (factory)
242                                         LOGE("%s:%s : From:%s To:%s   refcount : %d", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(element) ,
243                                                 gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(element));
244                                 g_value_reset(&item);
245                                 break;
246                         case GST_ITERATOR_RESYNC:
247                                 gst_iterator_resync(iter);
248                                 break;
249                         case GST_ITERATOR_ERROR:
250                                 done = TRUE;
251                                 break;
252                         case GST_ITERATOR_DONE:
253                                 done = TRUE;
254                                 break;
255                         }
256                 }
257         }
258
259         element = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
260
261         gst_element_get_state(element, &state, &pending, time);
262
263         factory = gst_element_get_factory(element) ;
264
265         if (factory) {
266                 LOGE("%s:%s : From:%s To:%s  refcount : %d",
267                         GST_OBJECT_NAME(factory),
268                         GST_ELEMENT_NAME(element),
269                         gst_element_state_get_name(state),
270                         gst_element_state_get_name(pending),
271                         GST_OBJECT_REFCOUNT_VALUE(element));
272         }
273
274         g_value_unset(&item);
275
276         if (iter)
277                 gst_iterator_free(iter);
278
279         MMPLAYER_FLEAVE();
280
281         return FALSE;
282 }
283
284 int
285 _mmplayer_exist_file_path(const char *file_path)
286 {
287         int fd = 0;
288         struct stat stat_results = {0, };
289
290         if (!file_path || !strlen(file_path))
291                 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
292
293         fd = open(file_path, O_RDONLY);
294
295         if (fd < 0) {
296                 char str_error[256];
297                 strerror_r(errno, str_error, sizeof(str_error));
298                 LOGE("failed to open file by %s (%d)", str_error, errno);
299
300                 if (EACCES == errno)
301                         return MM_ERROR_PLAYER_PERMISSION_DENIED;
302
303                 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
304         }
305
306         if (fstat(fd, &stat_results) < 0) {
307                 LOGE("failed to get file status");
308         } else if (stat_results.st_size == 0) {
309                 LOGE("file size is zero");
310                 close(fd);
311                 return MM_ERROR_PLAYER_FILE_NOT_FOUND;
312         } else
313                 LOGW("file size : %lld bytes", (long long)stat_results.st_size);
314
315         close(fd);
316
317         return MM_ERROR_NONE;
318 }
319
320 char **
321 _mmplayer_get_cookie_list(const char *cookies)
322 {
323         char **cookie_list = NULL;
324         char *temp = NULL;
325         gint i = 0;
326
327         if (!cookies || !strlen(cookies))
328                 return NULL;
329
330         SECURE_LOGD("cookies : %zu[bytes] - %s", strlen(cookies), cookies);
331
332         temp = g_strdup(cookies);
333
334         /* trimming. it works inplace */
335         g_strstrip(temp);
336
337         /* split */
338         cookie_list = g_strsplit(temp, ";", 100);
339
340         if (!cookie_list) {
341                 LOGE("failed to get cookie list");
342                 goto EXIT;
343         }
344
345         for (i = 0; i < g_strv_length(cookie_list); i++) {
346                 if (cookie_list[i]) {
347                         if (strlen(cookie_list[i])) {
348                                 g_strstrip(cookie_list[i]);
349                                 SECURE_LOGD("cookie_list[%d] : %zu[bytes] - %s", i, strlen(cookie_list[i]), cookie_list[i]);
350                         } else {
351                                 cookie_list[i][0] = '\0';
352                         }
353                 }
354         }
355
356 EXIT:
357         MMPLAYER_FREEIF(temp);
358
359         return cookie_list;
360 }
361
362 /* check the given path is indicating sdp file */
363 bool
364 _mmplayer_is_sdp_file(const char *path)
365 {
366         gboolean ret = FALSE;
367         gchar *uri = NULL;
368
369         MMPLAYER_FENTER();
370
371         MMPLAYER_RETURN_VAL_IF_FAIL(path, FALSE);
372
373         uri = g_ascii_strdown(path, -1);
374
375         if (uri == NULL)
376                 return FALSE;
377
378         /* trimming */
379         g_strstrip(uri);
380
381         /* strlen(".sdp") == 4 */
382         if (strlen(uri) <= 4) {
383                 LOGW("path is too short.");
384                 MMPLAYER_FREEIF(uri);
385                 return ret;
386         }
387
388         /* first, check extension name */
389         ret = g_str_has_suffix(uri, "sdp");
390
391         /* second, if no suffix is there, check it's contents */
392         if (!ret)
393                 /* FIXIT : do it soon */
394                 LOGD("no suffix");
395
396         MMPLAYER_FREEIF(uri);
397
398         return ret;
399 }
400
401 const char *
402 _mmplayer_get_charset(const char *file_path)
403 {
404         UCharsetDetector *ucsd;
405         const UCharsetMatch *ucm;
406         UErrorCode status = U_ZERO_ERROR;
407
408         const char *charset = NULL;
409         char *buf = NULL;
410         FILE *fin = 0;
411         size_t n_size = 0;
412
413         fin = fopen(file_path, "r");
414         if (!fin) {
415                 SECURE_LOGE("fail to open file %s", file_path);
416                 return NULL;
417         }
418
419         ucsd = ucsdet_open(&status);
420         if (U_FAILURE(status)) {
421                 LOGE("fail to ucsdet_open");
422                 goto done;
423         }
424
425         ucsdet_enableInputFilter(ucsd, TRUE);
426
427         buf = g_try_malloc(1024 * 1024);
428         if (!buf) {
429                 LOGE("fail to alloc");
430                 goto done;
431         }
432
433         n_size = fread(buf, 1, 1024*1024, fin);
434         buf[1024 * 1024 - 1] = '\0';
435         if (!n_size)
436                 goto done;
437
438         ucsdet_setText(ucsd, buf, strlen(buf), &status);
439         if (U_FAILURE(status)) {
440                 LOGE("fail to ucsdet_setText");
441                 goto done;
442         }
443
444         ucm = ucsdet_detect(ucsd, &status);
445         if (U_FAILURE(status)) {
446                 LOGE("fail to ucsdet_detect");
447                 goto done;
448         }
449
450         charset = ucsdet_getName(ucm, &status);
451         if (U_FAILURE(status)) {
452                 LOGE("fail to ucsdet_getName");
453                 goto done;
454         }
455
456         /* CP949 encoding is an extension of the EUC-KR and it is backwards compatible.*/
457         if (charset && !strcmp(charset, "EUC-KR"))
458                 charset = "CP949";
459
460 done:
461         if (fin)
462                 fclose(fin);
463
464         if (ucsd)
465                 ucsdet_close(ucsd);
466
467         MMPLAYER_FREEIF(buf);
468
469         return charset;
470 }
471
472 int
473 _mmplayer_get_pixtype(unsigned int fourcc)
474 {
475         int pixtype = MM_PIXEL_FORMAT_INVALID;
476
477 #ifdef __DEBUG__
478         char *pfourcc = (char *)&fourcc;
479
480         LOGD("fourcc(%c%c%c%c)",
481                 pfourcc[0], pfourcc[1], pfourcc[2], pfourcc[3]);
482 #endif
483
484         switch (fourcc) {
485         case GST_MAKE_FOURCC('S', 'N', '1', '2'):
486         case GST_MAKE_FOURCC('N', 'V', '1', '2'):
487                 pixtype = MM_PIXEL_FORMAT_NV12;
488                 break;
489         case GST_MAKE_FOURCC('S', 'T', '1', '2'):
490                 pixtype = MM_PIXEL_FORMAT_NV12T;
491                 break;
492         case GST_MAKE_FOURCC('S', 'N', '2', '1'):
493         case GST_MAKE_FOURCC('N', 'V', '2', '1'):
494                 pixtype = MM_PIXEL_FORMAT_NV21;
495                 break;
496         case GST_MAKE_FOURCC('S', 'U', 'Y', 'V'):
497         case GST_MAKE_FOURCC('Y', 'U', 'Y', 'V'):
498         case GST_MAKE_FOURCC('Y', 'U', 'Y', '2'):
499                 pixtype = MM_PIXEL_FORMAT_YUYV;
500                 break;
501         case GST_MAKE_FOURCC('S', 'Y', 'V', 'Y'):
502         case GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'):
503                 pixtype = MM_PIXEL_FORMAT_UYVY;
504                 break;
505         case GST_MAKE_FOURCC('S', '4', '2', '0'):
506         case GST_MAKE_FOURCC('I', '4', '2', '0'):
507                 pixtype = MM_PIXEL_FORMAT_I420;
508                 break;
509         case GST_MAKE_FOURCC('Y', 'V', '1', '2'):
510                 pixtype = MM_PIXEL_FORMAT_YV12;
511                 break;
512         case GST_MAKE_FOURCC('4', '2', '2', 'P'):
513                 pixtype = MM_PIXEL_FORMAT_422P;
514                 break;
515         case GST_MAKE_FOURCC('R', 'G', 'B', 'P'):
516                 pixtype = MM_PIXEL_FORMAT_RGB565;
517                 break;
518         case GST_MAKE_FOURCC('R', 'G', 'B', '3'):
519                 pixtype = MM_PIXEL_FORMAT_RGB888;
520                 break;
521         case GST_MAKE_FOURCC('A', 'R', 'G', 'B'):
522         case GST_MAKE_FOURCC('x', 'R', 'G', 'B'):
523                 pixtype = MM_PIXEL_FORMAT_ARGB;
524                 break;
525         case GST_MAKE_FOURCC('B', 'G', 'R', 'A'):
526         case GST_MAKE_FOURCC('B', 'G', 'R', 'x'):
527         case GST_MAKE_FOURCC('S', 'R', '3', '2'):
528                 pixtype = MM_PIXEL_FORMAT_RGBA;
529                 break;
530         case GST_MAKE_FOURCC('J', 'P', 'E', 'G'):
531         case GST_MAKE_FOURCC('P', 'N', 'G', ' '):
532                 pixtype = MM_PIXEL_FORMAT_ENCODED;
533                 break;
534         case GST_MAKE_FOURCC('I', 'T', 'L', 'V'):
535                 pixtype = MM_PIXEL_FORMAT_ITLV_JPEG_UYVY;
536                 break;
537         default:
538                 LOGE("Not supported fourcc type(%c%c%c%c)",
539                         fourcc, fourcc>>8, fourcc>>16, fourcc>>24);
540                 pixtype = MM_PIXEL_FORMAT_INVALID;
541                 break;
542         }
543
544         return pixtype;
545 }
546
547 static int
548 __mmplayer_storage_supported_cb(int storage_id, storage_type_e type,
549         storage_state_e state, const char *path, void *user_data)
550 {
551         mmplayer_storage_info_t *storage_info = (mmplayer_storage_info_t *)user_data;
552
553         MMPLAYER_RETURN_VAL_IF_FAIL(storage_info, FALSE);
554
555         if (type == storage_info->type && strstr(storage_info->path, path)) {
556                 storage_info->id = storage_id;
557                 storage_info->state = state;
558                 return FALSE;
559         }
560
561         return TRUE;
562 }
563
564 bool
565 _mmplayer_get_storage_info(const char *path, mmplayer_storage_info_t *storage_info)
566 {
567         int ret = 0;
568         const char *file_path = path;
569
570         MMPLAYER_RETURN_VAL_IF_FAIL(file_path && storage_info, false);
571
572         if (strncmp(file_path, "file://", strlen("file://")) == 0)
573                 file_path = path + 7; /* remove file prefix */
574
575         if (strncmp(file_path, MEDIA_PATH_EXTERNAL, strlen(MEDIA_PATH_EXTERNAL)) == 0) {
576                 storage_info->type = STORAGE_TYPE_EXTERNAL;
577
578                 memset(storage_info->path, 0x00, MM_MAX_URL_LEN);
579                 g_snprintf(storage_info->path, MM_MAX_URL_LEN, "%s", file_path);
580
581                 ret = storage_foreach_device_supported((storage_device_supported_cb)__mmplayer_storage_supported_cb, storage_info);
582                 if (ret != STORAGE_ERROR_NONE) {
583                         LOGE("failed to check supported storage 0x%x", ret);
584                         return false;
585                 }
586
587                 if (storage_info->state <= STORAGE_STATE_REMOVED) {
588                         LOGE("need to check the external storage state %d:%d", storage_info->id, storage_info->state);
589                         return false;
590                 }
591         } else {
592                 storage_info->type = STORAGE_TYPE_INTERNAL;
593                 storage_info->state = STORAGE_STATE_MOUNTED;
594         }
595
596         LOGD("storage info %d:%d:%d", storage_info->type, storage_info->id, storage_info->state);
597         return true;
598 }
599
600 media_format_mimetype_e _mmplayer_convert_audio_pcm_str_to_media_format_mime(const gchar *audio_pcm_str)
601 {
602         if (!audio_pcm_str) {
603                 LOGW("audio pcm str is NULL");
604                 return MEDIA_FORMAT_MAX;
605         }
606
607         if (strstr(audio_pcm_str, "S16LE"))
608                 return MEDIA_FORMAT_PCM_S16LE;
609         else if (strstr(audio_pcm_str, "S24LE"))
610                 return MEDIA_FORMAT_PCM_S24LE;
611         else if (strstr(audio_pcm_str, "S32LE"))
612                 return MEDIA_FORMAT_PCM_S32LE;
613         else if (strstr(audio_pcm_str, "S16BE"))
614                 return MEDIA_FORMAT_PCM_S16BE;
615         else if (strstr(audio_pcm_str, "S24BE"))
616                 return MEDIA_FORMAT_PCM_S24BE;
617         else if (strstr(audio_pcm_str, "S32BE"))
618                 return MEDIA_FORMAT_PCM_S32BE;
619         else if (strstr(audio_pcm_str, "F32LE"))
620                 return MEDIA_FORMAT_PCM_F32LE;
621         else if (strstr(audio_pcm_str, "F32BE"))
622                 return MEDIA_FORMAT_PCM_F32BE;
623         else if (strstr(audio_pcm_str, "U16LE"))
624                 return MEDIA_FORMAT_PCM_U16LE;
625         else if (strstr(audio_pcm_str, "U24LE"))
626                 return MEDIA_FORMAT_PCM_U24LE;
627         else if (strstr(audio_pcm_str, "U32LE"))
628                 return MEDIA_FORMAT_PCM_U32LE;
629         else if (strstr(audio_pcm_str, "U16BE"))
630                 return MEDIA_FORMAT_PCM_U16BE;
631         else if (strstr(audio_pcm_str, "U24BE"))
632                 return MEDIA_FORMAT_PCM_U24BE;
633         else if (strstr(audio_pcm_str, "U32BE"))
634                 return MEDIA_FORMAT_PCM_U32BE;
635         else {
636                 LOGW("Not supported audio pcm format str : %s", audio_pcm_str);
637                 return MEDIA_FORMAT_MAX;
638         }
639 }