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