Fixed for correct framerate setting
[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 #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;
183 #else
184                                 MD_L("uri is actually a file but it's sdp file. didn't support streaming uri");
185                                 return MEDIADEMUXER_SRC_INVALID;
186 #endif
187                         } else {
188                                 return MEDIADEMUXER_SRC_FILE;
189                         }
190                         return MD_ERROR_NONE;
191                 } else {
192                         MD_E("could not access %s.\n", path);
193                         goto ERROR;
194                 }
195 #ifdef TIZEN_FEATURE_STREAMING
196         } else if ((path = strstr(*uri, "rtsp://"))) {
197                 if (strlen(path)) {
198                         if ((path = strstr(*uri, "/wfd1.0/")))
199                                 return (MEDIADEMUXER_SRC_WFD);
200                         else
201                                 return (MEDIADEMUXER_SRC_RTSP);
202                 }
203         } else if ((path = strstr(*uri, "http://"))) {
204                 if (strlen(path)) {
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);
208                         } else {
209                                 return (MEDIADEMUXER_SRC_HTTP);
210                         }
211                 }
212 #endif
213         } else {
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));
224                         if (!new_uristr) {
225                                 free(old_uristr);
226                                 old_uristr = NULL;
227                                 return MD_ERROR_INVALID_ARGUMENT;
228                         }
229                         MD_L("reallocating uri[%p] to new_uristr[%p] \n", *uri, new_uristr);
230                         *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);
233                         free(old_uristr);
234                         old_uristr = NULL;
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;
239 #else
240                                 MD_L("uri is actually a file but it's sdp file. didn't support streaming uri");
241                                 return MEDIADEMUXER_SRC_INVALID;
242 #endif
243                         } else {
244                                 return (MEDIADEMUXER_SRC_FILE);
245                         }
246                 } else {
247                         goto ERROR;
248                 }
249         }
250         MEDIADEMUXER_FLEAVE();
251         return MD_ERROR_NONE;
252 ERROR:
253         MEDIADEMUXER_FLEAVE();
254         return MEDIADEMUXER_SRC_INVALID;
255 }
256
257 int _md_util_parse(MMHandleType demuxer, const char *type)
258 {
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;
276         }
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);
284         } else {
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);
288                 goto ERROR;
289         }
290         MEDIADEMUXER_FLEAVE();
291         return result;
292 ERROR:
293         result = MD_ERROR_INVALID_ARGUMENT;
294         MEDIADEMUXER_FLEAVE();
295         return result;
296 }
297
298 int md_set_data_source(MMHandleType demuxer, const char *uri)
299 {
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();
308         return result;
309 ERROR:
310         result = MD_ERROR_INVALID_ARGUMENT;
311         MEDIADEMUXER_FLEAVE();
312         return result;
313 }
314
315 int md_prepare(MMHandleType demuxer)
316 {
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();
328         return result;
329 ERROR:
330         result = MD_ERROR_INVALID_ARGUMENT;
331         MEDIADEMUXER_FLEAVE();
332         return result;
333 }
334
335 int md_get_track_count(MMHandleType demuxer, int *count)
336 {
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,
345                                                                         result, MD_ERROR,
346                                                                         "error while getting track count");
347         MEDIADEMUXER_FLEAVE();
348         return result;
349 ERROR:
350         result = MD_ERROR_INVALID_ARGUMENT;
351         MEDIADEMUXER_FLEAVE();
352         return result;
353 }
354
355 int md_select_track(MMHandleType demuxer, int track)
356 {
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();
367         return result;
368 ERROR:
369         result = MD_ERROR_INVALID_ARGUMENT;
370         MEDIADEMUXER_FLEAVE();
371         return result;
372 }
373
374 int md_start(MMHandleType demuxer)
375 {
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();
386         return result;
387 ERROR:
388         result = MD_ERROR_INVALID_ARGUMENT;
389         MEDIADEMUXER_FLEAVE();
390         return result;
391 }
392
393 int md_get_track_info(MMHandleType demuxer, int track, media_format_h *format)
394 {
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,
403                                                                         result, MD_ERROR,
404                                                                         "error while getting track count");
405         MEDIADEMUXER_FLEAVE();
406         return result;
407 ERROR:
408         result = MD_ERROR_INVALID_ARGUMENT;
409         MEDIADEMUXER_FLEAVE();
410         return result;
411 }
412
413 int md_read_sample(MMHandleType demuxer, int track_indx, media_packet_h *outbuf)
414 {
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();
424                 return result;
425         } else {
426                 MD_E("error while reading sample\n");
427                 goto ERROR;
428         }
429 ERROR:
430         result = MD_ERROR_INVALID_ARGUMENT;
431         MEDIADEMUXER_FLEAVE();
432         return result;
433 }
434
435 int md_seek(MMHandleType demuxer, int64_t pos)
436 {
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();
447         return result;
448 ERROR:
449         result = MD_ERROR_INVALID_ARGUMENT;
450         MEDIADEMUXER_FLEAVE();
451         return result;
452 }
453
454 int md_unselect_track(MMHandleType demuxer, int track)
455 {
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();
466         return result;
467 ERROR:
468         result = MD_ERROR_INVALID_ARGUMENT;
469         MEDIADEMUXER_FLEAVE();
470         return result;
471 }
472
473 int md_stop(MMHandleType demuxer)
474 {
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();
485         return result;
486 ERROR:
487         result = MD_ERROR_INVALID_ARGUMENT;
488         MEDIADEMUXER_FLEAVE();
489         return result;
490 }
491
492 int md_unprepare(MMHandleType demuxer)
493 {
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();
504         return result;
505 ERROR:
506         result = MD_ERROR_INVALID_ARGUMENT;
507         MEDIADEMUXER_FLEAVE();
508         return result;
509 }
510
511 int md_destroy(MMHandleType demuxer)
512 {
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");
522
523         /* free mediademuxer structure */
524         if (md_handle) {
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));
528                 }
529                 if (md_handle->uri_src) {
530                         MD_I("md_destroy deallocating md_handle->uri_src %p:\n",
531                                 md_handle->uri_src);
532                         g_free((void *)(md_handle->uri_src));
533                 }
534                 MD_I("md_destroy deallocating md_handle %p:\n", md_handle);
535                 g_free((void *)md_handle);
536                 md_handle = NULL;
537         }
538         MEDIADEMUXER_FLEAVE();
539         return result;
540
541 ERROR:
542         return result;
543 }
544
545 int md_set_error_cb(MMHandleType demuxer,
546                         mediademuxer_error_cb callback, void *user_data)
547 {
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();
558         return result;
559 ERROR:
560         result = MD_ERROR_INVALID_ARGUMENT;
561         MEDIADEMUXER_FLEAVE();
562         return result;
563 }
564
565 int md_set_eos_cb(MMHandleType demuxer,
566                         mediademuxer_eos_cb callback, void *user_data)
567 {
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();
578         return result;
579 ERROR:
580         result = MD_ERROR_INVALID_ARGUMENT;
581         MEDIADEMUXER_FLEAVE();
582         return result;
583 }