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