tizen 2.4 release
[framework/api/mediacodec.git] / src / media_codec_port.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
21 #include <dlog.h>
22
23 #include <media_codec.h>
24 #include <media_codec_private.h>
25 #include <media_codec_port.h>
26 #include <media_codec_port_gst.h>
27
28 #include <media_codec_spec_emul.h>
29
30 static mc_codec_spec_t spec_emul[MEDIA_CODEC_MAX_CODEC_TYPE];
31
32 int mc_create(MMHandleType *mediacodec)
33 {
34     mc_handle_t *new_mediacodec = NULL;
35     int ret = MC_ERROR_NONE;
36     int i;
37     int support_list = sizeof(spec_emul) / sizeof(spec_emul[0]);
38
39     /* alloc mediacodec structure */
40     new_mediacodec = (mc_handle_t *)g_malloc(sizeof(mc_handle_t));
41
42     if (!new_mediacodec) {
43         LOGE("Cannot allocate memory for mediacodec");
44         ret = MC_ERROR;
45         goto ERROR;
46     }
47     memset(new_mediacodec, 0, sizeof(mc_handle_t));
48     memset(spec_emul, 0, sizeof(mc_codec_spec_t)*MEDIA_CODEC_MAX_CODEC_TYPE);
49
50     new_mediacodec->is_encoder = false;
51     new_mediacodec->is_video = false;
52     new_mediacodec->is_hw = true;
53     new_mediacodec->is_prepared = false;
54     new_mediacodec->codec_id = MEDIACODEC_NONE;
55
56     new_mediacodec->ports[0] = NULL;
57     new_mediacodec->ports[1] = NULL;
58
59     new_mediacodec->num_supported_codecs  = 0;
60     new_mediacodec->num_supported_decoder = 0;
61     new_mediacodec->num_supported_encoder = 0;
62
63     new_mediacodec->core = NULL;
64
65     /* load ini files */
66     ret = mc_ini_load(&new_mediacodec->ini);
67     if(ret != MC_ERROR_NONE)
68         goto ERROR;
69     _mc_create_codec_map_from_ini(new_mediacodec, spec_emul);
70
71     for (i = 0; i < new_mediacodec->num_supported_codecs; i++) {
72         new_mediacodec->supported_codecs =
73             g_list_append(new_mediacodec->supported_codecs, GINT_TO_POINTER(spec_emul[i].codec_id));
74     }
75
76     /* create decoder map from ini */
77     _mc_create_decoder_map_from_ini(new_mediacodec);
78
79     /* create encoder map from ini */
80     _mc_create_encoder_map_from_ini(new_mediacodec);
81
82     *mediacodec = (MMHandleType)new_mediacodec;
83
84     return ret;
85
86 ERROR:
87
88     return MC_INVALID_ARG;
89 }
90
91 int mc_destroy(MMHandleType mediacodec)
92 {
93     int ret = MC_ERROR_NONE;
94     mc_handle_t *mc_handle = (mc_handle_t *) mediacodec;
95
96     if (!mc_handle) {
97         LOGE("fail invaild param\n");
98         return MC_INVALID_ARG;
99     }
100
101     LOGD("mediacodec : %p", mediacodec);
102
103     if (mc_handle->core != NULL) {
104         if (mc_gst_unprepare(mc_handle) != MC_ERROR_NONE) {
105             LOGE("mc_gst_unprepare() failed");
106             return MC_ERROR;
107         }
108     }
109
110     mc_handle->is_prepared = false;
111     g_list_free(mc_handle->supported_codecs);
112
113     /* free mediacodec structure */
114     if (mc_handle) {
115         g_free((void *)mc_handle);
116         mc_handle = NULL;
117     }
118
119     return ret;
120 }
121
122 int mc_set_codec(MMHandleType mediacodec, mediacodec_codec_type_e codec_id, mediacodec_support_type_e flags)
123 {
124     int ret = MC_ERROR_NONE;
125     mc_handle_t *mc_handle = (mc_handle_t *) mediacodec;
126     int i;
127
128     if (!mc_handle) {
129         LOGE("fail invaild param");
130         return MC_INVALID_ARG;
131     }
132
133     /* Mandatory setting */
134     if (!GET_IS_ENCODER(flags) && !GET_IS_DECODER(flags)) {
135         LOGE("should be encoder or decoder");
136         return MC_PARAM_ERROR;
137     }
138
139
140     for (i = 0; i < mc_handle->num_supported_codecs; i++) {
141         if ((codec_id == spec_emul[i].codec_id) && (flags == spec_emul[i].codec_type)) {
142             break;
143         }
144     }
145     LOGD("support_list : %d, i : %d", mc_handle->num_supported_codecs, i);
146
147     if (i == mc_handle->num_supported_codecs)
148         return MC_NOT_SUPPORTED;
149
150     mc_handle->port_type = spec_emul[i].port_type;
151
152     mc_handle->is_encoder = GET_IS_ENCODER(flags) ? 1 : 0;
153     mc_handle->is_hw = GET_IS_HW(flags) ? 1 : 0;
154     mc_handle->codec_id = codec_id;
155     mc_handle->is_video = CHECK_BIT(codec_id, 13);
156
157     mc_handle->is_prepared = false;
158
159     LOGD("encoder : %d, hardware : %d, codec_id : %x, video : %d",
160         mc_handle->is_encoder, mc_handle->is_hw, mc_handle->codec_id, mc_handle->is_video);
161
162     return ret;
163 }
164
165 int mc_set_vdec_info(MMHandleType mediacodec, int width, int height)
166 {
167     int ret = MC_ERROR_NONE;
168     mc_handle_t* mc_handle = (mc_handle_t *)mediacodec;
169
170     if (!mc_handle) {
171         LOGE("fail invaild param\n");
172         return MC_INVALID_ARG;
173     }
174
175     if ((width <= 0) || (height <= 0))
176         return MC_PARAM_ERROR;
177
178     MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && mc_handle->is_video && !mc_handle->is_encoder,
179             MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER");
180
181     mc_handle->info.decoder.width = width;
182     mc_handle->info.decoder.height = height;
183
184     mc_handle->is_prepared = true;
185
186     switch (mc_handle->codec_id) {
187         case MEDIACODEC_H264:
188             mc_sniff_bitstream = mc_sniff_h264_bitstream;
189             LOGD("mc_sniff_h264_bitstream");
190             break;
191         case MEDIACODEC_MPEG4:
192             mc_sniff_bitstream = mc_sniff_mpeg4_bitstream;
193             break;
194         case MEDIACODEC_H263:
195             mc_sniff_bitstream = mc_sniff_h263_bitstream;
196             break;
197         default:
198             LOGE("NOT SUPPORTED!!!!");
199             break;
200     }
201
202     return ret;
203 }
204
205 int mc_set_venc_info(MMHandleType mediacodec, int width, int height, int fps, int target_bits)
206 {
207     int ret = MC_ERROR_NONE;
208     mc_handle_t *mc_handle = (mc_handle_t *) mediacodec;
209
210     if (!mc_handle) {
211         LOGE("fail invaild param\n");
212         return MC_INVALID_ARG;
213     }
214
215     if ((width <= 0) || (height <= 0))
216         return MC_PARAM_ERROR;
217
218     MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && mc_handle->is_video && mc_handle->is_encoder,
219         MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER");
220
221     mc_handle->info.encoder.width = width;
222     mc_handle->info.encoder.height = height;
223     mc_handle->info.encoder.fps = fps;
224     mc_handle->info.encoder.bitrate = target_bits;
225     mc_handle->is_prepared = true;
226     mc_sniff_bitstream = mc_sniff_yuv;
227
228     return ret;
229 }
230
231 int mc_set_adec_info(MMHandleType mediacodec, int samplerate, int channel, int bit)
232 {
233     int ret = MC_ERROR_NONE;
234     mc_handle_t *mc_handle = (mc_handle_t *) mediacodec;
235
236     if (!mc_handle) {
237         LOGE("fail invaild param\n");
238         return MC_INVALID_ARG;
239     }
240
241     if ((samplerate <= 0) || (channel <= 0) || (bit <= 0))
242         return MC_PARAM_ERROR;
243
244     MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && !mc_handle->is_video && !mc_handle->is_encoder,
245         MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER");
246
247     mc_handle->info.decoder.samplerate = samplerate;
248     mc_handle->info.decoder.channel = channel;
249     mc_handle->info.decoder.bit = bit;
250     mc_handle->is_prepared = true;
251
252     return ret;
253 }
254
255 int mc_set_aenc_info(MMHandleType mediacodec, int samplerate, int channel, int bit, int bitrate)
256 {
257     int ret = MC_ERROR_NONE;
258     mc_handle_t * mc_handle = (mc_handle_t *) mediacodec;
259
260     if (!mc_handle) {
261         LOGE("fail invaild param\n");
262         return MC_INVALID_ARG;
263     }
264
265     if ((samplerate <= 0) || (channel <= 0) || (bit <= 0))
266         return MC_PARAM_ERROR;
267
268     MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && !mc_handle->is_video && mc_handle->is_encoder,
269         MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER");
270
271     mc_handle->info.encoder.samplerate = samplerate;
272     mc_handle->info.encoder.channel = channel;
273     mc_handle->info.encoder.bit = bit;
274     mc_handle->info.encoder.bitrate = bitrate;
275
276     mc_handle->is_prepared = true;
277
278     return ret;
279 }
280
281 int mc_prepare(MMHandleType mediacodec)
282 {
283     int ret = MC_ERROR_NONE;
284     mc_handle_t *mc_handle = (mc_handle_t *) mediacodec;
285
286     if (!mc_handle) {
287         LOGE("fail invaild param\n");
288         return MC_INVALID_ARG;
289     }
290
291     if (!mc_handle->is_prepared)
292         return MC_NOT_INITIALIZED;
293
294     /* setting core details */
295     switch (mc_handle->port_type) {
296         case MEDIACODEC_PORT_TYPE_GENERAL:
297         {
298         }
299         break;
300
301         case MEDIACODEC_PORT_TYPE_OMX:
302         {
303         }
304         break;
305
306         case MEDIACODEC_PORT_TYPE_GST:
307         {
308             mc_gst_prepare(mc_handle);
309         }
310         break;
311
312         default:
313         break;
314     }
315
316     return ret;
317 }
318
319 int mc_unprepare(MMHandleType mediacodec)
320 {
321     int ret = MC_ERROR_NONE;
322     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
323
324     if (!mc_handle) {
325         LOGE("fail invaild param\n");
326         return MC_INVALID_ARG;
327     }
328
329     /* deinit core details */
330     switch (mc_handle->port_type) {
331         case MEDIACODEC_PORT_TYPE_GENERAL:
332         {
333         }
334         break;
335
336         case MEDIACODEC_PORT_TYPE_OMX:
337         {
338         }
339         break;
340
341         case MEDIACODEC_PORT_TYPE_GST:
342         {
343             ret = mc_gst_unprepare(mc_handle);
344         }
345         break;
346
347         default:
348             break;
349     }
350
351     return ret;
352 }
353
354 int mc_process_input(MMHandleType mediacodec, media_packet_h inbuf, uint64_t timeOutUs)
355 {
356     int ret = MC_ERROR_NONE;
357
358     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
359
360     if (!mc_handle) {
361         LOGE("fail invaild param");
362         return MC_INVALID_ARG;
363     }
364
365     if (mc_handle->is_video) {
366         if ((ret = mc_sniff_bitstream(mc_handle, inbuf)) != MC_ERROR_NONE) {
367             return MC_INVALID_IN_BUF;
368         }
369     }
370
371     switch (mc_handle->port_type) {
372         case MEDIACODEC_PORT_TYPE_GENERAL:
373         break;
374
375         case MEDIACODEC_PORT_TYPE_OMX:
376         break;
377
378         case MEDIACODEC_PORT_TYPE_GST:
379         {
380             ret = mc_gst_process_input(mc_handle, inbuf, timeOutUs);
381         }
382         break;
383
384         default:
385             break;
386     }
387
388     return ret;
389 }
390
391 int mc_get_output(MMHandleType mediacodec, media_packet_h *outbuf, uint64_t timeOutUs)
392 {
393     int ret = MC_ERROR_NONE;
394     mc_handle_t *mc_handle = (mc_handle_t *) mediacodec;
395
396     if (!mc_handle) {
397         LOGE("fail invaild param\n");
398         return MC_INVALID_ARG;
399     }
400
401     /* setting core details */
402     switch (mc_handle->port_type) {
403         case MEDIACODEC_PORT_TYPE_GENERAL:
404         break;
405
406         case MEDIACODEC_PORT_TYPE_OMX:
407         break;
408
409         case MEDIACODEC_PORT_TYPE_GST:
410         {
411             ret = mc_gst_get_output(mc_handle, outbuf, timeOutUs);
412         }
413         break;
414
415         default:
416             break;
417     }
418
419     return ret;
420 }
421
422 int mc_flush_buffers(MMHandleType mediacodec)
423 {
424     int ret = MC_ERROR_NONE;
425     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
426
427     if (!mc_handle) {
428         LOGE("fail invaild param\n");
429         return MC_INVALID_ARG;
430     }
431
432     /* setting core details */
433     switch (mc_handle->port_type) {
434         case MEDIACODEC_PORT_TYPE_GENERAL:
435         break;
436
437         case MEDIACODEC_PORT_TYPE_OMX:
438         break;
439
440         case MEDIACODEC_PORT_TYPE_GST:
441         {
442             ret = mc_gst_flush_buffers(mc_handle);
443         }
444         break;
445
446         default:
447             break;
448     }
449
450     return ret;
451 }
452
453 int mc_get_supported_type(MMHandleType mediacodec, mediacodec_codec_type_e codec_type, bool encoder, int *support_type)
454 {
455     int ret = MC_ERROR_NONE;
456     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
457     mc_codec_map_t *codec_map;
458     int num_supported_codec = 0;
459     int i;
460
461     *support_type = 0;
462
463     if (!mc_handle) {
464         LOGE("fail invaild param\n");
465         return MC_INVALID_ARG;
466     }
467     codec_map = encoder ? mc_handle->encoder_map : mc_handle->decoder_map;
468     num_supported_codec = encoder ? mc_handle->num_supported_encoder : mc_handle->num_supported_decoder;
469
470     for (i = 0; i < num_supported_codec; i++)
471     {
472         if (codec_map[i].id == codec_type)
473         {
474             if (codec_map[i].hardware)
475                 *support_type |= MEDIACODEC_SUPPORT_TYPE_HW;
476             else
477                 *support_type |= MEDIACODEC_SUPPORT_TYPE_SW;
478             break;
479         }
480
481     }
482
483     return ret;
484 }
485
486 int mc_set_empty_buffer_cb(MMHandleType mediacodec, mediacodec_input_buffer_used_cb callback, void *user_data)
487 {
488     int ret = MC_ERROR_NONE;
489     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
490
491     if (!mc_handle) {
492         LOGE("fail invaild param\n");
493         return MC_INVALID_ARG;
494     }
495
496     if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) {
497         LOGE("Already set mediacodec_empty_buffer_cb");
498         return MC_PARAM_ERROR;
499     } else {
500         if (!callback) {
501             return MC_INVALID_ARG;
502         }
503
504         LOGD("Set empty buffer callback(cb = %p, data = %p)", callback, user_data);
505
506         mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER] = (mc_empty_buffer_cb) callback;
507         mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER] = user_data;
508
509         return MC_ERROR_NONE;
510     }
511
512     return ret;
513 }
514
515 int mc_unset_empty_buffer_cb(MMHandleType mediacodec)
516 {
517     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
518
519     if (!mc_handle) {
520         LOGE("fail invaild param\n");
521         return MC_INVALID_ARG;
522     }
523
524     mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER] = NULL;
525     mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER] = NULL;
526
527     return MC_ERROR_NONE;
528 }
529
530 int mc_set_fill_buffer_cb(MMHandleType mediacodec, mediacodec_output_buffer_available_cb callback, void *user_data)
531 {
532     int ret = MC_ERROR_NONE;
533     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
534
535     if (!mc_handle) {
536         LOGE("fail invaild param\n");
537         return MC_INVALID_ARG;
538     }
539
540     if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]) {
541         LOGE("Already set mediacodec_fill_buffer_cb");
542         return MC_PARAM_ERROR;
543     } else {
544         if (!callback) {
545             return MC_INVALID_ARG;
546         }
547
548         LOGD("Set fill buffer callback(cb = %p, data = %p)", callback, user_data);
549
550         mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER] = (mc_fill_buffer_cb) callback;
551         mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_FILLBUFFER] = user_data;
552         return MC_ERROR_NONE;
553     }
554
555     return ret;
556 }
557
558 int mc_unset_fill_buffer_cb(MMHandleType mediacodec)
559 {
560     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
561
562     if (!mc_handle) {
563         LOGE("fail invaild param\n");
564         return MC_INVALID_ARG;
565     }
566
567     mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER] = NULL;
568     mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_FILLBUFFER] = NULL;
569
570     return MC_ERROR_NONE;
571 }
572
573 int mc_set_error_cb(MMHandleType mediacodec, mediacodec_error_cb callback, void *user_data)
574 {
575     int ret = MC_ERROR_NONE;
576     mc_handle_t *mc_handle = (mc_handle_t *) mediacodec;
577
578     if (!mc_handle) {
579         LOGE("fail invaild param\n");
580         return MC_INVALID_ARG;
581     }
582
583     if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) {
584         LOGE("Already set mediacodec_fill_buffer_cb\n");
585         return MC_PARAM_ERROR;
586     } else {
587         if (!callback) {
588             return MC_INVALID_ARG;
589         }
590
591         LOGD("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
592
593         mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR] = (mc_error_cb) callback;
594         mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_ERROR] = user_data;
595         return MC_ERROR_NONE;
596     }
597
598     return ret;
599 }
600
601 int mc_unset_error_cb(MMHandleType mediacodec)
602 {
603     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
604
605     if (!mc_handle) {
606         LOGE("fail invaild param");
607         return MC_INVALID_ARG;
608     }
609
610     mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR] = NULL;
611     mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_ERROR] = NULL;
612
613     return MC_ERROR_NONE;
614 }
615
616 int mc_set_eos_cb(MMHandleType mediacodec, mediacodec_eos_cb callback, void *user_data)
617 {
618     int ret = MC_ERROR_NONE;
619     mc_handle_t *mc_handle = (mc_handle_t *) mediacodec;
620
621     if (!mc_handle) {
622         LOGE("fail invaild param\n");
623         return MC_INVALID_ARG;
624     }
625
626     if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) {
627         LOGE("Already set mediacodec_fill_buffer_cb");
628         return MC_PARAM_ERROR;
629     } else {
630         if (!callback) {
631             return MC_INVALID_ARG;
632         }
633
634         LOGD("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
635
636         mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_EOS] = (mc_eos_cb) callback;
637         mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_EOS] = user_data;
638         return MC_ERROR_NONE;
639     }
640
641     return ret;
642 }
643
644 int mc_unset_eos_cb(MMHandleType mediacodec)
645 {
646     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
647
648     if (!mc_handle) {
649         LOGE("fail invaild param\n");
650         return MC_INVALID_ARG;
651     }
652
653     mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_EOS] = NULL;
654     mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_EOS] = NULL;
655
656     return MC_ERROR_NONE;
657 }
658
659 int mc_set_buffer_status_cb(MMHandleType mediacodec, mediacodec_buffer_status_cb callback, void *user_data)
660 {
661     int ret = MC_ERROR_NONE;
662     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
663
664     if (!mc_handle) {
665         LOGE("fail invaild param\n");
666         return MC_INVALID_ARG;
667     }
668
669     if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]) {
670         LOGE("Already set mediacodec_need_data_cb\n");
671         return MC_PARAM_ERROR;
672     } else {
673         if (!callback) {
674             return MC_INVALID_ARG;
675         }
676
677         LOGD("Set start feed callback(cb = %p, data = %p)\n", callback, user_data);
678
679         mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS] = (mc_buffer_status_cb) callback;
680         mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS] = user_data;
681         return MC_ERROR_NONE;
682     }
683
684     return ret;
685 }
686
687 int mc_unset_buffer_status_cb(MMHandleType mediacodec)
688 {
689     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
690
691     if (!mc_handle) {
692         LOGE("fail invaild param\n");
693         return MC_INVALID_ARG;
694     }
695
696     mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS] = NULL;
697     mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS] = NULL;
698
699     return MC_ERROR_NONE;
700 }
701
702 int mc_set_supported_codec_cb(MMHandleType mediacodec, mediacodec_supported_codec_cb callback, void *user_data)
703 {
704     int ret = MC_ERROR_NONE;
705     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
706
707     if (!mc_handle) {
708         LOGE("fail invaild param\n");
709         return MC_INVALID_ARG;
710     }
711
712     if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_SUPPORTED_CODEC]) {
713         LOGE("Already set mediacodec_supported_codec_cb\n");
714         return MC_PARAM_ERROR;
715     } else {
716         if (!callback) {
717             return MC_INVALID_ARG;
718         }
719
720         LOGD("Set event handler callback(cb = %p, data = %p)", callback, user_data);
721
722         mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_SUPPORTED_CODEC] = (mc_supported_codec_cb) callback;
723         mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_SUPPORTED_CODEC] = user_data;
724         return MC_ERROR_NONE;
725     }
726
727     return ret;
728 }
729
730 int _mediacodec_foreach_supported_codec(MMHandleType mediacodec, mediacodec_supported_codec_cb callback, void *user_data)
731 {
732     int ret = MC_ERROR_NONE;
733     mc_handle_t *mc_handle = (mc_handle_t *)mediacodec;
734     int codecs_num;
735     gpointer tmp;
736
737     if (!mc_handle) {
738         LOGE("fail invaild param\n");
739         return MC_INVALID_ARG;
740     }
741
742     if (mc_handle->supported_codecs) {
743         codecs_num = g_list_length(mc_handle->supported_codecs);
744         LOGD("supported_codecs : %d", codecs_num);
745
746         while (codecs_num) {
747             tmp = g_list_nth_data(mc_handle->supported_codecs, codecs_num - 1);
748             if (tmp) {
749                 if (!callback(GPOINTER_TO_INT(tmp), user_data)) {
750                     ret = MEDIACODEC_ERROR_INTERNAL;
751                     goto CALLBACK_ERROR;
752                 }
753             }
754             codecs_num--;
755         }
756
757         if (!callback(-1, user_data)) {
758             ret = MEDIACODEC_ERROR_INTERNAL;
759             goto CALLBACK_ERROR;
760         }
761     }
762
763 CALLBACK_ERROR:
764     LOGD("foreach callback returned error");
765     return ret;
766 }
767
768 int mc_sniff_h264_bitstream(mc_handle_t *handle, media_packet_h pkt)
769 {
770     int ret = MC_ERROR_NONE;
771     void *buf_data = NULL;
772     void *codec_data = NULL;
773     unsigned int codec_data_size = 0;
774     uint64_t buf_size = 0;
775     bool eos = false;
776     bool codec_config = false;
777
778     media_packet_get_buffer_size(pkt, &buf_size);
779     media_packet_get_buffer_data_ptr(pkt, &buf_data);
780     media_packet_get_codec_data(pkt, &codec_data, &codec_data_size);
781     media_packet_is_end_of_stream(pkt, &eos);
782     media_packet_is_codec_config(pkt, &codec_config);
783
784     LOGD("codec_data_size : %d, buf_size : %d, codec_config : %d, eos : %d",
785         codec_data_size, (int)buf_size, codec_config, eos);
786
787     if (codec_config) {
788         if (codec_data_size == 0)
789           ret = _mc_check_h264_bytestream(buf_data, (int)buf_size, 0, NULL, NULL, NULL);
790     }
791
792     return ret;
793 }
794
795 int mc_sniff_mpeg4_bitstream(mc_handle_t *handle, media_packet_h pkt)
796 {
797     uint64_t buf_size = 0;
798     unsigned char *buf_data = NULL;
799     void *codec_data = NULL;
800     int codec_data_size = 0, voss_size = 0;
801     bool eos = false;
802     bool codec_config = false;
803     bool sync_frame = false;
804
805     media_packet_get_buffer_size(pkt, &buf_size);
806     media_packet_get_buffer_data_ptr(pkt, (void *)&buf_data);
807     media_packet_get_codec_data(pkt, &codec_data, &codec_data_size);
808     media_packet_is_end_of_stream(pkt, &eos);
809     media_packet_is_codec_config(pkt, &codec_config);
810     media_packet_is_sync_frame(pkt, &sync_frame);
811
812     LOGD("codec_data_size : %d, buff_size : %d, codec_config : %d, sync_frame : %d, eos : %d",
813         codec_data_size, (int)buf_size, codec_config, sync_frame, eos);
814
815     if (eos)
816         return MC_ERROR_NONE;
817
818     if (codec_config) {
819         if (codec_data) {
820             if (!_mc_is_voss(codec_data, codec_data_size, NULL))/*voss not in codec data */
821                 return MC_INVALID_IN_BUF;
822         }
823         /* Codec data + I-frame in buffer */
824         if (_mc_is_voss(buf_data, buf_size, &voss_size)) {
825             if (_mc_is_ivop(buf_data, buf_size, voss_size))   /* IVOP after codec_data */
826                 return MC_ERROR_NONE;
827         } else {
828             if (_mc_is_ivop(buf_data, buf_size, 0))            /* IVOP at the start */
829                 return MC_ERROR_NONE;
830         }
831     } else if (_mc_is_vop(buf_data, buf_size, 0))
832         return MC_ERROR_NONE;
833
834     return MC_INVALID_IN_BUF;
835 }
836
837 int mc_sniff_h263_bitstream(mc_handle_t *handle, media_packet_h pkt)
838 {
839     void *buf_data = NULL;
840     uint64_t buf_size = 0;
841     bool eos = false;
842
843     media_packet_get_buffer_size(pkt, &buf_size);
844     media_packet_get_buffer_data_ptr(pkt, &buf_data);
845     media_packet_is_end_of_stream(pkt, &eos);
846
847     if (eos)
848         return MC_ERROR_NONE;
849
850     return _mc_check_valid_h263_frame((unsigned char *)buf_data, (int)buf_size);
851 }
852
853 int mc_sniff_yuv(mc_handle_t *handle, media_packet_h pkt)
854 {
855     int ret = MC_ERROR_NONE;
856
857 #if 0 /* libtbm, media-tool should be updated */
858     uint64_t buf_size = 0;
859     int plane_num = 0;
860     int padded_width = 0;
861     int padded_height = 0;
862     int allocated_buffer = 0;
863     int index;
864
865     media_packet_get_buffer_size(pkt, &buf_size);
866     media_packet_get_video_number_of_planes(pkt, &plane_num);
867
868     for (index = 0; index < plane_num; index++) {
869         media_packet_get_video_stride_width(pkt, index, &padded_width);
870         media_packet_get_video_stride_height(pkt, index, &padded_height);
871         allocated_buffer += padded_width * padded_height;
872
873         LOGD("%d plane size : %d", padded_width * padded_height);
874     }
875
876     if (buf_size > allocated_buffer) {
877         LOGE("Buffer exceeds maximum size [buf_size: %d, allocated_size :%d", (int)buf_size, allocated_buffer);
878         ret = MC_INVALID_IN_BUF;
879     }
880 #endif
881     return ret;
882 }
883