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