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 MD_L("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
181 return MEDIADEMUXER_SRC_RTSP;
183 return MEDIADEMUXER_SRC_FILE;
185 return MD_ERROR_NONE;
187 MD_E("could not access %s.\n", path);
190 } else if ((path = strstr(*uri, "rtsp://"))) {
192 if ((path = strstr(*uri, "/wfd1.0/")))
193 return (MEDIADEMUXER_SRC_WFD);
195 return (MEDIADEMUXER_SRC_RTSP);
197 } else if ((path = strstr(*uri, "http://"))) {
199 if (g_str_has_suffix(g_ascii_strdown(*uri, strlen(*uri)), ".ism/manifest") ||
200 g_str_has_suffix(g_ascii_strdown(*uri, strlen(*uri)), ".isml/manifest")) {
201 return (MEDIADEMUXER_SRC_SS);
203 return (MEDIADEMUXER_SRC_HTTP);
207 int file_stat = MD_ERROR_NONE;
208 file_stat = __md_util_exist_file_path(*uri);
209 if (file_stat == MD_ERROR_NONE) {
210 int len_uri = strlen(*uri);
211 old_uristr = (char *)g_malloc(sizeof(char) * (len_uri + 1));
212 MEDIADEMUXER_CHECK_NULL(old_uristr);
213 MD_L("allocating temp old_uristr[%p] \n", old_uristr);
214 strncpy(old_uristr, *uri, len_uri + 1);
215 /* need to added 7 char for file:// + 1 for '\0'+ uri len */
216 new_uristr = (char *)realloc(*uri, (7 + len_uri + 1) * sizeof(char));
220 return MD_ERROR_INVALID_ARGUMENT;
222 MD_L("reallocating uri[%p] to new_uristr[%p] \n", *uri, new_uristr);
224 g_snprintf(*uri, 7 + len_uri + 1, "file://%s", old_uristr);
225 MD_L("deallocating old_uristr[%p] \n", old_uristr);
228 if (__md_util_is_sdp_file((char *)(*uri))) {
229 MD_L("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
230 return (MEDIADEMUXER_SRC_RTSP);
232 return (MEDIADEMUXER_SRC_FILE);
238 MEDIADEMUXER_FLEAVE();
239 return MD_ERROR_NONE;
241 MEDIADEMUXER_FLEAVE();
242 return MEDIADEMUXER_SRC_INVALID;
245 int _md_util_parse(MMHandleType demuxer, const char *type)
247 char *media_type_string = NULL;
248 int lenght_string = 0;
249 int result = MD_ERROR_NONE;
250 md_handle_t *new_demuxer = NULL;
251 MEDIADEMUXER_FENTER();
252 MEDIADEMUXER_CHECK_NULL(demuxer);
253 new_demuxer = (md_handle_t *)demuxer;
254 lenght_string = strlen(type);
255 media_type_string = (char *)g_malloc(sizeof(char) * (lenght_string + 1));
256 MEDIADEMUXER_CHECK_NULL(media_type_string);
257 MD_L("media_type_string allocating %p\n", media_type_string);
258 strncpy(media_type_string, type, lenght_string + 1);
259 /*Set media_type depending upon the header of string else consider using file protocol */
260 if (new_demuxer->uri_src) {
261 MD_L("new_demuxer->uri_src deallocating %p\n", new_demuxer->uri_src);
262 g_free(new_demuxer->uri_src);
263 new_demuxer->uri_src = NULL;
265 new_demuxer->uri_src_media_type = __md_util_media_type(&media_type_string);
266 if (new_demuxer->uri_src_media_type != MEDIADEMUXER_SRC_INVALID) {
267 if (new_demuxer->uri_src)
268 g_free(new_demuxer->uri_src);
269 new_demuxer->uri_src = media_type_string;
270 MD_L("uri:%s\n uri_type:%d\n", new_demuxer->uri_src,
271 new_demuxer->uri_src_media_type);
273 MD_E("Error while setiing source\n");
274 MD_E("deallocating media_type_string %p\n", media_type_string);
275 g_free(media_type_string);
278 MEDIADEMUXER_FLEAVE();
281 result = MD_ERROR_INVALID_ARGUMENT;
282 MEDIADEMUXER_FLEAVE();
286 int md_set_data_source(MMHandleType demuxer, const char *uri)
288 int result = MD_ERROR_NONE;
289 MEDIADEMUXER_FENTER();
290 MEDIADEMUXER_CHECK_NULL(demuxer);
291 result = _md_util_parse(demuxer, (const char *)uri);
292 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
293 MD_ERROR_INVALID_ARGUMENT,
294 "error while parsing the file");
295 MEDIADEMUXER_FLEAVE();
298 result = MD_ERROR_INVALID_ARGUMENT;
299 MEDIADEMUXER_FLEAVE();
303 int md_prepare(MMHandleType demuxer)
305 int result = MD_ERROR_NONE;
306 md_handle_t *md_handle = (md_handle_t *)demuxer;
307 MEDIADEMUXER_FENTER();
308 MEDIADEMUXER_CHECK_NULL(md_handle);
309 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
310 MEDIADEMUXER_CHECK_NULL(pOps);
311 MEDIADEMUXER_CHECK_NULL(md_handle->uri_src);
312 result = pOps->prepare(md_handle->mdport_handle, md_handle->uri_src);
313 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
314 MD_ERROR, "error while doing prepare");
315 MEDIADEMUXER_FLEAVE();
318 result = MD_ERROR_INVALID_ARGUMENT;
319 MEDIADEMUXER_FLEAVE();
323 int md_get_track_count(MMHandleType demuxer, int *count)
325 int result = MD_ERROR_NONE;
326 md_handle_t *md_handle = (md_handle_t *)demuxer;
327 MEDIADEMUXER_FENTER();
328 MEDIADEMUXER_CHECK_NULL(md_handle);
329 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
330 MEDIADEMUXER_CHECK_NULL(pOps);
331 result = pOps->get_track_count(md_handle->mdport_handle, count);
332 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE,
334 "error while getting track count");
335 MEDIADEMUXER_FLEAVE();
338 result = MD_ERROR_INVALID_ARGUMENT;
339 MEDIADEMUXER_FLEAVE();
343 int md_select_track(MMHandleType demuxer, int track)
345 int result = MD_ERROR_NONE;
346 md_handle_t *md_handle = (md_handle_t *)demuxer;
347 MEDIADEMUXER_FENTER();
348 MEDIADEMUXER_CHECK_NULL(md_handle);
349 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
350 MEDIADEMUXER_CHECK_NULL(pOps);
351 result = pOps->set_track(md_handle->mdport_handle, track);
352 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
353 MD_ERROR, "error select track");
354 MEDIADEMUXER_FLEAVE();
357 result = MD_ERROR_INVALID_ARGUMENT;
358 MEDIADEMUXER_FLEAVE();
362 int md_start(MMHandleType demuxer)
364 int result = MD_ERROR_NONE;
365 md_handle_t *md_handle = (md_handle_t *)demuxer;
366 MEDIADEMUXER_FENTER();
367 MEDIADEMUXER_CHECK_NULL(md_handle);
368 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
369 MEDIADEMUXER_CHECK_NULL(pOps);
370 result = pOps->start(md_handle->mdport_handle);
371 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
372 MD_ERROR, "error while doing start");
373 MEDIADEMUXER_FLEAVE();
376 result = MD_ERROR_INVALID_ARGUMENT;
377 MEDIADEMUXER_FLEAVE();
381 int md_get_track_info(MMHandleType demuxer, int track, media_format_h *format)
383 int result = MD_ERROR_NONE;
384 md_handle_t *md_handle = (md_handle_t *)demuxer;
385 MEDIADEMUXER_FENTER();
386 MEDIADEMUXER_CHECK_NULL(md_handle);
387 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
388 MEDIADEMUXER_CHECK_NULL(pOps);
389 result = pOps->get_track_info(md_handle->mdport_handle, format, track);
390 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE,
392 "error while getting track count");
393 MEDIADEMUXER_FLEAVE();
396 result = MD_ERROR_INVALID_ARGUMENT;
397 MEDIADEMUXER_FLEAVE();
401 int md_read_sample(MMHandleType demuxer, int track_indx, media_packet_h *outbuf)
403 int result = MD_ERROR_NONE;
404 md_handle_t *md_handle = (md_handle_t *)demuxer;
405 MEDIADEMUXER_FENTER();
406 MEDIADEMUXER_CHECK_NULL(md_handle);
407 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
408 MEDIADEMUXER_CHECK_NULL(pOps);
409 result = pOps->read_sample(md_handle->mdport_handle, outbuf, track_indx);
410 if (result == MD_ERROR_NONE) {
411 MEDIADEMUXER_FLEAVE();
414 MD_E("error while reading sample\n");
418 result = MD_ERROR_INVALID_ARGUMENT;
419 MEDIADEMUXER_FLEAVE();
423 int md_seek(MMHandleType demuxer, int64_t pos)
425 int result = MD_ERROR_NONE;
426 md_handle_t *md_handle = (md_handle_t *)demuxer;
427 MEDIADEMUXER_FENTER();
428 MEDIADEMUXER_CHECK_NULL(md_handle);
429 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
430 MEDIADEMUXER_CHECK_NULL(pOps);
431 result = pOps->seek(md_handle->mdport_handle, pos);
432 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
433 MD_ERROR, "error while doing seek");
434 MEDIADEMUXER_FLEAVE();
437 result = MD_ERROR_INVALID_ARGUMENT;
438 MEDIADEMUXER_FLEAVE();
442 int md_unselect_track(MMHandleType demuxer, int track)
444 int result = MD_ERROR_NONE;
445 md_handle_t *md_handle = (md_handle_t *)demuxer;
446 MEDIADEMUXER_FENTER();
447 MEDIADEMUXER_CHECK_NULL(md_handle);
448 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
449 MEDIADEMUXER_CHECK_NULL(pOps);
450 result = pOps->unset_track(md_handle->mdport_handle, track);
451 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
452 MD_ERROR, "error unselect track");
453 MEDIADEMUXER_FLEAVE();
456 result = MD_ERROR_INVALID_ARGUMENT;
457 MEDIADEMUXER_FLEAVE();
461 int md_stop(MMHandleType demuxer)
463 int result = MD_ERROR_NONE;
464 md_handle_t *md_handle = (md_handle_t *)demuxer;
465 MEDIADEMUXER_FENTER();
466 MEDIADEMUXER_CHECK_NULL(md_handle);
467 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
468 MEDIADEMUXER_CHECK_NULL(pOps);
469 result = pOps->stop(md_handle->mdport_handle);
470 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
471 MD_ERROR, "error while doing stop");
472 MEDIADEMUXER_FLEAVE();
475 result = MD_ERROR_INVALID_ARGUMENT;
476 MEDIADEMUXER_FLEAVE();
480 int md_unprepare(MMHandleType demuxer)
482 int result = MD_ERROR_NONE;
483 md_handle_t *md_handle = (md_handle_t *)demuxer;
484 MEDIADEMUXER_FENTER();
485 MEDIADEMUXER_CHECK_NULL(md_handle);
486 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
487 MEDIADEMUXER_CHECK_NULL(pOps);
488 result = pOps->unprepare(md_handle->mdport_handle);
489 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
490 MD_ERROR, "error while doing stop");
491 MEDIADEMUXER_FLEAVE();
494 result = MD_ERROR_INVALID_ARGUMENT;
495 MEDIADEMUXER_FLEAVE();
499 int md_destroy(MMHandleType demuxer)
501 int result = MD_ERROR_NONE;
502 md_handle_t *md_handle = (md_handle_t *)demuxer;
503 MEDIADEMUXER_CHECK_NULL(md_handle);
504 MEDIADEMUXER_FENTER();
505 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
506 MEDIADEMUXER_CHECK_NULL(pOps);
507 result = pOps->destroy(md_handle->mdport_handle);
508 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
509 MD_ERROR, "error while doing destroy");
511 /* free mediademuxer structure */
513 if (md_handle->demuxer_ops) {
514 MD_I("md_destroy deallocating md_handle->demuxer_ops %p:\n", md_handle->demuxer_ops);
515 g_free((void *)(md_handle->demuxer_ops));
517 if (md_handle->uri_src) {
518 MD_I("md_destroy deallocating md_handle->uri_src %p:\n",
520 g_free((void *)(md_handle->uri_src));
522 MD_I("md_destroy deallocating md_handle %p:\n", md_handle);
523 g_free((void *)md_handle);
526 MEDIADEMUXER_FLEAVE();
533 int md_set_error_cb(MMHandleType demuxer,
534 mediademuxer_error_cb callback, void *user_data)
536 MEDIADEMUXER_FENTER();
537 int result = MD_ERROR_NONE;
538 md_handle_t *md_handle = (md_handle_t *)demuxer;
539 MEDIADEMUXER_CHECK_NULL(md_handle);
540 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
541 MEDIADEMUXER_CHECK_NULL(pOps);
542 result = pOps->set_error_cb(md_handle->mdport_handle, callback, user_data);
543 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
544 MD_ERROR, "error while setting error call back");
545 MEDIADEMUXER_FLEAVE();
548 result = MD_ERROR_INVALID_ARGUMENT;
549 MEDIADEMUXER_FLEAVE();
553 int md_set_eos_cb(MMHandleType demuxer,
554 mediademuxer_eos_cb callback, void *user_data)
556 MEDIADEMUXER_FENTER();
557 int result = MD_ERROR_NONE;
558 md_handle_t *md_handle = (md_handle_t *)demuxer;
559 MEDIADEMUXER_CHECK_NULL(md_handle);
560 media_port_demuxer_ops *pOps = md_handle->demuxer_ops;
561 MEDIADEMUXER_CHECK_NULL(pOps);
562 result = pOps->set_eos_cb(md_handle->mdport_handle, callback, user_data);
563 MEDIADEMUXER_CHECK_SET_AND_PRINT(result, MD_ERROR_NONE, result,
564 MD_ERROR, "error while setting eos call back");
565 MEDIADEMUXER_FLEAVE();
568 result = MD_ERROR_INVALID_ARGUMENT;
569 MEDIADEMUXER_FLEAVE();