fixed coverity issues
[platform/core/api/mediacodec.git] / src / media_codec.c
1 /*
2  * Copyright (c) 2011 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 <media_codec.h>
21 #include <media_codec_private.h>
22 #include <media_codec_port.h>
23 #include <system_info.h>
24
25 #include <dlog.h>
26
27 #define MC_PREALLOCATED_HANDLE_ARRAY_SIZE 16
28
29 static mm_resource_manager_h resource_manager;
30 static GPtrArray *mediacodec_handles;
31 static GMutex mediacodec_handles_lock;
32
33 static gboolean  __mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data);
34 static gboolean __mediacodec_fill_buffer_cb(media_packet_h pkt, void *user_data);
35 static gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data);
36 static gboolean __mediacodec_eos_cb(void *user_data);
37 static gboolean __mediacodec_supported_codec_cb(mediacodec_codec_type_e codec_type, void *user_data);
38 static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void *user_data);
39 static void __mediacodec_init_lib() __attribute__((constructor));
40 static void __mediacodec_deinit_lib() __attribute__((destructor));
41 static int __mediacodec_resource_release_cb(mm_resource_manager_h rm,
42                 mm_resource_manager_res_h resource_h, void *user_data);
43
44 /*
45  * Internal Implementation
46  */
47 int __convert_error_code(int code, char *func_name)
48 {
49         int ret = MEDIACODEC_ERROR_INVALID_OPERATION;
50         char *msg = "MEDIACOODEC_INVALID_OPERATION";
51
52         switch (code) {
53         case MC_ERROR_NONE:
54                 ret = MEDIACODEC_ERROR_NONE;
55                 msg = "MEDIACODEC_ERROR_NONE";
56                 break;
57         case MC_PARAM_ERROR:
58         case MC_INVALID_ARG:
59                 ret = MEDIACODEC_ERROR_INVALID_PARAMETER;
60                 msg = "MEDIACODEC_ERROR_INVALID_PARAMETER";
61                 break;
62         case MC_PERMISSION_DENIED:
63                 ret = MEDIACODEC_ERROR_PERMISSION_DENIED;
64                 msg = "MEDIACODEC_ERROR_PERMISSION_DENIED";
65                 break;
66         case MC_INVALID_STATUS:
67                 ret = MEDIACODEC_ERROR_INVALID_STATE;
68                 msg = "MEDIACODEC_ERROR_INVALID_STATE";
69                 break;
70         case MC_NOT_SUPPORTED:
71                 ret = MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE;
72                 msg = "MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE";
73                 break;
74         case MC_ERROR:
75         case MC_INTERNAL_ERROR:
76         case MC_HW_ERROR:
77                 ret = MEDIACODEC_ERROR_INVALID_OPERATION;
78                 msg = "MEDIACODEC_ERROR_INVALID_OPERATION";
79                 break;
80         case MC_INVALID_STREAM:
81                 ret = MEDIACODEC_ERROR_INVALID_STREAM;
82                 msg = "MEDIACODEC_ERROR_INVALID_STREAM";
83                 break;
84         case MC_CODEC_NOT_FOUND:
85                 ret = MEDIACODEC_ERROR_CODEC_NOT_FOUND;
86                 msg = "MEDIACODEC_ERROR_CODEC_NOT_FOUND";
87                 break;
88         case MC_ERROR_DECODE:
89                 ret = MEDIACODEC_ERROR_DECODE;
90                 msg = "MEDIACODEC_ERROR_DECODE";
91                 break;
92         case MC_INVALID_IN_BUF:
93                 ret = MEDIACODEC_ERROR_INVALID_INBUFFER;
94                 msg = "MEDIACODEC_ERROR_INVALID_INBUFFER";
95                 break;
96         case MC_INVALID_OUT_BUF:
97                 ret = MEDIACODEC_ERROR_INVALID_OUTBUFFER;
98                 msg = "MEDIACODEC_ERROR_INVALID_OUTBUFFER";
99                 break;
100         case MC_NOT_INITIALIZED:
101                 ret = MEDIACODEC_ERROR_NOT_INITIALIZED;
102                 msg = "MEDIACODEC_ERROR_NOT_INITIALIZED";
103                 break;
104         case MC_OUTPUT_BUFFER_EMPTY:
105         case MC_OUTPUT_BUFFER_OVERFLOW:
106                 ret = MEDIACODEC_ERROR_BUFFER_NOT_AVAILABLE;
107                 msg = "MEDIACODEC_ERROR_BUFFER_NOT_AVAILABLE";
108                 break;
109         case MC_OUT_OF_MEMORY:
110                 ret = MEDIACODEC_ERROR_OUT_OF_MEMORY;
111                 msg = "MEDIACODEC_ERROR_OUT_OF_MEMORY";
112                 break;
113         default:
114                 ret = MEDIACODEC_ERROR_INTERNAL;
115                 msg = "MEDIACODEC_ERROR_INTERNAL";
116                 break;
117         }
118         LOGD("[%s] %s(0x%08x) : core fw error(0x%x)", func_name, msg, ret, code);
119         return ret;
120 }
121
122 /*
123  *  Public Implementation
124  */
125
126 int mediacodec_create(mediacodec_h *mediacodec)
127 {
128         MEDIACODEC_INSTANCE_CHECK(mediacodec);
129         mediacodec_s *handle;
130         int ret;
131
132         LOGD("mediacodec_create..");
133
134         if (resource_manager == NULL)
135                 return MEDIACODEC_ERROR_INTERNAL;
136
137         handle = (mediacodec_s *)malloc(sizeof(mediacodec_s));
138         if (handle != NULL) {
139                 memset(handle, 0 , sizeof(mediacodec_s));
140         } else {
141                 LOGE("MEDIACODEC_ERROR_OUT_OF_MEMORY(0x%08x)", MEDIACODEC_ERROR_OUT_OF_MEMORY);
142                 return MEDIACODEC_ERROR_OUT_OF_MEMORY;
143         }
144
145         ret = mc_create(&handle->mc_handle);
146         if (ret != MEDIACODEC_ERROR_NONE) {
147                 LOGE("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION);
148                 handle->state = MEDIACODEC_STATE_NONE;
149                 g_free(handle->mc_handle);
150                 g_free(handle);
151                 handle = NULL;
152                 return MEDIACODEC_ERROR_INVALID_OPERATION;
153         } else {
154                 *mediacodec = (mediacodec_h)handle;
155                 handle->state = MEDIACODEC_STATE_IDLE;
156                 LOGD("new handle : %p", *mediacodec);
157         }
158
159         /* set callback */
160         mc_set_empty_buffer_cb(handle->mc_handle, (mediacodec_input_buffer_used_cb)__mediacodec_empty_buffer_cb, handle);
161         mc_set_fill_buffer_cb(handle->mc_handle, (mediacodec_output_buffer_available_cb)__mediacodec_fill_buffer_cb, handle);
162         mc_set_error_cb(handle->mc_handle, (mediacodec_error_cb)__mediacodec_error_cb, handle);
163         mc_set_eos_cb(handle->mc_handle, (mediacodec_eos_cb)__mediacodec_eos_cb, handle);
164         mc_set_buffer_status_cb(handle->mc_handle, (mediacodec_buffer_status_cb)__mediacodec_buffer_status_cb, handle);
165         mc_set_supported_codec_cb(handle->mc_handle, (mediacodec_supported_codec_cb)__mediacodec_supported_codec_cb, handle);
166
167         g_mutex_lock(&mediacodec_handles_lock);
168         g_ptr_array_insert(mediacodec_handles, -1, *mediacodec);
169         g_mutex_unlock(&mediacodec_handles_lock);
170
171         return MEDIACODEC_ERROR_NONE;
172
173 }
174
175 int mediacodec_destroy(mediacodec_h mediacodec)
176 {
177         LOGD("[%s] Start, handle to destroy : %p", __FUNCTION__, mediacodec);
178         MEDIACODEC_INSTANCE_CHECK(mediacodec);
179         mediacodec_s *handle = (mediacodec_s *)mediacodec;
180
181         int ret = mc_destroy(handle->mc_handle);
182         if (ret != MEDIACODEC_ERROR_NONE) {
183                 LOGD("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION);
184                 return MEDIACODEC_ERROR_INVALID_OPERATION;
185         } else {
186                 g_mutex_lock(&mediacodec_handles_lock);
187                 g_ptr_array_remove_fast(mediacodec_handles, mediacodec);
188                 g_mutex_unlock(&mediacodec_handles_lock);
189
190                 handle->state = MEDIACODEC_STATE_NONE;
191                 free(handle);
192                 handle = NULL;
193                 return MEDIACODEC_ERROR_NONE;
194         }
195 }
196
197 int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_id, int flags)
198 {
199         MEDIACODEC_INSTANCE_CHECK(mediacodec);
200         mediacodec_s *handle = (mediacodec_s *)mediacodec;
201         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
202
203         int ret = mc_set_codec(handle->mc_handle, codec_id, flags);
204
205         if (ret != MEDIACODEC_ERROR_NONE) {
206                 return __convert_error_code(ret, (char *)__FUNCTION__);
207         } else {
208                 handle->state = MEDIACODEC_STATE_IDLE;
209                 return MEDIACODEC_ERROR_NONE;
210         }
211 }
212
213 int mediacodec_set_vdec_info(mediacodec_h mediacodec, int width, int height)
214 {
215         MEDIACODEC_INSTANCE_CHECK(mediacodec);
216         mediacodec_s *handle = (mediacodec_s *)mediacodec;
217         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
218
219         int ret = mc_set_vdec_info(handle->mc_handle, width, height);
220
221         if (ret != MEDIACODEC_ERROR_NONE) {
222                 return __convert_error_code(ret, (char *)__FUNCTION__);
223         } else {
224                 handle->state = MEDIACODEC_STATE_IDLE;
225                 return MEDIACODEC_ERROR_NONE;
226         }
227 }
228
229 int mediacodec_set_venc_info(mediacodec_h mediacodec, int width, int height, int fps, int target_bits)
230 {
231         MEDIACODEC_INSTANCE_CHECK(mediacodec);
232         mediacodec_s *handle = (mediacodec_s *)mediacodec;
233         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
234
235         int ret = mc_set_venc_info(handle->mc_handle, width, height, fps, target_bits);
236
237         if (ret != MEDIACODEC_ERROR_NONE) {
238                 return __convert_error_code(ret, (char *)__FUNCTION__);
239         } else {
240                 handle->state = MEDIACODEC_STATE_IDLE;
241                 return MEDIACODEC_ERROR_NONE;
242         }
243 }
244
245 int mediacodec_set_adec_info(mediacodec_h mediacodec, int samplerate, int channel, int bit)
246 {
247         MEDIACODEC_INSTANCE_CHECK(mediacodec);
248         mediacodec_s *handle = (mediacodec_s *)mediacodec;
249         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
250
251         int ret = mc_set_adec_info(handle->mc_handle, samplerate, channel, bit);
252
253         if (ret != MEDIACODEC_ERROR_NONE) {
254                 return __convert_error_code(ret, (char *)__FUNCTION__);
255         } else {
256                 handle->state = MEDIACODEC_STATE_IDLE;
257                 return MEDIACODEC_ERROR_NONE;
258         }
259 }
260
261 int mediacodec_set_aenc_info(mediacodec_h mediacodec, int samplerate, int channel, int bit, int bitrate)
262 {
263         MEDIACODEC_INSTANCE_CHECK(mediacodec);
264         mediacodec_s *handle = (mediacodec_s *)mediacodec;
265         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
266
267         int ret = mc_set_aenc_info(handle->mc_handle, samplerate, channel, bit, bitrate);
268
269         if (ret != MEDIACODEC_ERROR_NONE) {
270                 return __convert_error_code(ret, (char *)__FUNCTION__);
271         } else {
272                 handle->state = MEDIACODEC_STATE_IDLE;
273                 return MEDIACODEC_ERROR_NONE;
274         }
275 }
276
277 int mediacodec_configure_from_media_format(mediacodec_h mediacodec, media_format_h format, int flags)
278 {
279         MEDIACODEC_INSTANCE_CHECK(mediacodec);
280         mediacodec_s *handle = (mediacodec_s *)mediacodec;
281         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
282
283         int ret = mc_configure(handle->mc_handle, format, flags);
284
285         if (ret != MEDIACODEC_ERROR_NONE) {
286                 return __convert_error_code(ret, (char *)__FUNCTION__);
287         } else {
288                 handle->state = MEDIACODEC_STATE_IDLE;
289                 return MEDIACODEC_ERROR_NONE;
290         }
291 }
292
293 int mediacodec_prepare(mediacodec_h mediacodec)
294 {
295         MEDIACODEC_INSTANCE_CHECK(mediacodec);
296         mediacodec_s *handle = (mediacodec_s *)mediacodec;
297         mc_handle_t *mc_handle = (mc_handle_t *) handle->mc_handle;
298         int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
299         mm_resource_manager_res_h resource;
300         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
301
302         if (mc_handle->is_hw && mc_handle->is_video) {
303
304                 if (handle->codec_resource) {
305                         LOGE("Codec resource is tried to be acquired twice\n");
306                         return MC_INTERNAL_ERROR;
307                 }
308
309                 /*
310                  * TODO
311                  * Currently volume of requested resource is set to 1. Default
312                  * capacity for video encoder/decoder is 1 too. The actual capacity
313                  * should be set in mmfw-sysconf > mmfw_resource_manager.ini.
314                  * If different encode/decode operation needs different volume of
315                  * video encoder/decoder, '1' in the following
316                  * mm_resource_manager_mark_for_acquire function should be set to
317                  * corresponding value.
318                  * If that value depends on platform where it's executed,
319                  * MM_RESOURCE_MANAGER_RES_TYPE_COND_* and
320                  * mm_resource_manager_get_res_type_volume() can be used.
321                  * Additional info can be found in doxygen comments of mm_resource_manager.h
322                  */
323                 rm_ret = mm_resource_manager_mark_for_acquire(resource_manager,
324                                 mc_handle->is_encoder ?
325                                 MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_ENCODER :
326                                 MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER,
327                                 1, &resource);
328                 if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE)
329                         switch (rm_ret) {
330                         case MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED:
331                                 return MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE;
332                         case MM_RESOURCE_MANAGER_ERROR_NOT_ENOUGH:
333                                 return MEDIACODEC_ERROR_RESOURCE_OVERLOADED;
334                         default:
335                                 return MEDIACODEC_ERROR_INTERNAL;
336                         }
337
338                 rm_ret = mm_resource_manager_commit(resource_manager);
339                 if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
340                         mm_resource_manager_mark_for_release(resource_manager, resource);
341                         switch (rm_ret) {
342                         case MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY:
343                                 return MEDIACODEC_ERROR_RESOURCE_OVERLOADED;
344                         default:
345                                 return MEDIACODEC_ERROR_INTERNAL;
346                         }
347                 }
348
349                 handle->codec_resource = resource;
350         }
351
352         int ret = mc_prepare(handle->mc_handle);
353
354         if (ret != MEDIACODEC_ERROR_NONE) {
355                 return __convert_error_code(ret, (char *)__FUNCTION__);
356         } else {
357                 handle->state = MEDIACODEC_STATE_READY;
358                 return MEDIACODEC_ERROR_NONE;
359         }
360 }
361
362 int mediacodec_unprepare(mediacodec_h mediacodec)
363 {
364         MEDIACODEC_INSTANCE_CHECK(mediacodec);
365         mediacodec_s *handle = (mediacodec_s *)mediacodec;
366         int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE;
367
368         int ret = mc_unprepare(handle->mc_handle);
369
370         if (ret != MEDIACODEC_ERROR_NONE) {
371                 return __convert_error_code(ret, (char *)__FUNCTION__);
372         } else {
373                 if (handle->codec_resource != NULL) {
374                         mm_resource_manager_mark_for_release(resource_manager,
375                                         handle->codec_resource);
376                         handle->codec_resource = NULL;
377                         rm_ret = mm_resource_manager_commit(resource_manager);
378                         if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) {
379                                 mm_resource_manager_mark_for_release(resource_manager, resource);
380                                 switch (rm_ret) {
381                                 case MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY:
382                                         return MEDIACODEC_ERROR_RESOURCE_OVERLOADED;
383                                 default:
384                                         return MEDIACODEC_ERROR_INTERNAL;
385                                 }
386                         }
387                 } else {
388                         LOGD("No codec resource to release. Probably resource release cb called\n");
389                 }
390
391                 handle->state = MEDIACODEC_STATE_IDLE;
392                 return MEDIACODEC_ERROR_NONE;
393         }
394 }
395
396 int mediacodec_process_input(mediacodec_h mediacodec, media_packet_h inbuf, uint64_t timeOutUs)
397 {
398         MEDIACODEC_INSTANCE_CHECK(mediacodec);
399         mediacodec_s *handle = (mediacodec_s *)mediacodec;
400         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_READY);
401
402         int ret = mc_process_input(handle->mc_handle, inbuf, timeOutUs);
403
404         if (ret != MEDIACODEC_ERROR_NONE)
405                 return __convert_error_code(ret, (char *)__FUNCTION__);
406         else
407                 return MEDIACODEC_ERROR_NONE;
408 }
409
410 int mediacodec_get_output(mediacodec_h mediacodec, media_packet_h *outbuf, uint64_t timeOutUs)
411 {
412         MEDIACODEC_INSTANCE_CHECK(mediacodec);
413         mediacodec_s *handle = (mediacodec_s *)mediacodec;
414         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_READY);
415
416         int ret = mc_get_output(handle->mc_handle, outbuf, timeOutUs);
417
418         if (ret != MEDIACODEC_ERROR_NONE)
419                 return __convert_error_code(ret, (char *)__FUNCTION__);
420         else
421                 return MEDIACODEC_ERROR_NONE;
422 }
423
424 int mediacodec_flush_buffers(mediacodec_h mediacodec)
425 {
426         MEDIACODEC_INSTANCE_CHECK(mediacodec);
427         mediacodec_s *handle = (mediacodec_s *)mediacodec;
428
429         int ret = mc_flush_buffers(handle->mc_handle);
430
431         if (ret != MEDIACODEC_ERROR_NONE)
432                 return __convert_error_code(ret, (char *)__FUNCTION__);
433         else
434                 return MEDIACODEC_ERROR_NONE;
435 }
436
437 int mediacodec_get_supported_type(mediacodec_h mediacodec, mediacodec_codec_type_e codec_type, bool encoder, int *support_type)
438 {
439         MEDIACODEC_INSTANCE_CHECK(mediacodec);
440         mediacodec_s *handle = (mediacodec_s *)mediacodec;
441         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
442
443         int ret = mc_get_supported_type(handle->mc_handle, codec_type, encoder, support_type);
444
445         if (ret != MEDIACODEC_ERROR_NONE)
446                 return __convert_error_code(ret, (char *)__FUNCTION__);
447         else
448                 handle->state = MEDIACODEC_STATE_IDLE;
449
450         return MEDIACODEC_ERROR_NONE;
451 }
452
453 int mediacodec_set_input_buffer_used_cb(mediacodec_h mediacodec, mediacodec_input_buffer_used_cb callback, void *user_data)
454 {
455         MEDIACODEC_INSTANCE_CHECK(mediacodec);
456         mediacodec_s *handle = (mediacodec_s *)mediacodec;
457         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
458
459         handle->empty_buffer_cb = callback;
460         handle->empty_buffer_cb_userdata = user_data;
461
462         LOGD("set empty_buffer_cb(%p)", callback);
463
464         return MEDIACODEC_ERROR_NONE;
465 }
466
467 int mediacodec_unset_input_buffer_used_cb(mediacodec_h mediacodec)
468 {
469         MEDIACODEC_INSTANCE_CHECK(mediacodec);
470         mediacodec_s *handle = (mediacodec_s *)mediacodec;
471
472         handle->empty_buffer_cb = NULL;
473         handle->empty_buffer_cb_userdata = NULL;
474
475         return MEDIACODEC_ERROR_NONE;
476 }
477
478
479 int mediacodec_set_output_buffer_available_cb(mediacodec_h mediacodec, mediacodec_output_buffer_available_cb callback, void *user_data)
480 {
481         MEDIACODEC_INSTANCE_CHECK(mediacodec);
482         mediacodec_s *handle = (mediacodec_s *)mediacodec;
483         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
484
485         handle->fill_buffer_cb = callback;
486         handle->fill_buffer_cb_userdata = user_data;
487
488         LOGD("set fill_buffer_cb(%p)", callback);
489
490         return MEDIACODEC_ERROR_NONE;
491
492 }
493
494 int mediacodec_unset_output_buffer_available_cb(mediacodec_h mediacodec)
495 {
496         MEDIACODEC_INSTANCE_CHECK(mediacodec);
497         mediacodec_s *handle = (mediacodec_s *)mediacodec;
498
499         handle->fill_buffer_cb = NULL;
500         handle->fill_buffer_cb_userdata = NULL;
501
502         return MEDIACODEC_ERROR_NONE;
503 }
504
505 int mediacodec_set_error_cb(mediacodec_h mediacodec, mediacodec_error_cb callback, void *user_data)
506 {
507         MEDIACODEC_INSTANCE_CHECK(mediacodec);
508         mediacodec_s *handle = (mediacodec_s *)mediacodec;
509         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
510
511         handle->error_cb = callback;
512         handle->error_cb_userdata = user_data;
513
514         LOGD("set error_cb(%p)", callback);
515
516         return MEDIACODEC_ERROR_NONE;
517
518 }
519
520 int mediacodec_unset_error_cb(mediacodec_h mediacodec)
521 {
522         MEDIACODEC_INSTANCE_CHECK(mediacodec);
523         mediacodec_s *handle = (mediacodec_s *)mediacodec;
524
525         handle->error_cb = NULL;
526         handle->error_cb_userdata = NULL;
527
528         return MEDIACODEC_ERROR_NONE;
529 }
530
531 int mediacodec_set_eos_cb(mediacodec_h mediacodec, mediacodec_eos_cb callback, void *user_data)
532 {
533         MEDIACODEC_INSTANCE_CHECK(mediacodec);
534         mediacodec_s *handle = (mediacodec_s *)mediacodec;
535         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
536
537         handle->eos_cb = callback;
538         handle->eos_cb_userdata = user_data;
539
540         LOGD("set eos_cb(%p)", callback);
541
542         return MEDIACODEC_ERROR_NONE;
543
544 }
545
546 int mediacodec_unset_eos_cb(mediacodec_h mediacodec)
547 {
548         MEDIACODEC_INSTANCE_CHECK(mediacodec);
549         mediacodec_s *handle = (mediacodec_s *)mediacodec;
550
551         handle->eos_cb = NULL;
552         handle->eos_cb_userdata = NULL;
553
554         return MEDIACODEC_ERROR_NONE;
555 }
556
557 int mediacodec_set_buffer_status_cb(mediacodec_h mediacodec, mediacodec_buffer_status_cb callback, void *user_data)
558 {
559         MEDIACODEC_INSTANCE_CHECK(mediacodec);
560         mediacodec_s *handle = (mediacodec_s *)mediacodec;
561         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
562
563         handle->buffer_status_cb = callback;
564         handle->buffer_status_cb_userdata = user_data;
565
566         LOGD("set buffer_status_cb(%p)", callback);
567
568         return MEDIACODEC_ERROR_NONE;
569
570 }
571
572 int mediacodec_unset_buffer_status_cb(mediacodec_h mediacodec)
573 {
574         MEDIACODEC_INSTANCE_CHECK(mediacodec);
575         mediacodec_s *handle = (mediacodec_s *)mediacodec;
576
577         handle->buffer_status_cb = NULL;
578         handle->buffer_status_cb_userdata = NULL;
579
580         return MEDIACODEC_ERROR_NONE;
581 }
582
583 int mediacodec_foreach_supported_codec(mediacodec_h mediacodec, mediacodec_supported_codec_cb callback, void *user_data)
584 {
585         MEDIACODEC_INSTANCE_CHECK(mediacodec);
586         mediacodec_s *handle = (mediacodec_s *)mediacodec;
587
588         handle->supported_codec_cb = callback;
589         handle->supported_codec_cb_userdata = user_data;
590
591         LOGD("set supported_codec_cb(%p)", callback);
592         int ret = _mediacodec_foreach_supported_codec(callback, handle);
593
594         if (ret != MEDIACODEC_ERROR_NONE)
595                 return __convert_error_code(ret, (char *)__FUNCTION__);
596         else
597                 return MEDIACODEC_ERROR_NONE;
598
599         return MEDIACODEC_ERROR_NONE;
600
601 }
602
603 int mediacodec_get_packet_pool(mediacodec_h mediacodec, media_packet_pool_h *pkt_pool)
604 {
605         MEDIACODEC_INSTANCE_CHECK(mediacodec);
606         mediacodec_s *handle = (mediacodec_s *)mediacodec;
607         MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_READY);
608         int ret = mc_get_packet_pool(handle->mc_handle, pkt_pool);
609
610         if (ret != MEDIACODEC_ERROR_NONE)
611                 return MEDIACODEC_ERROR_INVALID_OPERATION;
612         else
613                 return MEDIACODEC_ERROR_NONE;
614 }
615
616 static gboolean __mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data)
617 {
618         if (user_data == NULL || pkt == NULL)
619                 return 0;
620
621         mediacodec_s *handle = (mediacodec_s *)user_data;
622
623         if (handle->empty_buffer_cb)
624                 ((mediacodec_input_buffer_used_cb)handle->empty_buffer_cb)(pkt, handle->empty_buffer_cb_userdata);
625
626         return 1;
627 }
628
629 static gboolean  __mediacodec_fill_buffer_cb(media_packet_h pkt, void *user_data)
630 {
631         if (user_data == NULL || pkt == NULL)
632                 return 0;
633
634         mediacodec_s *handle = (mediacodec_s *)user_data;
635
636         if (handle->fill_buffer_cb)
637                 ((mediacodec_output_buffer_available_cb)handle->fill_buffer_cb)(pkt, handle->fill_buffer_cb_userdata);
638
639         return 1;
640 }
641
642 static gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data)
643 {
644         if (user_data == NULL)
645                 return 0;
646
647         mediacodec_s *handle = (mediacodec_s *)user_data;
648
649         if (handle->error_cb)
650                 ((mediacodec_error_cb)handle->error_cb)(error, handle->error_cb_userdata);
651
652         return 1;
653 }
654
655 static gboolean __mediacodec_eos_cb(void *user_data)
656 {
657         if (user_data == NULL)
658                 return 0;
659
660         mediacodec_s *handle = (mediacodec_s *)user_data;
661
662         if (handle->eos_cb)
663                 ((mediacodec_eos_cb)handle->eos_cb)(handle->eos_cb_userdata);
664
665         return 1;
666 }
667
668 static gboolean __mediacodec_supported_codec_cb(mediacodec_codec_type_e codec_type, void *user_data)
669 {
670         if (user_data == NULL)
671                 return 0;
672
673         mediacodec_s *handle = (mediacodec_s *)user_data;
674
675         if (handle->supported_codec_cb)
676                 return ((mediacodec_supported_codec_cb)handle->supported_codec_cb)(codec_type, handle->supported_codec_cb_userdata);
677
678         return false;
679 }
680
681 static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void *user_data)
682 {
683         if (user_data == NULL)
684                 return 0;
685
686         mediacodec_s *handle = (mediacodec_s *)user_data;
687
688         if (handle->buffer_status_cb)
689                 ((mediacodec_buffer_status_cb)handle->buffer_status_cb)(status, handle->buffer_status_cb_userdata);
690
691         return 1;
692 }
693
694
695 static int __mediacodec_resource_release_cb(mm_resource_manager_h rm,
696                 mm_resource_manager_res_h resource_h, void *user_data)
697 {
698         int i;
699         mediacodec_s *handle;
700
701         g_mutex_lock(&mediacodec_handles_lock);
702         for (i = 0; i < mediacodec_handles->len; i++) {
703                 handle = g_ptr_array_index(mediacodec_handles, i);
704                 if (handle->codec_resource == resource_h) {
705                         /*
706                          * TODO
707                          * The resource release cb is asynchronous, so mediacodec_unprepare might be
708                          * called in this thread and in the main thread at the same time.
709                          * Mutex lock/unlock should be added in the body of mediacodec_unprepare() to
710                          * avoid the race condition.
711                          */
712                         handle->codec_resource = NULL;
713                         mediacodec_unprepare((mediacodec_h)handle);
714                         __mediacodec_error_cb(MEDIACODEC_ERROR_RESOURCE_OVERLOADED, handle);
715                         break;
716                 }
717         }
718         g_mutex_unlock(&mediacodec_handles_lock);
719
720         return FALSE;
721 }
722
723 static void __mediacodec_init_lib()
724 {
725         mediacodec_handles = g_ptr_array_sized_new(MC_PREALLOCATED_HANDLE_ARRAY_SIZE);
726
727         if (MM_RESOURCE_MANAGER_ERROR_NONE != mm_resource_manager_create(MM_RESOURCE_MANAGER_APP_CLASS_MEDIA,
728                         __mediacodec_resource_release_cb, NULL, &resource_manager)) {
729                 LOGE("Failed to initialize resource manager");
730                 g_ptr_array_unref(mediacodec_handles);
731         }
732 }
733
734 static void __mediacodec_deinit_lib()
735 {
736         if (resource_manager != NULL)
737                 mm_resource_manager_destroy(resource_manager);
738         g_ptr_array_unref(mediacodec_handles);
739 }