Featuer Enhancement : A Media Player library in Tizen Native API
[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
24 #include <dlog.h>
25
26 static gboolean  __mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data);
27 static gboolean __mediacodec_fill_buffer_cb(media_packet_h pkt, void *user_data);
28 static gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data);
29 static gboolean __mediacodec_eos_cb(void *user_data);
30
31 /*
32 * Internal Implementation
33 */
34 int __convert_error_code(int code, char* func_name)
35 {
36     int ret = MEDIACODEC_ERROR_INVALID_OPERATION;
37     char* msg = "MEDIACOODEC_INVALID_OPERATION";
38     switch(code)
39     {
40         case MC_ERROR_NONE:
41             ret = MEDIACODEC_ERROR_NONE;
42             msg = "MEDIACODEC_ERROR_NONE";
43             break;
44         case MC_PARAM_ERROR:
45         case MC_INVALID_ARG:
46             ret = MEDIACODEC_ERROR_INVALID_PARAMETER;
47             msg = "MEDIACODEC_ERROR_INVALID_PARAMETER";
48             break;
49         case MC_PERMISSION_DENIED:
50             ret = MEDIACODEC_ERROR_PERMISSION_DENIED;
51             msg = "MEDIACODEC_ERROR_PERMISSION_DENIED";
52             break;
53         case MC_INVALID_STATUS:
54             ret = MEDIACODEC_ERROR_INVALID_STATE;
55             msg = "MEDIACODEC_ERROR_INVALID_STATE";
56             break;
57         case MC_NOT_SUPPORTED:
58             ret = MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE;
59             msg = "MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE";
60             break;
61         case MC_ERROR:
62         case MC_INTERNAL_ERROR:
63         case MC_HW_ERROR:
64             ret = MEDIACODEC_ERROR_INVALID_OPERATION;
65             msg = "MEDIACODEC_ERROR_INVALID_OPERATION";
66             break;
67         case MC_INVALID_STREAM:
68             ret = MEDIACODEC_ERROR_INVALID_STREAM;
69             msg = "MEDIACODEC_ERROR_INVALID_STREAM";
70             break;
71         case MC_CODEC_NOT_FOUND:
72             ret = MEDIACODEC_ERROR_CODEC_NOT_FOUND;
73             msg = "MEDIACODEC_ERROR_CODEC_NOT_FOUND";
74             break;
75         case MC_ERROR_DECODE:
76             ret = MEDIACODEC_ERROR_DECODE;
77             msg = "MEDIACODEC_ERROR_DECODE";
78             break;
79         case MC_INVALID_IN_BUF:
80             ret = MEDIACODEC_ERROR_INVALID_INBUFFER;
81             msg = "MEDIACODEC_ERROR_INVALID_INBUFFER";
82             break;
83         case MC_INVALID_OUT_BUF:
84             ret = MEDIACODEC_ERROR_INVALID_OUTBUFFER;
85             msg = "MEDIACODEC_ERROR_INVALID_OUTBUFFER";
86             break;
87         case MC_NOT_INITIALIZED:
88             ret = MEDIACODEC_ERROR_NOT_INITIALIZED;
89             msg = "MEDIACODEC_ERROR_NOT_INITIALIZED";
90             break;
91         case MC_OUTPUT_BUFFER_EMPTY:
92         case MC_OUTPUT_BUFFER_OVERFLOW:
93             ret = MEDIACODEC_ERROR_BUFFER_NOT_AVAILABLE;
94             msg = "MEDIACODEC_ERROR_BUFFER_NOT_AVAILABLE";
95             break;
96         default:
97             ret = MEDIACODEC_ERROR_INTERNAL;
98             msg = "MEDIACODEC_ERROR_INTERNAL";
99             break;
100     }
101     LOGD("[%s] %s(0x%08x) : core fw error(0x%x)", func_name, msg, ret, code);
102     return ret;
103 }
104
105 bool __mediacodec_state_validate(mediacodec_h mediacodec, mediacodec_state_e threshold)
106 {
107     mediacodec_s * handle = (mediacodec_s *) mediacodec;
108
109     if(handle->state < threshold)
110         return FALSE;
111     return TRUE;
112 }
113
114
115 int mediacodec_create(mediacodec_h *mediacodec)
116 {
117     MEDIACODEC_INSTANCE_CHECK(mediacodec);
118     mediacodec_s *handle;
119     int ret;
120
121     LOGD ("mediacodec_create..\n");
122
123     handle = (mediacodec_s*)malloc( sizeof(mediacodec_s));
124     if (handle != NULL)
125     {
126         memset(handle, 0 , sizeof(mediacodec_s));
127     }
128     else
129     {
130         LOGE("MEDIACODEC_ERROR_OUT_OF_MEMORY(0x%08x)", MEDIACODEC_ERROR_OUT_OF_MEMORY);
131         return MEDIACODEC_ERROR_OUT_OF_MEMORY;
132     }
133
134     ret = mc_create(&handle->mc_handle);
135     if (ret != MEDIACODEC_ERROR_NONE)
136     {
137         LOGE("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION);
138         handle->state = MEDIACODEC_STATE_NONE;
139         free(handle);
140         handle = NULL;
141         return MEDIACODEC_ERROR_INVALID_OPERATION;
142     }
143     else
144     {
145         *mediacodec = (mediacodec_h) handle;
146         handle->state = MEDIACODEC_STATE_IDLE;
147         LOGD("new handle : %p", *mediacodec);
148     }
149
150     /* set callback */
151     mc_set_empty_buffer_cb(handle->mc_handle, (mediacodec_input_buffer_used_cb)__mediacodec_empty_buffer_cb, handle);
152     mc_set_fill_buffer_cb(handle->mc_handle, (mediacodec_output_buffer_available_cb)__mediacodec_fill_buffer_cb, handle);
153     mc_set_error_cb(handle->mc_handle, (mediacodec_error_cb)__mediacodec_error_cb, handle);
154     mc_set_eos_cb(handle->mc_handle, (mediacodec_eos_cb)__mediacodec_eos_cb, handle);
155
156     return MEDIACODEC_ERROR_NONE;
157
158 }
159
160 int mediacodec_destroy(mediacodec_h mediacodec)
161 {
162     LOGD ("[%s] Start, handle to destroy : %p", __FUNCTION__, mediacodec);
163     MEDIACODEC_INSTANCE_CHECK(mediacodec);
164     mediacodec_s * handle = (mediacodec_s *) mediacodec;
165
166     int ret = mc_destroy(handle->mc_handle);
167     if (ret != MEDIACODEC_ERROR_NONE) {
168         LOGD("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION);
169         return MEDIACODEC_ERROR_INVALID_OPERATION;
170     }
171     else
172     {
173         handle->state = MEDIACODEC_STATE_NONE;
174         free(handle);
175         handle = NULL;
176         return MEDIACODEC_ERROR_NONE;
177     }
178 }
179
180 int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_id, mediacodec_support_type_e flags)
181 {
182     MEDIACODEC_INSTANCE_CHECK(mediacodec);
183     mediacodec_s * handle = (mediacodec_s *) mediacodec;
184     MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
185
186     int ret = mc_set_codec(handle->mc_handle, codec_id, flags);
187
188     if (ret != MEDIACODEC_ERROR_NONE)
189     {
190         return __convert_error_code(ret,(char*)__FUNCTION__);
191     }
192     else
193     {
194         handle->state = MEDIACODEC_STATE_IDLE;
195         return MEDIACODEC_ERROR_NONE;
196     }
197 }
198
199 int mediacodec_set_vdec_info(mediacodec_h mediacodec, int width, int height)
200 {
201     MEDIACODEC_INSTANCE_CHECK(mediacodec);
202     mediacodec_s * handle = (mediacodec_s *) mediacodec;
203     MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
204
205     int ret = mc_set_vdec_info(handle->mc_handle, width, height);
206
207     if (ret != MEDIACODEC_ERROR_NONE)
208     {
209         return __convert_error_code(ret,(char*)__FUNCTION__);
210     }
211     else
212     {
213         handle->state = MEDIACODEC_STATE_IDLE;
214         return MEDIACODEC_ERROR_NONE;
215     }
216 }
217
218 int mediacodec_set_venc_info(mediacodec_h mediacodec, int width, int height, int fps, int target_bits)
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_venc_info(handle->mc_handle, width, height, fps, target_bits);
225
226     if (ret != MEDIACODEC_ERROR_NONE)
227     {
228         return __convert_error_code(ret,(char*)__FUNCTION__);
229     }
230     else
231     {
232         handle->state = MEDIACODEC_STATE_IDLE;
233         return MEDIACODEC_ERROR_NONE;
234     }
235 }
236
237 int mediacodec_set_adec_info(mediacodec_h mediacodec, int samplerate, int channel, int bit)
238 {
239     MEDIACODEC_INSTANCE_CHECK(mediacodec);
240     mediacodec_s * handle = (mediacodec_s *) mediacodec;
241     MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
242
243     int ret = mc_set_adec_info(handle->mc_handle, samplerate, channel, bit);
244
245     if (ret != MEDIACODEC_ERROR_NONE)
246     {
247         return __convert_error_code(ret,(char*)__FUNCTION__);
248     }
249     else
250     {
251         handle->state = MEDIACODEC_STATE_IDLE;
252         return MEDIACODEC_ERROR_NONE;
253     }
254 }
255
256 int mediacodec_set_aenc_info(mediacodec_h mediacodec, int samplerate, int channel, int bit, int bitrate)
257 {
258     MEDIACODEC_INSTANCE_CHECK(mediacodec);
259     mediacodec_s * handle = (mediacodec_s *) mediacodec;
260     MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
261
262     int ret = mc_set_aenc_info(handle->mc_handle, samplerate, channel, bit, bitrate);
263
264     if (ret != MEDIACODEC_ERROR_NONE)
265     {
266         return __convert_error_code(ret,(char*)__FUNCTION__);
267     }
268     else
269     {
270         handle->state = MEDIACODEC_STATE_IDLE;
271         return MEDIACODEC_ERROR_NONE;
272     }
273 }
274
275 int mediacodec_prepare(mediacodec_h mediacodec)
276 {
277     MEDIACODEC_INSTANCE_CHECK(mediacodec);
278     mediacodec_s * handle = (mediacodec_s *) mediacodec;
279     MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
280
281     int ret = mc_prepare(handle->mc_handle);
282
283     if (ret != MEDIACODEC_ERROR_NONE)
284     {
285         return __convert_error_code(ret,(char*)__FUNCTION__);
286     }
287     else
288     {
289         handle->state = MEDIACODEC_STATE_READY;
290         return MEDIACODEC_ERROR_NONE;
291     }
292 }
293
294 int mediacodec_unprepare(mediacodec_h mediacodec)
295 {
296     MEDIACODEC_INSTANCE_CHECK(mediacodec);
297     mediacodec_s * handle = (mediacodec_s *) mediacodec;
298
299     int ret = mc_unprepare(handle->mc_handle);
300
301     if (ret != MEDIACODEC_ERROR_NONE)
302     {
303         return __convert_error_code(ret,(char*)__FUNCTION__);
304     }
305     else
306     {
307         handle->state = MEDIACODEC_STATE_IDLE;
308         return MEDIACODEC_ERROR_NONE;
309     }
310 }
311
312 int mediacodec_process_input(mediacodec_h mediacodec, media_packet_h inbuf, uint64_t timeOutUs)
313 {
314     MEDIACODEC_INSTANCE_CHECK(mediacodec);
315     mediacodec_s * handle = (mediacodec_s *) mediacodec;
316     MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_READY);
317
318     int ret = mc_process_input(handle->mc_handle, inbuf, timeOutUs);
319
320     if (ret != MEDIACODEC_ERROR_NONE)
321     {
322         return __convert_error_code(ret,(char*)__FUNCTION__);
323     }
324     else
325     {
326         //handle->state = MEDIACODEC_STATE_EXCUTE;
327         return MEDIACODEC_ERROR_NONE;
328     }
329 }
330
331 int mediacodec_get_output(mediacodec_h mediacodec, media_packet_h *outbuf, uint64_t timeOutUs)
332 {
333     MEDIACODEC_INSTANCE_CHECK(mediacodec);
334     mediacodec_s * handle = (mediacodec_s *) mediacodec;
335     MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_READY);
336
337     int ret = mc_get_output(handle->mc_handle, outbuf, timeOutUs);
338
339     if (ret != MEDIACODEC_ERROR_NONE)
340     {
341         return __convert_error_code(ret,(char*)__FUNCTION__);
342     }
343     else
344     {
345         //handle->state = MEDIACODEC_STATE_EXCUTE;
346         return MEDIACODEC_ERROR_NONE;
347     }
348 }
349
350 int mediacodec_set_input_buffer_used_cb(mediacodec_h mediacodec, mediacodec_input_buffer_used_cb callback, void* user_data)
351 {
352     MEDIACODEC_INSTANCE_CHECK(mediacodec);
353     mediacodec_s * handle = (mediacodec_s *) mediacodec;
354     MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
355
356     handle->empty_buffer_cb = callback;
357     handle->empty_buffer_cb_userdata = user_data;
358
359     LOGD("set empty_buffer_cb(%p)", callback);
360
361     return MEDIACODEC_ERROR_NONE;
362 }
363
364 int mediacodec_unset_input_buffer_used_cb(mediacodec_h mediacodec)
365 {
366     MEDIACODEC_INSTANCE_CHECK(mediacodec);
367     mediacodec_s * handle = (mediacodec_s *) mediacodec;
368
369     handle->empty_buffer_cb = NULL;
370     handle->empty_buffer_cb_userdata = NULL;
371
372     return MEDIACODEC_ERROR_NONE;
373 }
374
375
376 int mediacodec_set_output_buffer_available_cb(mediacodec_h mediacodec, mediacodec_output_buffer_available_cb callback, void* user_data)
377 {
378     MEDIACODEC_INSTANCE_CHECK(mediacodec);
379     mediacodec_s * handle = (mediacodec_s *) mediacodec;
380     MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
381
382     handle->fill_buffer_cb = callback;
383     handle->fill_buffer_cb_userdata = user_data;
384
385     LOGD("set fill_buffer_cb(%p)", callback);
386
387     return MEDIACODEC_ERROR_NONE;
388
389 }
390
391 int mediacodec_unset_output_buffer_available_cb(mediacodec_h mediacodec)
392 {
393     MEDIACODEC_INSTANCE_CHECK(mediacodec);
394     mediacodec_s * handle = (mediacodec_s *) mediacodec;
395
396     handle->fill_buffer_cb = NULL;
397     handle->fill_buffer_cb_userdata = NULL;
398
399     return MEDIACODEC_ERROR_NONE;
400 }
401
402 int mediacodec_set_error_cb(mediacodec_h mediacodec, mediacodec_error_cb callback, void* user_data)
403 {
404     MEDIACODEC_INSTANCE_CHECK(mediacodec);
405     mediacodec_s * handle = (mediacodec_s *) mediacodec;
406     MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
407
408     handle->error_cb = callback;
409     handle->error_cb_userdata = user_data;
410
411     LOGD("set error_cb(%p)", callback);
412
413     return MEDIACODEC_ERROR_NONE;
414
415 }
416
417 int mediacodec_unset_error_cb(mediacodec_h mediacodec)
418 {
419     MEDIACODEC_INSTANCE_CHECK(mediacodec);
420     mediacodec_s * handle = (mediacodec_s *) mediacodec;
421
422     handle->error_cb = NULL;
423     handle->error_cb_userdata = NULL;
424
425     return MEDIACODEC_ERROR_NONE;
426 }
427
428 int mediacodec_set_eos_cb(mediacodec_h mediacodec, mediacodec_eos_cb callback, void* user_data)
429 {
430     MEDIACODEC_INSTANCE_CHECK(mediacodec);
431     mediacodec_s * handle = (mediacodec_s *) mediacodec;
432     MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
433
434     handle->eos_cb = callback;
435     handle->eos_cb_userdata = user_data;
436
437     LOGD("set eos_cb(%p)", callback);
438
439     return MEDIACODEC_ERROR_NONE;
440
441 }
442
443 int mediacodec_unset_eos_cb(mediacodec_h mediacodec)
444 {
445     MEDIACODEC_INSTANCE_CHECK(mediacodec);
446     mediacodec_s * handle = (mediacodec_s *) mediacodec;
447
448     handle->eos_cb = NULL;
449     handle->eos_cb_userdata = NULL;
450
451     return MEDIACODEC_ERROR_NONE;
452 }
453
454 static gboolean __mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data)
455 {
456     if(user_data == NULL || pkt == NULL)
457         return 0;
458
459     mediacodec_s * handle = (mediacodec_s *) user_data;
460
461     if ( handle->empty_buffer_cb )
462     {
463         ((mediacodec_input_buffer_used_cb)handle->empty_buffer_cb)(pkt, handle->empty_buffer_cb_userdata);
464     }
465
466     return 1;
467 }
468
469 static gboolean  __mediacodec_fill_buffer_cb(media_packet_h pkt, void *user_data)
470 {
471     if(user_data == NULL || pkt == NULL)
472         return 0;
473
474     mediacodec_s * handle = (mediacodec_s *) user_data;
475
476     if ( handle->fill_buffer_cb )
477     {
478         ((mediacodec_output_buffer_available_cb)handle->fill_buffer_cb)(pkt, handle->fill_buffer_cb_userdata);
479     }
480
481     return 1;
482 }
483
484 static gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data)
485 {
486     if(user_data == NULL)
487         return 0;
488
489     mediacodec_s * handle = (mediacodec_s *) user_data;
490
491     if ( handle->error_cb )
492     {
493         ((mediacodec_error_cb)handle->error_cb)(error, handle->error_cb_userdata);
494     }
495
496     return 1;
497 }
498
499 static gboolean __mediacodec_eos_cb(void *user_data)
500 {
501     if(user_data == NULL)
502         return 0;
503
504     mediacodec_s * handle = (mediacodec_s *) user_data;
505
506     if ( handle->eos_cb )
507     {
508         ((mediacodec_eos_cb)handle->eos_cb)(handle->eos_cb_userdata);
509     }
510
511     return 1;
512 }