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