Support avi file format
[platform/core/api/mediademuxer.git] / src / mediademuxer_port.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /**
18  * @file mediademuxer_port.c
19  * @brief general port based functions. sets specific function pointers
20  */
21
22 #include <string.h>
23 #include <mm_types.h>
24 #include <mm_message.h>
25 #include <mm_debug.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>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35
36 #define MAX_ERR_LEN 256
37
38 /* function type */
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);
46
47 /*
48   * Sequence of functions should be same as the port enumeration
49   * "port_mode" in mm_demuxer_ini.h file
50   */
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
56 };
57
58 int md_create(MMHandleType *demuxer)
59 {
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));
68
69         /* alloc ops structure */
70         pOps = (media_port_demuxer_ops *)g_malloc(sizeof(media_port_demuxer_ops));
71         MEDIADEMUXER_CHECK_NULL(pOps);
72
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);
77
78         new_demuxer->uri_src = NULL;
79         new_demuxer->uri_src_media_type = MEDIADEMUXER_SRC_INVALID;
80         /* load ini files */
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");
84
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();
91         return result;
92 ERROR:
93         *demuxer = (MMHandleType)0;
94         if (pOps)
95                 g_free(pOps);
96         if (new_demuxer)
97                 g_free(new_demuxer);
98         MEDIADEMUXER_FLEAVE();
99         return result;
100 }
101
102 int __md_util_exist_file_path(const char *file_path)
103 {
104         int fd = 0;
105         struct stat stat_results = { 0, };
106         MEDIADEMUXER_FENTER();
107
108         if (!file_path || !strlen(file_path))
109                 return MD_ERROR_FILE_NOT_FOUND;
110
111         fd = open(file_path, O_RDONLY);
112         if (fd < 0) {
113                 char buf[MAX_ERR_LEN];
114                 int ret_err = 0;
115                 ret_err = strerror_r(errno, buf, MAX_ERR_LEN);
116                 if (0 == ret_err)
117                         MD_E("failed to open file by %s (%d)\n", buf, errno);
118                 else
119                         MD_E("File not found, strerror_r() failed with errno (%d)\n", errno);
120                 MEDIADEMUXER_FLEAVE();
121                 return MD_ERROR_FILE_NOT_FOUND;
122         }
123
124         if (fstat(fd, &stat_results) < 0) {
125                 MD_E("failed to get file status\n");
126                 close(fd);
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");
131                 close(fd);
132                 MEDIADEMUXER_FLEAVE();
133                 return MD_ERROR_FILE_NOT_FOUND;
134         } else {
135                 MD_E("file size : %lld bytes\n", (long long)stat_results.st_size);
136         }
137         close(fd);
138         MEDIADEMUXER_FLEAVE();
139         return MD_ERROR_NONE;
140 }
141
142 bool __md_util_is_sdp_file(const char *path)
143 {
144         gboolean ret = FALSE;
145         gchar *uri = NULL;
146         MEDIADEMUXER_FENTER();
147         return_val_if_fail(path, FALSE);
148         uri = g_ascii_strdown(path, -1);
149         if (uri == NULL)
150                 return FALSE;
151         /* trimming */
152         g_strstrip(uri);
153         /* strlen(".sdp") == 4 */
154         if (strlen(uri) <= 4) {
155                 MD_W("path is too short.\n");
156                 return ret;
157         }
158         /* first, check extension name */
159         ret = g_str_has_suffix(uri, "sdp");
160         /* second, if no suffix is there, check it's contents */
161         if (!ret)
162                 /* FIXIT : do it soon */
163         g_free(uri);
164         uri = NULL;
165         MEDIADEMUXER_FLEAVE();
166         return ret;
167 }
168
169 mediademuxer_src_type __md_util_media_type(char **uri)
170 {
171         char *path = NULL;
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;
182                         } else {
183                                 return MEDIADEMUXER_SRC_FILE;
184                         }
185                         return MD_ERROR_NONE;
186                 } else {
187                         MD_E("could not access %s.\n", path);
188                         goto ERROR;
189                 }
190         } else if ((path = strstr(*uri, "rtsp://"))) {
191                 if (strlen(path)) {
192                         if ((path = strstr(*uri, "/wfd1.0/")))
193                                 return (MEDIADEMUXER_SRC_WFD);
194                         else
195                                 return (MEDIADEMUXER_SRC_RTSP);
196                 }
197         } else if ((path = strstr(*uri, "http://"))) {
198                 if (strlen(path)) {
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);
202                         } else {
203                                 return (MEDIADEMUXER_SRC_HTTP);
204                         }
205                 }
206         } else {
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));
217                         if (!new_uristr) {
218                                 free(old_uristr);
219                                 old_uristr = NULL;
220                                 return MD_ERROR_INVALID_ARGUMENT;
221                         }
222                         MD_L("reallocating uri[%p] to new_uristr[%p] \n", *uri, new_uristr);
223                         *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);
226                         free(old_uristr);
227                         old_uristr = NULL;
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);
231                         } else {
232                                 return (MEDIADEMUXER_SRC_FILE);
233                         }
234                 } else {
235                         goto ERROR;
236                 }
237         }
238         MEDIADEMUXER_FLEAVE();
239         return MD_ERROR_NONE;
240 ERROR:
241         MEDIADEMUXER_FLEAVE();
242         return MEDIADEMUXER_SRC_INVALID;
243 }
244
245 int _md_util_parse(MMHandleType demuxer, const char *type)
246 {
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;
264         }
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);
272         } else {
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);
276                 goto ERROR;
277         }
278         MEDIADEMUXER_FLEAVE();
279         return result;
280 ERROR:
281         result = MD_ERROR_INVALID_ARGUMENT;
282         MEDIADEMUXER_FLEAVE();
283         return result;
284 }
285
286 int md_set_data_source(MMHandleType demuxer, const char *uri)
287 {
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();
296         return result;
297 ERROR:
298         result = MD_ERROR_INVALID_ARGUMENT;
299         MEDIADEMUXER_FLEAVE();
300         return result;
301 }
302
303 int md_prepare(MMHandleType demuxer)
304 {
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();
316         return result;
317 ERROR:
318         result = MD_ERROR_INVALID_ARGUMENT;
319         MEDIADEMUXER_FLEAVE();
320         return result;
321 }
322
323 int md_get_track_count(MMHandleType demuxer, int *count)
324 {
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,
333                                                                         result, MD_ERROR,
334                                                                         "error while getting track count");
335         MEDIADEMUXER_FLEAVE();
336         return result;
337 ERROR:
338         result = MD_ERROR_INVALID_ARGUMENT;
339         MEDIADEMUXER_FLEAVE();
340         return result;
341 }
342
343 int md_select_track(MMHandleType demuxer, int track)
344 {
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();
355         return result;
356 ERROR:
357         result = MD_ERROR_INVALID_ARGUMENT;
358         MEDIADEMUXER_FLEAVE();
359         return result;
360 }
361
362 int md_start(MMHandleType demuxer)
363 {
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();
374         return result;
375 ERROR:
376         result = MD_ERROR_INVALID_ARGUMENT;
377         MEDIADEMUXER_FLEAVE();
378         return result;
379 }
380
381 int md_get_track_info(MMHandleType demuxer, int track, media_format_h *format)
382 {
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,
391                                                                         result, MD_ERROR,
392                                                                         "error while getting track count");
393         MEDIADEMUXER_FLEAVE();
394         return result;
395 ERROR:
396         result = MD_ERROR_INVALID_ARGUMENT;
397         MEDIADEMUXER_FLEAVE();
398         return result;
399 }
400
401 int md_read_sample(MMHandleType demuxer, int track_indx, media_packet_h *outbuf)
402 {
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();
412                 return result;
413         } else {
414                 MD_E("error while reading sample\n");
415                 goto ERROR;
416         }
417 ERROR:
418         result = MD_ERROR_INVALID_ARGUMENT;
419         MEDIADEMUXER_FLEAVE();
420         return result;
421 }
422
423 int md_seek(MMHandleType demuxer, int64_t pos)
424 {
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();
435         return result;
436 ERROR:
437         result = MD_ERROR_INVALID_ARGUMENT;
438         MEDIADEMUXER_FLEAVE();
439         return result;
440 }
441
442 int md_unselect_track(MMHandleType demuxer, int track)
443 {
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();
454         return result;
455 ERROR:
456         result = MD_ERROR_INVALID_ARGUMENT;
457         MEDIADEMUXER_FLEAVE();
458         return result;
459 }
460
461 int md_stop(MMHandleType demuxer)
462 {
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();
473         return result;
474 ERROR:
475         result = MD_ERROR_INVALID_ARGUMENT;
476         MEDIADEMUXER_FLEAVE();
477         return result;
478 }
479
480 int md_unprepare(MMHandleType demuxer)
481 {
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();
492         return result;
493 ERROR:
494         result = MD_ERROR_INVALID_ARGUMENT;
495         MEDIADEMUXER_FLEAVE();
496         return result;
497 }
498
499 int md_destroy(MMHandleType demuxer)
500 {
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");
510
511         /* free mediademuxer structure */
512         if (md_handle) {
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));
516                 }
517                 if (md_handle->uri_src) {
518                         MD_I("md_destroy deallocating md_handle->uri_src %p:\n",
519                                 md_handle->uri_src);
520                         g_free((void *)(md_handle->uri_src));
521                 }
522                 MD_I("md_destroy deallocating md_handle %p:\n", md_handle);
523                 g_free((void *)md_handle);
524                 md_handle = NULL;
525         }
526         MEDIADEMUXER_FLEAVE();
527         return result;
528
529 ERROR:
530         return result;
531 }
532
533 int md_set_error_cb(MMHandleType demuxer,
534                         mediademuxer_error_cb callback, void *user_data)
535 {
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();
546         return result;
547 ERROR:
548         result = MD_ERROR_INVALID_ARGUMENT;
549         MEDIADEMUXER_FLEAVE();
550         return result;
551 }
552
553 int md_set_eos_cb(MMHandleType demuxer,
554                         mediademuxer_eos_cb callback, void *user_data)
555 {
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();
566         return result;
567 ERROR:
568         result = MD_ERROR_INVALID_ARGUMENT;
569         MEDIADEMUXER_FLEAVE();
570         return result;
571 }