2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @file mediademuxer_port.c
19 * @brief general port based functions. sets specific function pointers
24 #include <mm_message.h>
26 #include <mediademuxer.h>
27 #include <mediademuxer_ini.h>
28 #include <mediademuxer_error.h>
29 #include <mediademuxer_private.h>
30 #include <mediademuxer_port.h>
31 #include <sys/types.h>
36 #define MAX_ERR_LEN 256
39 extern int gst_mediademxer_port_register(media_port_demuxer_ops *pOps);
40 extern int ffmpeg_mediademxer_port_register(media_port_demuxer_ops *pOps);
41 extern int custom_mediademxer_port_register(media_port_demuxer_ops *pOps);
42 int __md_util_exist_file_path(const char *file_path);
43 bool __md_util_is_sdp_file(const char *path);
44 mediademuxer_src_type __md_util_media_type(char **uri);
45 int _md_util_parse(MMHandleType demuxer, const char *type);
48 * Sequence of functions should be same as the port enumeration
49 * "port_mode" in mm_demuxer_ini.h file
51 typedef int (*register_port_demuxer)(media_port_demuxer_ops *);
52 register_port_demuxer register_port_demuxer_func[] = {
53 &gst_mediademxer_port_register,
54 &ffmpeg_mediademxer_port_register,
55 &custom_mediademxer_port_register
58 int md_create(MMHandleType *demuxer)
60 int result = MD_ERROR_NONE;
61 media_port_demuxer_ops *pOps = NULL;
62 md_handle_t *new_demuxer = NULL;
63 MEDIADEMUXER_FENTER();
64 new_demuxer = (md_handle_t *)g_malloc(sizeof(md_handle_t));
65 MD_I("md_create allocatiing new_demuxer %p:\n", new_demuxer);
66 MEDIADEMUXER_CHECK_NULL(new_demuxer);
67 memset(new_demuxer, 0, sizeof(md_handle_t));
69 /* alloc ops structure */
70 pOps = (media_port_demuxer_ops *)g_malloc(sizeof(media_port_demuxer_ops));
71 MEDIADEMUXER_CHECK_NULL(pOps);
73 new_demuxer->demuxer_ops = pOps;
74 MD_I("md_create allocating new_demuxer->demuxer_ops %p:\n",
75 new_demuxer->demuxer_ops);
76 pOps->n_size = sizeof(media_port_demuxer_ops);
78 new_demuxer->uri_src = NULL;
79 new_demuxer->uri_src_media_type = MEDIADEMUXER_SRC_INVALID;
81 result = md_ini_load(&new_demuxer->ini);
82 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
83 MD_COURRPTED_INI, "can't load ini");
85 register_port_demuxer_func[new_demuxer->ini.port_type](pOps);
86 result = pOps->init(&new_demuxer->mdport_handle);
87 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
88 MD_NOT_INITIALIZED, "md_create failed");
89 *demuxer = (MMHandleType)new_demuxer;
90 MEDIADEMUXER_FLEAVE();
93 *demuxer = (MMHandleType)0;
98 MEDIADEMUXER_FLEAVE();
102 int __md_util_exist_file_path(const char *file_path)
105 struct stat stat_results = { 0, };
106 MEDIADEMUXER_FENTER();
108 if (!file_path || !strlen(file_path))
109 return MD_ERROR_FILE_NOT_FOUND;
111 fd = open(file_path, O_RDONLY);
113 char buf[MAX_ERR_LEN];
115 ret_err = strerror_r(errno, buf, MAX_ERR_LEN);
117 MD_E("failed to open file by %s (%d)\n", buf, errno);
119 MD_E("File not found, strerror_r() failed with errno (%d)\n", errno);
120 MEDIADEMUXER_FLEAVE();
121 return MD_ERROR_FILE_NOT_FOUND;
124 if (fstat(fd, &stat_results) < 0) {
125 MD_E("failed to get file status\n");
127 MEDIADEMUXER_FLEAVE();
128 return MD_ERROR_FILE_NOT_FOUND;
129 } else if (stat_results.st_size == 0) {
130 MD_E("file size is zero\n");
132 MEDIADEMUXER_FLEAVE();
133 return MD_ERROR_FILE_NOT_FOUND;
135 MD_E("file size : %lld bytes\n", (long long)stat_results.st_size);
138 MEDIADEMUXER_FLEAVE();
139 return MD_ERROR_NONE;
142 bool __md_util_is_sdp_file(const char *path)
144 gboolean ret = FALSE;
146 MEDIADEMUXER_FENTER();
147 return_val_if_fail(path, FALSE);
148 uri = g_ascii_strdown(path, -1);
153 /* strlen(".sdp") == 4 */
154 if (strlen(uri) <= 4) {
155 MD_W("path is too short.\n");
158 /* first, check extension name */
159 ret = g_str_has_suffix(uri, "sdp");
160 /* second, if no suffix is there, check it's contents */
162 /* FIXIT : do it soon */
165 MEDIADEMUXER_FLEAVE();
169 mediademuxer_src_type __md_util_media_type(char **uri)
172 char *new_uristr = NULL;
173 char *old_uristr = NULL;
174 MEDIADEMUXER_FENTER();
175 if ((path = strstr((*uri), "file://"))) {
176 int file_stat = MD_ERROR_NONE;
177 file_stat = __md_util_exist_file_path(path + 7);
178 if (file_stat == MD_ERROR_NONE) {
179 if (__md_util_is_sdp_file(path)) {
180 #ifdef TIZEN_FEATURE_STREAMING
181 MD_L("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
182 return MEDIADEMUXER_SRC_RTSP;
184 MD_L("uri is actually a file but it's sdp file. didn't support streaming uri");
185 return MEDIADEMUXER_SRC_INVALID;
188 return MEDIADEMUXER_SRC_FILE;
190 return MD_ERROR_NONE;
192 MD_E("could not access %s.\n", path);
195 #ifdef TIZEN_FEATURE_STREAMING
196 } else if ((path = strstr(*uri, "rtsp://"))) {
198 if ((path = strstr(*uri, "/wfd1.0/")))
199 return (MEDIADEMUXER_SRC_WFD);
201 return (MEDIADEMUXER_SRC_RTSP);
203 } else if ((path = strstr(*uri, "http://"))) {
205 if (g_str_has_suffix(g_ascii_strdown(*uri, strlen(*uri)), ".ism/manifest") ||
206 g_str_has_suffix(g_ascii_strdown(*uri, strlen(*uri)), ".isml/manifest")) {
207 return (MEDIADEMUXER_SRC_SS);
209 return (MEDIADEMUXER_SRC_HTTP);
214 int file_stat = MD_ERROR_NONE;
215 file_stat = __md_util_exist_file_path(*uri);
216 if (file_stat == MD_ERROR_NONE) {
217 int len_uri = strlen(*uri);
218 old_uristr = (char *)g_malloc(sizeof(char) * (len_uri + 1));
219 MEDIADEMUXER_CHECK_NULL(old_uristr);
220 MD_L("allocating temp old_uristr[%p] \n", old_uristr);
221 strncpy(old_uristr, *uri, len_uri + 1);
222 /* need to added 7 char for file:// + 1 for '\0'+ uri len */
223 new_uristr = (char *)realloc(*uri, (7 + len_uri + 1) * sizeof(char));
227 return MD_ERROR_INVALID_ARGUMENT;
229 MD_L("reallocating uri[%p] to new_uristr[%p] \n", *uri, new_uristr);
231 g_snprintf(*uri, 7 + len_uri + 1, "file://%s", old_uristr);
232 MD_L("deallocating old_uristr[%p] \n", old_uristr);
235 if (__md_util_is_sdp_file((char *)(*uri))) {
236 #ifdef TIZEN_FEATURE_STREAMING
237 MD_L("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
238 return MEDIADEMUXER_SRC_RTSP;
240 MD_L("uri is actually a file but it's sdp file. didn't support streaming uri");
241 return MEDIADEMUXER_SRC_INVALID;
244 return (MEDIADEMUXER_SRC_FILE);
250 MEDIADEMUXER_FLEAVE();
251 return MD_ERROR_NONE;
253 MEDIADEMUXER_FLEAVE();
254 return MEDIADEMUXER_SRC_INVALID;
257 int _md_util_parse(MMHandleType demuxer, const char *type)
259 char *media_type_string = NULL;
260 int lenght_string = 0;
261 int result = MD_ERROR_NONE;
262 md_handle_t *new_demuxer = NULL;
263 MEDIADEMUXER_FENTER();
264 MEDIADEMUXER_CHECK_NULL(demuxer);
265 new_demuxer = (md_handle_t *)demuxer;
266 lenght_string = strlen(type);
267 media_type_string = (char *)g_malloc(sizeof(char) * (lenght_string + 1));
268 MEDIADEMUXER_CHECK_NULL(media_type_string);
269 MD_L("media_type_string allocating %p\n", media_type_string);
270 strncpy(media_type_string, type, lenght_string + 1);
271 /*Set media_type depending upon the header of string else consider using file protocol */
272 if (new_demuxer->uri_src) {
273 MD_L("new_demuxer->uri_src deallocating %p\n", new_demuxer->uri_src);
274 g_free(new_demuxer->uri_src);
275 new_demuxer->uri_src = NULL;
277 new_demuxer->uri_src_media_type = __md_util_media_type(&media_type_string);
278 if (new_demuxer->uri_src_media_type != MEDIADEMUXER_SRC_INVALID) {
279 if (new_demuxer->uri_src)
280 g_free(new_demuxer->uri_src);
281 new_demuxer->uri_src = media_type_string;
282 MD_L("uri:%s\n uri_type:%d\n", new_demuxer->uri_src,
283 new_demuxer->uri_src_media_type);
285 MD_E("Error while setiing source\n");
286 MD_E("deallocating media_type_string %p\n", media_type_string);
287 g_free(media_type_string);
290 MEDIADEMUXER_FLEAVE();
293 result = MD_ERROR_INVALID_ARGUMENT;
294 MEDIADEMUXER_FLEAVE();
298 int md_set_data_source(MMHandleType demuxer, const char *uri)
300 int result = MD_ERROR_NONE;
301 MEDIADEMUXER_FENTER();
302 MEDIADEMUXER_CHECK_NULL(demuxer);
303 result = _md_util_parse(demuxer, (const char *)uri);
304 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
305 MD_ERROR_INVALID_ARGUMENT,
306 "error while parsing the file");
307 MEDIADEMUXER_FLEAVE();
310 result = MD_ERROR_INVALID_ARGUMENT;
311 MEDIADEMUXER_FLEAVE();
315 int md_prepare(MMHandleType demuxer)
317 int result = MD_ERROR_NONE;
318 md_handle_t *md_handle = (md_handle_t *)demuxer;
319 MEDIADEMUXER_FENTER();
320 MEDIADEMUXER_CHECK_NULL(md_handle);
321 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
322 MEDIADEMUXER_CHECK_NULL(pOps);
323 MEDIADEMUXER_CHECK_NULL(md_handle->uri_src);
324 result = pOps->prepare(md_handle->mdport_handle, md_handle->uri_src);
325 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
326 MD_ERROR, "error while doing prepare");
327 MEDIADEMUXER_FLEAVE();
330 result = MD_ERROR_INVALID_ARGUMENT;
331 MEDIADEMUXER_FLEAVE();
335 int md_get_track_count(MMHandleType demuxer, int *count)
337 int result = MD_ERROR_NONE;
338 md_handle_t *md_handle = (md_handle_t *)demuxer;
339 MEDIADEMUXER_FENTER();
340 MEDIADEMUXER_CHECK_NULL(md_handle);
341 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
342 MEDIADEMUXER_CHECK_NULL(pOps);
343 result = pOps->get_track_count(md_handle->mdport_handle, count);
344 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE,
346 "error while getting track count");
347 MEDIADEMUXER_FLEAVE();
350 result = MD_ERROR_INVALID_ARGUMENT;
351 MEDIADEMUXER_FLEAVE();
355 int md_select_track(MMHandleType demuxer, int track)
357 int result = MD_ERROR_NONE;
358 md_handle_t *md_handle = (md_handle_t *)demuxer;
359 MEDIADEMUXER_FENTER();
360 MEDIADEMUXER_CHECK_NULL(md_handle);
361 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
362 MEDIADEMUXER_CHECK_NULL(pOps);
363 result = pOps->set_track(md_handle->mdport_handle, track);
364 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
365 MD_ERROR, "error select track");
366 MEDIADEMUXER_FLEAVE();
369 result = MD_ERROR_INVALID_ARGUMENT;
370 MEDIADEMUXER_FLEAVE();
374 int md_start(MMHandleType demuxer)
376 int result = MD_ERROR_NONE;
377 md_handle_t *md_handle = (md_handle_t *)demuxer;
378 MEDIADEMUXER_FENTER();
379 MEDIADEMUXER_CHECK_NULL(md_handle);
380 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
381 MEDIADEMUXER_CHECK_NULL(pOps);
382 result = pOps->start(md_handle->mdport_handle);
383 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
384 MD_ERROR, "error while doing start");
385 MEDIADEMUXER_FLEAVE();
388 result = MD_ERROR_INVALID_ARGUMENT;
389 MEDIADEMUXER_FLEAVE();
393 int md_get_track_info(MMHandleType demuxer, int track, media_format_h *format)
395 int result = MD_ERROR_NONE;
396 md_handle_t *md_handle = (md_handle_t *)demuxer;
397 MEDIADEMUXER_FENTER();
398 MEDIADEMUXER_CHECK_NULL(md_handle);
399 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
400 MEDIADEMUXER_CHECK_NULL(pOps);
401 result = pOps->get_track_info(md_handle->mdport_handle, format, track);
402 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE,
404 "error while getting track count");
405 MEDIADEMUXER_FLEAVE();
408 result = MD_ERROR_INVALID_ARGUMENT;
409 MEDIADEMUXER_FLEAVE();
413 int md_read_sample(MMHandleType demuxer, int track_indx, media_packet_h *outbuf)
415 int result = MD_ERROR_NONE;
416 md_handle_t *md_handle = (md_handle_t *)demuxer;
417 MEDIADEMUXER_FENTER();
418 MEDIADEMUXER_CHECK_NULL(md_handle);
419 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
420 MEDIADEMUXER_CHECK_NULL(pOps);
421 result = pOps->read_sample(md_handle->mdport_handle, outbuf, track_indx);
422 if (result == MD_ERROR_NONE) {
423 MEDIADEMUXER_FLEAVE();
426 MD_E("error while reading sample\n");
430 result = MD_ERROR_INVALID_ARGUMENT;
431 MEDIADEMUXER_FLEAVE();
435 int md_seek(MMHandleType demuxer, int64_t pos)
437 int result = MD_ERROR_NONE;
438 md_handle_t *md_handle = (md_handle_t *)demuxer;
439 MEDIADEMUXER_FENTER();
440 MEDIADEMUXER_CHECK_NULL(md_handle);
441 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
442 MEDIADEMUXER_CHECK_NULL(pOps);
443 result = pOps->seek(md_handle->mdport_handle, pos);
444 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
445 MD_ERROR, "error while doing seek");
446 MEDIADEMUXER_FLEAVE();
449 result = MD_ERROR_INVALID_ARGUMENT;
450 MEDIADEMUXER_FLEAVE();
454 int md_unselect_track(MMHandleType demuxer, int track)
456 int result = MD_ERROR_NONE;
457 md_handle_t *md_handle = (md_handle_t *)demuxer;
458 MEDIADEMUXER_FENTER();
459 MEDIADEMUXER_CHECK_NULL(md_handle);
460 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
461 MEDIADEMUXER_CHECK_NULL(pOps);
462 result = pOps->unset_track(md_handle->mdport_handle, track);
463 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
464 MD_ERROR, "error unselect track");
465 MEDIADEMUXER_FLEAVE();
468 result = MD_ERROR_INVALID_ARGUMENT;
469 MEDIADEMUXER_FLEAVE();
473 int md_stop(MMHandleType demuxer)
475 int result = MD_ERROR_NONE;
476 md_handle_t *md_handle = (md_handle_t *)demuxer;
477 MEDIADEMUXER_FENTER();
478 MEDIADEMUXER_CHECK_NULL(md_handle);
479 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
480 MEDIADEMUXER_CHECK_NULL(pOps);
481 result = pOps->stop(md_handle->mdport_handle);
482 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
483 MD_ERROR, "error while doing stop");
484 MEDIADEMUXER_FLEAVE();
487 result = MD_ERROR_INVALID_ARGUMENT;
488 MEDIADEMUXER_FLEAVE();
492 int md_unprepare(MMHandleType demuxer)
494 int result = MD_ERROR_NONE;
495 md_handle_t *md_handle = (md_handle_t *)demuxer;
496 MEDIADEMUXER_FENTER();
497 MEDIADEMUXER_CHECK_NULL(md_handle);
498 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
499 MEDIADEMUXER_CHECK_NULL(pOps);
500 result = pOps->unprepare(md_handle->mdport_handle);
501 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
502 MD_ERROR, "error while doing stop");
503 MEDIADEMUXER_FLEAVE();
506 result = MD_ERROR_INVALID_ARGUMENT;
507 MEDIADEMUXER_FLEAVE();
511 int md_destroy(MMHandleType demuxer)
513 int result = MD_ERROR_NONE;
514 md_handle_t *md_handle = (md_handle_t *)demuxer;
515 MEDIADEMUXER_CHECK_NULL(md_handle);
516 MEDIADEMUXER_FENTER();
517 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
518 MEDIADEMUXER_CHECK_NULL(pOps);
519 result = pOps->destroy(md_handle->mdport_handle);
520 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
521 MD_ERROR, "error while doing destroy");
523 /* free mediademuxer structure */
525 if (md_handle->demuxer_ops) {
526 MD_I("md_destroy deallocating md_handle->demuxer_ops %p:\n", md_handle->demuxer_ops);
527 g_free((void *)(md_handle->demuxer_ops));
529 if (md_handle->uri_src) {
530 MD_I("md_destroy deallocating md_handle->uri_src %p:\n",
532 g_free((void *)(md_handle->uri_src));
534 MD_I("md_destroy deallocating md_handle %p:\n", md_handle);
535 g_free((void *)md_handle);
538 MEDIADEMUXER_FLEAVE();
545 int md_set_error_cb(MMHandleType demuxer,
546 mediademuxer_error_cb callback, void *user_data)
548 MEDIADEMUXER_FENTER();
549 int result = MD_ERROR_NONE;
550 md_handle_t *md_handle = (md_handle_t *)demuxer;
551 MEDIADEMUXER_CHECK_NULL(md_handle);
552 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
553 MEDIADEMUXER_CHECK_NULL(pOps);
554 result = pOps->set_error_cb(md_handle->mdport_handle, callback, user_data);
555 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
556 MD_ERROR, "error while setting error call back");
557 MEDIADEMUXER_FLEAVE();
560 result = MD_ERROR_INVALID_ARGUMENT;
561 MEDIADEMUXER_FLEAVE();
565 int md_set_eos_cb(MMHandleType demuxer,
566 mediademuxer_eos_cb callback, void *user_data)
568 MEDIADEMUXER_FENTER();
569 int result = MD_ERROR_NONE;
570 md_handle_t *md_handle = (md_handle_t *)demuxer;
571 MEDIADEMUXER_CHECK_NULL(md_handle);
572 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
573 MEDIADEMUXER_CHECK_NULL(pOps);
574 result = pOps->set_eos_cb(md_handle->mdport_handle, callback, user_data);
575 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
576 MD_ERROR, "error while setting eos call back");
577 MEDIADEMUXER_FLEAVE();
580 result = MD_ERROR_INVALID_ARGUMENT;
581 MEDIADEMUXER_FLEAVE();