Support avi file format
[platform/core/api/mediademuxer.git] / src / mediademuxer.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 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <dlog.h>
21
22 #include <mediademuxer.h>
23 #include <mediademuxer_private.h>
24 #include <mediademuxer_port.h>
25
26 #ifndef USE_TASK_QUEUE
27 #define USE_TASK_QUEUE
28 #endif
29
30 /*
31 * Public Implementation
32 */
33 static gboolean _mediademuxer_error_cb(mediademuxer_error_e error, void *user_data);
34 static gboolean _mediademuxer_eos_cb(int track_num, void *user_data);
35
36 int mediademuxer_create(mediademuxer_h *demuxer)
37 {
38         MD_I("mediademuxer_create\n");
39         mediademuxer_error_e ret;
40         DEMUXER_INSTANCE_CHECK(demuxer);
41
42         mediademuxer_s *handle;
43         if (*demuxer == NULL) {
44                 handle = (mediademuxer_s *) g_malloc(sizeof(mediademuxer_s));
45                 if (handle != NULL) {
46                         memset(handle, 0, sizeof(mediademuxer_s));
47                         handle->demux_state = MEDIADEMUXER_STATE_NONE;
48                 } else {
49                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_OUT_OF_MEMORY(0x%08x)",
50                                 __FUNCTION__, MEDIADEMUXER_ERROR_OUT_OF_MEMORY);
51                         return MEDIADEMUXER_ERROR_OUT_OF_MEMORY;
52                 }
53         } else {
54                 MD_E("Already created the instance\n");
55                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
56         }
57
58         ret = md_create(&handle->md_handle);
59
60         if (ret != MEDIADEMUXER_ERROR_NONE) {
61                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
62                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
63                 free(handle);
64                 handle = NULL;
65                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
66         } else {
67                 *demuxer = (mediademuxer_h)handle;
68                 handle->is_stopped = false;
69                 MD_I("[CoreAPI][%s] new handle : %p", __FUNCTION__, *demuxer);
70         }
71         /* set callback */
72         md_set_error_cb(handle->md_handle,
73                         (mediademuxer_error_cb)_mediademuxer_error_cb, handle);
74         md_set_eos_cb(handle->md_handle,
75                         (mediademuxer_eos_cb)_mediademuxer_eos_cb, handle);
76
77         handle->demux_state = MEDIADEMUXER_STATE_IDLE;
78         return MEDIADEMUXER_ERROR_NONE;
79 }
80
81 int mediademuxer_set_data_source(mediademuxer_h demuxer, const char *path)
82 {
83         MD_I("mediademuxer_set_data_source\n");
84         mediademuxer_error_e ret = MEDIADEMUXER_ERROR_NONE;
85         DEMUXER_INSTANCE_CHECK(demuxer);
86         mediademuxer_s *handle;
87         handle = (mediademuxer_s *)demuxer;
88         if (handle && path && handle->demux_state == MEDIADEMUXER_STATE_IDLE) {
89                 ret = md_set_data_source((MMHandleType)handle->md_handle, path);
90                 if (ret != MEDIADEMUXER_ERROR_NONE) {
91                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)", __FUNCTION__,
92                                 MEDIADEMUXER_ERROR_INVALID_PATH);
93                         return MEDIADEMUXER_ERROR_INVALID_PATH;
94                 }
95         } else {
96                 if (!path) {
97                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
98                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_PATH);
99                         return MEDIADEMUXER_ERROR_INVALID_PATH;
100                 } else {
101                         if (handle->demux_state != MEDIADEMUXER_STATE_IDLE)
102                                 return MEDIADEMUXER_ERROR_INVALID_STATE;
103                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
104                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
105                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
106                 }
107         }
108         return ret;
109 }
110
111 int mediademuxer_prepare(mediademuxer_h demuxer)
112 {
113         MD_I("mediademuxer_prepare\n");
114         mediademuxer_error_e ret = MEDIADEMUXER_ERROR_NONE;
115         DEMUXER_INSTANCE_CHECK(demuxer);
116         mediademuxer_s *handle;
117         handle = (mediademuxer_s *)demuxer;
118         if (handle && handle->demux_state == MEDIADEMUXER_STATE_IDLE && handle->eos_cb != NULL) {
119                 ret = md_prepare((MMHandleType)handle->md_handle);
120                 if (ret != MEDIADEMUXER_ERROR_NONE) {
121                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
122                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
123                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
124                 } else {
125                         handle->demux_state = MEDIADEMUXER_STATE_READY;
126                 }
127         } else {
128                 if (handle->demux_state != MEDIADEMUXER_STATE_IDLE)
129                         return MEDIADEMUXER_ERROR_INVALID_STATE;
130                 if (handle->eos_cb == NULL)
131                         MD_E("EOS callback is not set\n");
132                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
133                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
134                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
135         }
136         return ret;
137 }
138
139 int mediademuxer_get_track_count(mediademuxer_h demuxer, int *count)
140 {
141         MD_I("mediademuxer_get_track_count\n");
142         mediademuxer_error_e ret;
143         DEMUXER_INSTANCE_CHECK(demuxer);
144         mediademuxer_s *handle;
145         handle = (mediademuxer_s *)demuxer;
146         if (handle && handle->demux_state == MEDIADEMUXER_STATE_READY) {
147                 ret = md_get_track_count((MMHandleType)handle->md_handle, count);
148                 if (ret != MEDIADEMUXER_ERROR_NONE) {
149                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
150                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
151                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
152                 }
153         } else {
154                 if (handle->demux_state != MEDIADEMUXER_STATE_READY)
155                         return MEDIADEMUXER_ERROR_INVALID_STATE;
156                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
157                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
158                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
159         }
160         return ret;
161 }
162
163 int mediademuxer_select_track(mediademuxer_h demuxer, int track_index)
164 {
165         MD_I("mediademuxer_select_track\n");
166         mediademuxer_error_e ret;
167         DEMUXER_INSTANCE_CHECK(demuxer);
168         mediademuxer_s *handle;
169         handle = (mediademuxer_s *)demuxer;
170         if (handle && handle->demux_state == MEDIADEMUXER_STATE_READY) {
171                 ret = md_select_track((MMHandleType)handle->md_handle, track_index);
172                 if (ret != MEDIADEMUXER_ERROR_NONE) {
173                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
174                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
175                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
176                 }
177         } else {
178                 if (handle->demux_state != MEDIADEMUXER_STATE_READY)
179                         return MEDIADEMUXER_ERROR_INVALID_STATE;
180                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
181                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
182                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
183         }
184         return ret;
185 }
186
187 int mediademuxer_start(mediademuxer_h demuxer)
188 {
189         MD_I("mediademuxer_start\n");
190         mediademuxer_error_e ret;
191         DEMUXER_INSTANCE_CHECK(demuxer);
192         mediademuxer_s *handle;
193         handle = (mediademuxer_s *)demuxer;
194         if (handle && handle->demux_state == MEDIADEMUXER_STATE_READY) {
195                 ret = md_start((MMHandleType)handle->md_handle);
196                 if (ret != MEDIADEMUXER_ERROR_NONE) {
197                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
198                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
199                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
200                 } else {
201                         handle->demux_state = MEDIADEMUXER_STATE_DEMUXING;
202                 }
203         } else {
204                 if (handle->demux_state != MEDIADEMUXER_STATE_READY)
205                         return MEDIADEMUXER_ERROR_INVALID_STATE;
206                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
207                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
208                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
209         }
210         return ret;
211 }
212
213 int mediademuxer_get_track_info(mediademuxer_h demuxer, int track_index,
214                                                         media_format_h *format)
215 {
216         MD_I("mediademuxer_get_track_info\n");
217         mediademuxer_error_e ret;
218         DEMUXER_INSTANCE_CHECK(demuxer);
219         mediademuxer_s *handle;
220         handle = (mediademuxer_s *)demuxer;
221         if (track_index < 0 || format == NULL) {
222                 MD_E("Invalid input parameters\n");
223                 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
224         }
225         if (handle && (handle->demux_state == MEDIADEMUXER_STATE_READY
226                 || handle->demux_state == MEDIADEMUXER_STATE_DEMUXING)) {
227                 ret = md_get_track_info((MMHandleType)handle->md_handle, track_index, format);
228                 if (ret != MEDIADEMUXER_ERROR_NONE) {
229                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
230                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
231                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
232                 }
233         } else {
234                 if (handle->demux_state != MEDIADEMUXER_STATE_READY)
235                         return MEDIADEMUXER_ERROR_INVALID_STATE;
236                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
237                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
238                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
239         }
240         return ret;
241 }
242
243 int mediademuxer_read_sample(mediademuxer_h demuxer, int track_index,
244                                                         media_packet_h *outbuf)
245 {
246         MD_I("mediademuxer_read_sample\n");
247         mediademuxer_error_e ret;
248         DEMUXER_INSTANCE_CHECK(demuxer);
249         mediademuxer_s *handle;
250         handle = (mediademuxer_s *)demuxer;
251         if (outbuf == NULL || track_index < 0)
252                 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
253         if (handle && handle->demux_state == MEDIADEMUXER_STATE_DEMUXING) {
254                 ret = md_read_sample((MMHandleType)handle->md_handle, track_index, outbuf);
255                 if (ret != MEDIADEMUXER_ERROR_NONE) {
256                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
257                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
258                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
259                 }
260         } else {
261                 if (handle->demux_state != MEDIADEMUXER_STATE_DEMUXING)
262                         return MEDIADEMUXER_ERROR_INVALID_STATE;
263                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
264                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
265                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
266         }
267         return ret;
268 }
269
270 int mediademuxer_seek(mediademuxer_h demuxer, int64_t pos)
271 {
272         MD_I("mediademuxer_seek\n");
273         mediademuxer_error_e ret;
274         DEMUXER_INSTANCE_CHECK(demuxer);
275         mediademuxer_s *handle;
276         handle = (mediademuxer_s *)demuxer;
277         if (handle && handle->demux_state == MEDIADEMUXER_STATE_DEMUXING) {
278                 ret = md_seek((MMHandleType)handle->md_handle, pos);
279                 if (ret != MEDIADEMUXER_ERROR_NONE) {
280                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
281                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
282                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
283                 }
284         } else {
285                 if (handle->demux_state != MEDIADEMUXER_STATE_DEMUXING)
286                         return MEDIADEMUXER_ERROR_INVALID_STATE;
287                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
288                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
289                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
290         }
291         return ret;
292 }
293
294 int mediademuxer_unselect_track(mediademuxer_h demuxer, int track_index)
295 {
296         MD_I("mediademuxer_unselect_track\n");
297         mediademuxer_error_e ret;
298         DEMUXER_INSTANCE_CHECK(demuxer);
299         mediademuxer_s *handle;
300         handle = (mediademuxer_s *)demuxer;
301         if (handle && (handle->demux_state == MEDIADEMUXER_STATE_READY
302                 || handle->demux_state == MEDIADEMUXER_STATE_DEMUXING)) {
303                 ret = md_unselect_track((MMHandleType)handle->md_handle, track_index);
304                 if (ret != MEDIADEMUXER_ERROR_NONE) {
305                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
306                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
307                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
308                 }
309         } else {
310                 if (handle->demux_state != MEDIADEMUXER_STATE_READY)
311                         return MEDIADEMUXER_ERROR_INVALID_STATE;
312                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
313                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
314                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
315         }
316         return ret;
317 }
318
319 int mediademuxer_stop(mediademuxer_h demuxer)
320 {
321         MD_I("mediademuxer_stop\n");
322         mediademuxer_error_e ret;
323         DEMUXER_INSTANCE_CHECK(demuxer);
324         mediademuxer_s *handle;
325         handle = (mediademuxer_s *)demuxer;
326         if (handle && handle->demux_state == MEDIADEMUXER_STATE_DEMUXING) {
327                 ret = md_stop((MMHandleType)handle->md_handle);
328                 if (ret != MEDIADEMUXER_ERROR_NONE) {
329                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
330                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
331                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
332                 } else
333                         handle->demux_state = MEDIADEMUXER_STATE_READY;
334         } else {
335                 if (handle->demux_state != MEDIADEMUXER_STATE_DEMUXING)
336                         return MEDIADEMUXER_ERROR_INVALID_STATE;
337                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
338                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
339                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
340         }
341         return ret;
342 }
343
344 int mediademuxer_unprepare(mediademuxer_h demuxer)
345 {
346         MD_I("mediademuxer_unprepare\n");
347         mediademuxer_error_e ret;
348         DEMUXER_INSTANCE_CHECK(demuxer);
349         mediademuxer_s *handle;
350         handle = (mediademuxer_s *)demuxer;
351         if (handle && handle->demux_state == MEDIADEMUXER_STATE_READY) {
352                 ret = md_unprepare((MMHandleType)handle->md_handle);
353                 if (ret != MEDIADEMUXER_ERROR_NONE) {
354                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
355                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
356                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
357                 } else
358                         handle->demux_state = MEDIADEMUXER_STATE_IDLE;
359         } else {
360                 if (handle->demux_state != MEDIADEMUXER_STATE_READY)
361                         return MEDIADEMUXER_ERROR_INVALID_STATE;
362                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
363                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
364                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
365         }
366         return ret;
367 }
368
369 int mediademuxer_destroy(mediademuxer_h demuxer)
370 {
371         MD_I("mediademuxer_destroy\n");
372         mediademuxer_error_e ret;
373         DEMUXER_INSTANCE_CHECK(demuxer);
374         mediademuxer_s *handle;
375         handle = (mediademuxer_s *)demuxer;
376         if (handle && handle->demux_state == MEDIADEMUXER_STATE_IDLE) {
377                 ret = md_destroy((MMHandleType)handle->md_handle);
378                 if (ret != MEDIADEMUXER_ERROR_NONE) {
379                         MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
380                                 __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
381                         return MEDIADEMUXER_ERROR_INVALID_OPERATION;
382                 } else {
383                         MD_E("[CoreAPI][%s] destroy handle : %p", __FUNCTION__, handle);
384                         handle->demux_state = MEDIADEMUXER_STATE_NONE;
385                         g_free(handle);
386                         handle = NULL;
387                 }
388         } else {
389                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
390                                  __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
391                 return MEDIADEMUXER_ERROR_INVALID_OPERATION;
392         }
393         return MEDIADEMUXER_ERROR_NONE;
394 }
395
396 int mediademuxer_get_state(mediademuxer_h demuxer, mediademuxer_state *state)
397 {
398         mediademuxer_error_e ret = MEDIADEMUXER_ERROR_NONE;
399         DEMUXER_INSTANCE_CHECK(demuxer);
400         mediademuxer_s *handle = (mediademuxer_s *)demuxer;
401         if (state != NULL) {
402                 *state = handle->demux_state;
403         } else {
404                 MD_E("[CoreAPI][%s] DEMUXER_ERROR_INVALID_OPERATION(0x%08x)",
405                         __FUNCTION__, MEDIADEMUXER_ERROR_INVALID_OPERATION);
406                 ret = MEDIADEMUXER_ERROR_INVALID_OPERATION;
407         }
408         return ret;
409 }
410
411 int mediademuxer_set_error_cb(mediademuxer_h demuxer,
412                         mediademuxer_error_cb callback, void *user_data)
413 {
414         DEMUXER_INSTANCE_CHECK(demuxer);
415         mediademuxer_s *handle;
416         handle = (mediademuxer_s *)demuxer;
417         if (handle->demux_state != MEDIADEMUXER_STATE_IDLE)
418                 return MEDIADEMUXER_ERROR_INVALID_STATE;
419         handle->error_cb = callback;
420         handle->error_cb_userdata = user_data;
421         MD_I("set error_cb(%p)", callback);
422         return MEDIADEMUXER_ERROR_NONE;
423 }
424
425 int mediademuxer_unset_error_cb(mediademuxer_h demuxer)
426 {
427         DEMUXER_INSTANCE_CHECK(demuxer);
428         mediademuxer_s *handle;
429         handle = (mediademuxer_s *)demuxer;
430         if (handle->demux_state != MEDIADEMUXER_STATE_IDLE)
431                 return MEDIADEMUXER_ERROR_INVALID_STATE;
432         handle->error_cb = NULL;
433         handle->error_cb_userdata = NULL;
434         MD_I("mediademuxer_unset_error_cb\n");
435         return MEDIADEMUXER_ERROR_NONE;
436 }
437
438 static gboolean _mediademuxer_error_cb(mediademuxer_error_e error, void *user_data)
439 {
440         if (user_data == NULL) {
441                 MD_I("_mediademuxer_error_cb: ERROR %d to report. But call back is not set\n", error);
442                 return 0;
443         }
444         mediademuxer_s * handle = (mediademuxer_s *)user_data;
445         if (handle->demux_state != MEDIADEMUXER_STATE_IDLE)
446                 return MEDIADEMUXER_ERROR_INVALID_STATE;
447         if (handle->error_cb)
448                 ((mediademuxer_error_cb)handle->error_cb)(error, handle->error_cb_userdata);
449         else
450                 MD_I("_mediademuxer_error_cb: ERROR %d to report. But call back is not set\n", error);
451         return 0;
452 }
453
454 int mediademuxer_set_eos_cb(mediademuxer_h demuxer,
455                         mediademuxer_eos_cb callback, void *user_data)
456 {
457         DEMUXER_INSTANCE_CHECK(demuxer);
458         mediademuxer_s *handle;
459         handle = (mediademuxer_s *)demuxer;
460         if (handle->demux_state != MEDIADEMUXER_STATE_IDLE)
461                 return MEDIADEMUXER_ERROR_INVALID_STATE;
462         handle->eos_cb = callback;
463         handle->eos_cb_userdata = user_data;
464         MD_I("set eos_cb(%p)", callback);
465         return MEDIADEMUXER_ERROR_NONE;
466 }
467
468 int mediademuxer_unset_eos_cb(mediademuxer_h demuxer)
469 {
470         DEMUXER_INSTANCE_CHECK(demuxer);
471         mediademuxer_s *handle;
472         handle = (mediademuxer_s *)demuxer;
473         if (handle->demux_state != MEDIADEMUXER_STATE_IDLE)
474                 return MEDIADEMUXER_ERROR_INVALID_STATE;
475         handle->eos_cb = NULL;
476         handle->eos_cb_userdata = NULL;
477         MD_I("mediademuxer_unset_eos_cb\n");
478         return MEDIADEMUXER_ERROR_NONE;
479 }
480
481 static gboolean _mediademuxer_eos_cb(int track_num, void *user_data)
482 {
483         if (user_data == NULL) {
484                 MD_I("_mediademuxer_eos_cb: EOS to report. But call back is not set\n");
485                 return 0;
486         }
487         mediademuxer_s *handle = (mediademuxer_s *)user_data;
488         if (handle->demux_state != MEDIADEMUXER_STATE_DEMUXING)
489                 return MEDIADEMUXER_ERROR_INVALID_STATE;
490         if (handle->eos_cb)
491                 ((mediademuxer_eos_cb)handle->eos_cb)(track_num, handle->eos_cb_userdata);
492         else
493                 MD_I("_mediademuxer_eos_cb: EOS %d to report. But call back is not set\n", track_num);
494         return 0;
495 }