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