From d70d919c01b4c8c81dd4e755179c5d96de8bd1cd Mon Sep 17 00:00:00 2001 From: Sam Protsenko Date: Fri, 8 Sep 2023 19:45:36 -0500 Subject: [PATCH] Add original Samsung hardware projects Change-Id: I79380bc91acf57ca5f3e56fb64af76f4c45f6566 Signed-off-by: Sam Protsenko --- Android.mk | 16 + NOTICE | 190 + openmax/Android.mk | 81 + openmax/NOTICE | 190 + openmax/component/audio/common/Android.mk | 36 + .../audio/common/Exynos_OMX_ABasecomponent.c | 1727 +++++ .../audio/common/Exynos_OMX_ABasecomponent.h | 158 + .../audio/common/Exynos_OMX_ABaseport.c | 992 +++ .../audio/common/Exynos_OMX_ABaseport.h | 157 + openmax/component/audio/common/NOTICE | 190 + openmax/component/audio/dec/Android.mk | 31 + openmax/component/audio/dec/Exynos_OMX_Adec.c | 1538 +++++ openmax/component/audio/dec/Exynos_OMX_Adec.h | 144 + openmax/component/audio/dec/NOTICE | 190 + openmax/component/audio/dec/mp3/Android.mk | 41 + .../audio/dec/mp3/Exynos_OMX_Mp3dec.c | 938 +++ .../audio/dec/mp3/Exynos_OMX_Mp3dec.h | 63 + openmax/component/audio/dec/mp3/NOTICE | 190 + .../audio/dec/mp3/library_register.c | 58 + .../audio/dec/mp3/library_register.h | 54 + openmax/component/audio/dec/wma/Android.mk | 34 + .../audio/dec/wma/Exynos_OMX_Wmadec.c | 750 +++ .../audio/dec/wma/Exynos_OMX_Wmadec.h | 68 + openmax/component/audio/dec/wma/NOTICE | 190 + .../audio/dec/wma/library_register.c | 57 + .../audio/dec/wma/library_register.h | 53 + openmax/component/audio/seiren_dec/Android.mk | 29 + .../audio/seiren_dec/Exynos_OMX_Adec.c | 1537 +++++ .../audio/seiren_dec/Exynos_OMX_Adec.h | 143 + openmax/component/audio/seiren_dec/NOTICE | 190 + .../component/audio/seiren_dec/aac/Android.mk | 41 + .../audio/seiren_dec/aac/Exynos_OMX_Aacdec.c | 970 +++ .../audio/seiren_dec/aac/Exynos_OMX_Aacdec.h | 72 + openmax/component/audio/seiren_dec/aac/NOTICE | 190 + .../audio/seiren_dec/aac/library_register.c | 58 + .../audio/seiren_dec/aac/library_register.h | 54 + .../audio/seiren_dec/flac/Android.mk | 41 + .../seiren_dec/flac/Exynos_OMX_Flacdec.c | 946 +++ .../seiren_dec/flac/Exynos_OMX_Flacdec.h | 77 + .../component/audio/seiren_dec/flac/NOTICE | 190 + .../audio/seiren_dec/flac/library_register.c | 58 + .../audio/seiren_dec/flac/library_register.h | 54 + .../component/audio/seiren_dec/mp3/Android.mk | 41 + .../audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.c | 955 +++ .../audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.h | 74 + openmax/component/audio/seiren_dec/mp3/NOTICE | 190 + .../audio/seiren_dec/mp3/library_register.c | 67 + .../audio/seiren_dec/mp3/library_register.h | 60 + openmax/component/common/Android.mk | 97 + .../common/Exynos_OMX_Basecomponent.c | 2557 ++++++++ .../common/Exynos_OMX_Basecomponent.h | 166 + .../component/common/Exynos_OMX_Baseport.c | 1255 ++++ .../component/common/Exynos_OMX_Baseport.h | 242 + .../common/Exynos_OMX_Resourcemanager.c | 584 ++ .../common/Exynos_OMX_Resourcemanager.h | 50 + openmax/component/common/NOTICE | 190 + openmax/component/video/dec/Android.mk | 61 + openmax/component/video/dec/Exynos_OMX_Vdec.c | 2102 ++++++ openmax/component/video/dec/Exynos_OMX_Vdec.h | 226 + .../video/dec/Exynos_OMX_VdecControl.c | 2648 ++++++++ .../video/dec/Exynos_OMX_VdecControl.h | 117 + openmax/component/video/dec/NOTICE | 190 + openmax/component/video/dec/h264/Android.mk | 97 + .../video/dec/h264/Exynos_OMX_H264dec.c | 3865 +++++++++++ .../video/dec/h264/Exynos_OMX_H264dec.h | 105 + openmax/component/video/dec/h264/NOTICE | 190 + .../video/dec/h264/library_register.c | 59 + .../video/dec/h264/library_register.h | 62 + openmax/component/video/dec/hevc/Android.mk | 96 + .../video/dec/hevc/Exynos_OMX_HEVCdec.c | 4278 ++++++++++++ .../video/dec/hevc/Exynos_OMX_HEVCdec.h | 101 + openmax/component/video/dec/hevc/NOTICE | 190 + .../video/dec/hevc/library_register.c | 65 + .../video/dec/hevc/library_register.h | 62 + openmax/component/video/dec/mpeg2/Android.mk | 87 + .../video/dec/mpeg2/Exynos_OMX_Mpeg2dec.c | 3439 ++++++++++ .../video/dec/mpeg2/Exynos_OMX_Mpeg2dec.h | 97 + openmax/component/video/dec/mpeg2/NOTICE | 190 + .../video/dec/mpeg2/library_register.c | 59 + .../video/dec/mpeg2/library_register.h | 59 + openmax/component/video/dec/mpeg4/Android.mk | 87 + .../video/dec/mpeg4/Exynos_OMX_Mpeg4dec.c | 3643 +++++++++++ .../video/dec/mpeg4/Exynos_OMX_Mpeg4dec.h | 123 + openmax/component/video/dec/mpeg4/NOTICE | 190 + .../video/dec/mpeg4/library_register.c | 69 + .../video/dec/mpeg4/library_register.h | 72 + openmax/component/video/dec/vc1/Android.mk | 87 + .../video/dec/vc1/Exynos_OMX_Wmvdec.c | 3646 +++++++++++ .../video/dec/vc1/Exynos_OMX_Wmvdec.h | 108 + openmax/component/video/dec/vc1/NOTICE | 190 + .../video/dec/vc1/library_register.c | 59 + .../video/dec/vc1/library_register.h | 59 + openmax/component/video/dec/vp8/Android.mk | 88 + .../video/dec/vp8/Exynos_OMX_Vp8dec.c | 3353 ++++++++++ .../video/dec/vp8/Exynos_OMX_Vp8dec.h | 96 + openmax/component/video/dec/vp8/NOTICE | 190 + .../video/dec/vp8/library_register.c | 59 + .../video/dec/vp8/library_register.h | 60 + openmax/component/video/dec/vp9/Android.mk | 88 + .../video/dec/vp9/Exynos_OMX_Vp9dec.c | 3684 +++++++++++ .../video/dec/vp9/Exynos_OMX_Vp9dec.h | 97 + openmax/component/video/dec/vp9/NOTICE | 190 + .../video/dec/vp9/library_register.c | 65 + .../video/dec/vp9/library_register.h | 63 + openmax/component/video/enc/Android.mk | 73 + openmax/component/video/enc/Exynos_OMX_Venc.c | 2272 +++++++ openmax/component/video/enc/Exynos_OMX_Venc.h | 184 + .../video/enc/Exynos_OMX_VencControl.c | 2712 ++++++++ .../video/enc/Exynos_OMX_VencControl.h | 118 + openmax/component/video/enc/NOTICE | 190 + openmax/component/video/enc/h264/Android.mk | 89 + .../video/enc/h264/Exynos_OMX_H264enc.c | 4567 +++++++++++++ .../video/enc/h264/Exynos_OMX_H264enc.h | 135 + openmax/component/video/enc/h264/NOTICE | 190 + .../video/enc/h264/library_register.c | 60 + .../video/enc/h264/library_register.h | 57 + .../component/video/enc/h264wfd/Android.mk | 74 + .../enc/h264wfd/Exynos_OMX_H264enc_wfd.c | 5747 +++++++++++++++++ .../enc/h264wfd/Exynos_OMX_H264enc_wfd.h | 133 + openmax/component/video/enc/h264wfd/NOTICE | 190 + .../video/enc/h264wfd/library_register.c | 62 + .../video/enc/h264wfd/library_register.h | 58 + openmax/component/video/enc/hevc/Android.mk | 88 + .../video/enc/hevc/Exynos_OMX_HEVCenc.c | 4545 +++++++++++++ .../video/enc/hevc/Exynos_OMX_HEVCenc.h | 109 + openmax/component/video/enc/hevc/NOTICE | 190 + .../video/enc/hevc/library_register.c | 61 + .../video/enc/hevc/library_register.h | 58 + .../component/video/enc/hevcwfd/Android.mk | 74 + .../enc/hevcwfd/Exynos_OMX_HEVCenc_wfd.c | 5730 ++++++++++++++++ .../enc/hevcwfd/Exynos_OMX_HEVCenc_wfd.h | 132 + openmax/component/video/enc/hevcwfd/NOTICE | 190 + .../video/enc/hevcwfd/library_register.c | 62 + .../video/enc/hevcwfd/library_register.h | 58 + openmax/component/video/enc/mpeg4/Android.mk | 79 + .../video/enc/mpeg4/Exynos_OMX_Mpeg4enc.c | 3638 +++++++++++ .../video/enc/mpeg4/Exynos_OMX_Mpeg4enc.h | 99 + openmax/component/video/enc/mpeg4/NOTICE | 190 + .../video/enc/mpeg4/library_register.c | 62 + .../video/enc/mpeg4/library_register.h | 59 + openmax/component/video/enc/vp8/Android.mk | 80 + .../video/enc/vp8/Exynos_OMX_Vp8enc.c | 3565 ++++++++++ .../video/enc/vp8/Exynos_OMX_Vp8enc.h | 94 + openmax/component/video/enc/vp8/NOTICE | 190 + .../video/enc/vp8/library_register.c | 58 + .../video/enc/vp8/library_register.h | 56 + openmax/component/video/enc/vp9/Android.mk | 79 + .../video/enc/vp9/Exynos_OMX_Vp9enc.c | 3530 ++++++++++ .../video/enc/vp9/Exynos_OMX_Vp9enc.h | 94 + openmax/component/video/enc/vp9/NOTICE | 190 + .../video/enc/vp9/library_register.c | 58 + .../video/enc/vp9/library_register.h | 56 + openmax/core/Android.mk | 92 + openmax/core/Exynos_OMX_Component_Register.c | 833 +++ openmax/core/Exynos_OMX_Component_Register.h | 75 + openmax/core/Exynos_OMX_Core.c | 488 ++ openmax/core/Exynos_OMX_Core.h | 77 + openmax/core/NOTICE | 190 + openmax/include/exynos/Exynos_OMX_Def.h | 1298 ++++ openmax/include/exynos/Exynos_OMX_Macros.h | 137 + openmax/include/khronos/OMX_Audio.h | 1311 ++++ openmax/include/khronos/OMX_Component.h | 579 ++ openmax/include/khronos/OMX_ComponentExt.h | 61 + openmax/include/khronos/OMX_ContentPipe.h | 195 + openmax/include/khronos/OMX_Core.h | 1431 ++++ openmax/include/khronos/OMX_CoreExt.h | 73 + openmax/include/khronos/OMX_IVCommon.h | 920 +++ openmax/include/khronos/OMX_Image.h | 328 + openmax/include/khronos/OMX_ImageExt.h | 55 + openmax/include/khronos/OMX_Index.h | 258 + openmax/include/khronos/OMX_IndexExt.h | 90 + openmax/include/khronos/OMX_Other.h | 337 + openmax/include/khronos/OMX_Types.h | 359 + openmax/include/khronos/OMX_Video.h | 1060 +++ openmax/include/khronos/OMX_VideoExt.h | 123 + openmax/osal/Android.mk | 225 + openmax/osal/Exynos_OSAL_Android.cpp | 5018 ++++++++++++++ openmax/osal/Exynos_OSAL_Android.h | 79 + openmax/osal/Exynos_OSAL_ETC.c | 1445 +++++ openmax/osal/Exynos_OSAL_ETC.h | 119 + openmax/osal/Exynos_OSAL_Event.c | 220 + openmax/osal/Exynos_OSAL_Event.h | 61 + openmax/osal/Exynos_OSAL_ImageConverter.cpp | 403 ++ openmax/osal/Exynos_OSAL_ImageConverter.h | 44 + openmax/osal/Exynos_OSAL_Library.c | 108 + openmax/osal/Exynos_OSAL_Library.h | 48 + openmax/osal/Exynos_OSAL_Log.c | 126 + openmax/osal/Exynos_OSAL_Log.h | 86 + openmax/osal/Exynos_OSAL_Memory.c | 92 + openmax/osal/Exynos_OSAL_Memory.h | 51 + openmax/osal/Exynos_OSAL_Mutex.c | 90 + openmax/osal/Exynos_OSAL_Mutex.h | 47 + openmax/osal/Exynos_OSAL_Platform.h | 69 + openmax/osal/Exynos_OSAL_Queue.c | 201 + openmax/osal/Exynos_OSAL_Queue.h | 68 + openmax/osal/Exynos_OSAL_Semaphore.c | 161 + openmax/osal/Exynos_OSAL_Semaphore.h | 50 + openmax/osal/Exynos_OSAL_SharedMemory.c | 546 ++ openmax/osal/Exynos_OSAL_SharedMemory.h | 61 + openmax/osal/Exynos_OSAL_SkypeHD.c | 1020 +++ openmax/osal/Exynos_OSAL_SkypeHD.h | 62 + openmax/osal/Exynos_OSAL_Thread.c | 184 + openmax/osal/Exynos_OSAL_Thread.h | 49 + openmax/osal/NOTICE | 190 + videocodec/Android.mk | 74 + videocodec/ExynosVideoInterface.c | 119 + videocodec/NOTICE | 190 + videocodec/dec/ExynosVideoDecoder.c | 3457 ++++++++++ videocodec/enc/ExynosVideoEncoder.c | 3662 +++++++++++ videocodec/include/ExynosVideoApi.h | 881 +++ videocodec/include/ExynosVideoDec.h | 36 + videocodec/include/ExynosVideoEnc.h | 83 + videocodec/mfc_headers/exynos_mfc_media.h | 275 + videocodec/osal/ExynosVideo_OSAL.c | 2163 +++++++ videocodec/osal/include/ExynosVideo_OSAL.h | 233 + .../osal/include/ExynosVideo_OSAL_Dec.h | 46 + .../osal/include/ExynosVideo_OSAL_Enc.h | 52 + 217 files changed, 127074 insertions(+) create mode 100644 Android.mk create mode 100644 NOTICE create mode 100644 openmax/Android.mk create mode 100644 openmax/NOTICE create mode 100644 openmax/component/audio/common/Android.mk create mode 100644 openmax/component/audio/common/Exynos_OMX_ABasecomponent.c create mode 100644 openmax/component/audio/common/Exynos_OMX_ABasecomponent.h create mode 100644 openmax/component/audio/common/Exynos_OMX_ABaseport.c create mode 100644 openmax/component/audio/common/Exynos_OMX_ABaseport.h create mode 100644 openmax/component/audio/common/NOTICE create mode 100644 openmax/component/audio/dec/Android.mk create mode 100644 openmax/component/audio/dec/Exynos_OMX_Adec.c create mode 100644 openmax/component/audio/dec/Exynos_OMX_Adec.h create mode 100644 openmax/component/audio/dec/NOTICE create mode 100644 openmax/component/audio/dec/mp3/Android.mk create mode 100644 openmax/component/audio/dec/mp3/Exynos_OMX_Mp3dec.c create mode 100644 openmax/component/audio/dec/mp3/Exynos_OMX_Mp3dec.h create mode 100644 openmax/component/audio/dec/mp3/NOTICE create mode 100644 openmax/component/audio/dec/mp3/library_register.c create mode 100644 openmax/component/audio/dec/mp3/library_register.h create mode 100644 openmax/component/audio/dec/wma/Android.mk create mode 100644 openmax/component/audio/dec/wma/Exynos_OMX_Wmadec.c create mode 100644 openmax/component/audio/dec/wma/Exynos_OMX_Wmadec.h create mode 100644 openmax/component/audio/dec/wma/NOTICE create mode 100644 openmax/component/audio/dec/wma/library_register.c create mode 100644 openmax/component/audio/dec/wma/library_register.h create mode 100644 openmax/component/audio/seiren_dec/Android.mk create mode 100644 openmax/component/audio/seiren_dec/Exynos_OMX_Adec.c create mode 100644 openmax/component/audio/seiren_dec/Exynos_OMX_Adec.h create mode 100644 openmax/component/audio/seiren_dec/NOTICE create mode 100644 openmax/component/audio/seiren_dec/aac/Android.mk create mode 100644 openmax/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.c create mode 100644 openmax/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.h create mode 100644 openmax/component/audio/seiren_dec/aac/NOTICE create mode 100644 openmax/component/audio/seiren_dec/aac/library_register.c create mode 100644 openmax/component/audio/seiren_dec/aac/library_register.h create mode 100644 openmax/component/audio/seiren_dec/flac/Android.mk create mode 100644 openmax/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.c create mode 100644 openmax/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.h create mode 100644 openmax/component/audio/seiren_dec/flac/NOTICE create mode 100644 openmax/component/audio/seiren_dec/flac/library_register.c create mode 100644 openmax/component/audio/seiren_dec/flac/library_register.h create mode 100644 openmax/component/audio/seiren_dec/mp3/Android.mk create mode 100644 openmax/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.c create mode 100644 openmax/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.h create mode 100644 openmax/component/audio/seiren_dec/mp3/NOTICE create mode 100644 openmax/component/audio/seiren_dec/mp3/library_register.c create mode 100644 openmax/component/audio/seiren_dec/mp3/library_register.h create mode 100644 openmax/component/common/Android.mk create mode 100644 openmax/component/common/Exynos_OMX_Basecomponent.c create mode 100644 openmax/component/common/Exynos_OMX_Basecomponent.h create mode 100644 openmax/component/common/Exynos_OMX_Baseport.c create mode 100644 openmax/component/common/Exynos_OMX_Baseport.h create mode 100644 openmax/component/common/Exynos_OMX_Resourcemanager.c create mode 100644 openmax/component/common/Exynos_OMX_Resourcemanager.h create mode 100644 openmax/component/common/NOTICE create mode 100644 openmax/component/video/dec/Android.mk create mode 100644 openmax/component/video/dec/Exynos_OMX_Vdec.c create mode 100644 openmax/component/video/dec/Exynos_OMX_Vdec.h create mode 100644 openmax/component/video/dec/Exynos_OMX_VdecControl.c create mode 100644 openmax/component/video/dec/Exynos_OMX_VdecControl.h create mode 100644 openmax/component/video/dec/NOTICE create mode 100644 openmax/component/video/dec/h264/Android.mk create mode 100644 openmax/component/video/dec/h264/Exynos_OMX_H264dec.c create mode 100644 openmax/component/video/dec/h264/Exynos_OMX_H264dec.h create mode 100644 openmax/component/video/dec/h264/NOTICE create mode 100644 openmax/component/video/dec/h264/library_register.c create mode 100644 openmax/component/video/dec/h264/library_register.h create mode 100644 openmax/component/video/dec/hevc/Android.mk create mode 100644 openmax/component/video/dec/hevc/Exynos_OMX_HEVCdec.c create mode 100644 openmax/component/video/dec/hevc/Exynos_OMX_HEVCdec.h create mode 100644 openmax/component/video/dec/hevc/NOTICE create mode 100644 openmax/component/video/dec/hevc/library_register.c create mode 100644 openmax/component/video/dec/hevc/library_register.h create mode 100644 openmax/component/video/dec/mpeg2/Android.mk create mode 100644 openmax/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.c create mode 100644 openmax/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.h create mode 100644 openmax/component/video/dec/mpeg2/NOTICE create mode 100644 openmax/component/video/dec/mpeg2/library_register.c create mode 100644 openmax/component/video/dec/mpeg2/library_register.h create mode 100644 openmax/component/video/dec/mpeg4/Android.mk create mode 100644 openmax/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.c create mode 100644 openmax/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.h create mode 100644 openmax/component/video/dec/mpeg4/NOTICE create mode 100644 openmax/component/video/dec/mpeg4/library_register.c create mode 100644 openmax/component/video/dec/mpeg4/library_register.h create mode 100644 openmax/component/video/dec/vc1/Android.mk create mode 100644 openmax/component/video/dec/vc1/Exynos_OMX_Wmvdec.c create mode 100644 openmax/component/video/dec/vc1/Exynos_OMX_Wmvdec.h create mode 100644 openmax/component/video/dec/vc1/NOTICE create mode 100644 openmax/component/video/dec/vc1/library_register.c create mode 100644 openmax/component/video/dec/vc1/library_register.h create mode 100644 openmax/component/video/dec/vp8/Android.mk create mode 100644 openmax/component/video/dec/vp8/Exynos_OMX_Vp8dec.c create mode 100644 openmax/component/video/dec/vp8/Exynos_OMX_Vp8dec.h create mode 100644 openmax/component/video/dec/vp8/NOTICE create mode 100644 openmax/component/video/dec/vp8/library_register.c create mode 100644 openmax/component/video/dec/vp8/library_register.h create mode 100644 openmax/component/video/dec/vp9/Android.mk create mode 100644 openmax/component/video/dec/vp9/Exynos_OMX_Vp9dec.c create mode 100644 openmax/component/video/dec/vp9/Exynos_OMX_Vp9dec.h create mode 100644 openmax/component/video/dec/vp9/NOTICE create mode 100644 openmax/component/video/dec/vp9/library_register.c create mode 100644 openmax/component/video/dec/vp9/library_register.h create mode 100644 openmax/component/video/enc/Android.mk create mode 100644 openmax/component/video/enc/Exynos_OMX_Venc.c create mode 100644 openmax/component/video/enc/Exynos_OMX_Venc.h create mode 100644 openmax/component/video/enc/Exynos_OMX_VencControl.c create mode 100644 openmax/component/video/enc/Exynos_OMX_VencControl.h create mode 100644 openmax/component/video/enc/NOTICE create mode 100644 openmax/component/video/enc/h264/Android.mk create mode 100644 openmax/component/video/enc/h264/Exynos_OMX_H264enc.c create mode 100644 openmax/component/video/enc/h264/Exynos_OMX_H264enc.h create mode 100644 openmax/component/video/enc/h264/NOTICE create mode 100644 openmax/component/video/enc/h264/library_register.c create mode 100644 openmax/component/video/enc/h264/library_register.h create mode 100644 openmax/component/video/enc/h264wfd/Android.mk create mode 100644 openmax/component/video/enc/h264wfd/Exynos_OMX_H264enc_wfd.c create mode 100644 openmax/component/video/enc/h264wfd/Exynos_OMX_H264enc_wfd.h create mode 100644 openmax/component/video/enc/h264wfd/NOTICE create mode 100644 openmax/component/video/enc/h264wfd/library_register.c create mode 100644 openmax/component/video/enc/h264wfd/library_register.h create mode 100644 openmax/component/video/enc/hevc/Android.mk create mode 100644 openmax/component/video/enc/hevc/Exynos_OMX_HEVCenc.c create mode 100644 openmax/component/video/enc/hevc/Exynos_OMX_HEVCenc.h create mode 100644 openmax/component/video/enc/hevc/NOTICE create mode 100644 openmax/component/video/enc/hevc/library_register.c create mode 100644 openmax/component/video/enc/hevc/library_register.h create mode 100644 openmax/component/video/enc/hevcwfd/Android.mk create mode 100644 openmax/component/video/enc/hevcwfd/Exynos_OMX_HEVCenc_wfd.c create mode 100644 openmax/component/video/enc/hevcwfd/Exynos_OMX_HEVCenc_wfd.h create mode 100644 openmax/component/video/enc/hevcwfd/NOTICE create mode 100644 openmax/component/video/enc/hevcwfd/library_register.c create mode 100644 openmax/component/video/enc/hevcwfd/library_register.h create mode 100644 openmax/component/video/enc/mpeg4/Android.mk create mode 100644 openmax/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.c create mode 100644 openmax/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.h create mode 100644 openmax/component/video/enc/mpeg4/NOTICE create mode 100644 openmax/component/video/enc/mpeg4/library_register.c create mode 100644 openmax/component/video/enc/mpeg4/library_register.h create mode 100644 openmax/component/video/enc/vp8/Android.mk create mode 100644 openmax/component/video/enc/vp8/Exynos_OMX_Vp8enc.c create mode 100644 openmax/component/video/enc/vp8/Exynos_OMX_Vp8enc.h create mode 100644 openmax/component/video/enc/vp8/NOTICE create mode 100644 openmax/component/video/enc/vp8/library_register.c create mode 100644 openmax/component/video/enc/vp8/library_register.h create mode 100644 openmax/component/video/enc/vp9/Android.mk create mode 100644 openmax/component/video/enc/vp9/Exynos_OMX_Vp9enc.c create mode 100644 openmax/component/video/enc/vp9/Exynos_OMX_Vp9enc.h create mode 100644 openmax/component/video/enc/vp9/NOTICE create mode 100644 openmax/component/video/enc/vp9/library_register.c create mode 100644 openmax/component/video/enc/vp9/library_register.h create mode 100644 openmax/core/Android.mk create mode 100644 openmax/core/Exynos_OMX_Component_Register.c create mode 100644 openmax/core/Exynos_OMX_Component_Register.h create mode 100644 openmax/core/Exynos_OMX_Core.c create mode 100644 openmax/core/Exynos_OMX_Core.h create mode 100644 openmax/core/NOTICE create mode 100644 openmax/include/exynos/Exynos_OMX_Def.h create mode 100644 openmax/include/exynos/Exynos_OMX_Macros.h create mode 100644 openmax/include/khronos/OMX_Audio.h create mode 100644 openmax/include/khronos/OMX_Component.h create mode 100644 openmax/include/khronos/OMX_ComponentExt.h create mode 100644 openmax/include/khronos/OMX_ContentPipe.h create mode 100644 openmax/include/khronos/OMX_Core.h create mode 100644 openmax/include/khronos/OMX_CoreExt.h create mode 100644 openmax/include/khronos/OMX_IVCommon.h create mode 100644 openmax/include/khronos/OMX_Image.h create mode 100644 openmax/include/khronos/OMX_ImageExt.h create mode 100644 openmax/include/khronos/OMX_Index.h create mode 100644 openmax/include/khronos/OMX_IndexExt.h create mode 100644 openmax/include/khronos/OMX_Other.h create mode 100644 openmax/include/khronos/OMX_Types.h create mode 100644 openmax/include/khronos/OMX_Video.h create mode 100644 openmax/include/khronos/OMX_VideoExt.h create mode 100644 openmax/osal/Android.mk create mode 100644 openmax/osal/Exynos_OSAL_Android.cpp create mode 100644 openmax/osal/Exynos_OSAL_Android.h create mode 100644 openmax/osal/Exynos_OSAL_ETC.c create mode 100644 openmax/osal/Exynos_OSAL_ETC.h create mode 100644 openmax/osal/Exynos_OSAL_Event.c create mode 100644 openmax/osal/Exynos_OSAL_Event.h create mode 100644 openmax/osal/Exynos_OSAL_ImageConverter.cpp create mode 100644 openmax/osal/Exynos_OSAL_ImageConverter.h create mode 100644 openmax/osal/Exynos_OSAL_Library.c create mode 100644 openmax/osal/Exynos_OSAL_Library.h create mode 100644 openmax/osal/Exynos_OSAL_Log.c create mode 100644 openmax/osal/Exynos_OSAL_Log.h create mode 100644 openmax/osal/Exynos_OSAL_Memory.c create mode 100644 openmax/osal/Exynos_OSAL_Memory.h create mode 100644 openmax/osal/Exynos_OSAL_Mutex.c create mode 100644 openmax/osal/Exynos_OSAL_Mutex.h create mode 100644 openmax/osal/Exynos_OSAL_Platform.h create mode 100644 openmax/osal/Exynos_OSAL_Queue.c create mode 100644 openmax/osal/Exynos_OSAL_Queue.h create mode 100644 openmax/osal/Exynos_OSAL_Semaphore.c create mode 100644 openmax/osal/Exynos_OSAL_Semaphore.h create mode 100644 openmax/osal/Exynos_OSAL_SharedMemory.c create mode 100644 openmax/osal/Exynos_OSAL_SharedMemory.h create mode 100644 openmax/osal/Exynos_OSAL_SkypeHD.c create mode 100644 openmax/osal/Exynos_OSAL_SkypeHD.h create mode 100644 openmax/osal/Exynos_OSAL_Thread.c create mode 100644 openmax/osal/Exynos_OSAL_Thread.h create mode 100644 openmax/osal/NOTICE create mode 100644 videocodec/Android.mk create mode 100644 videocodec/ExynosVideoInterface.c create mode 100644 videocodec/NOTICE create mode 100644 videocodec/dec/ExynosVideoDecoder.c create mode 100644 videocodec/enc/ExynosVideoEncoder.c create mode 100644 videocodec/include/ExynosVideoApi.h create mode 100644 videocodec/include/ExynosVideoDec.h create mode 100644 videocodec/include/ExynosVideoEnc.h create mode 100644 videocodec/mfc_headers/exynos_mfc_media.h create mode 100644 videocodec/osal/ExynosVideo_OSAL.c create mode 100644 videocodec/osal/include/ExynosVideo_OSAL.h create mode 100644 videocodec/osal/include/ExynosVideo_OSAL_Dec.h create mode 100644 videocodec/osal/include/ExynosVideo_OSAL_Enc.h diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..3625068 --- /dev/null +++ b/Android.mk @@ -0,0 +1,16 @@ +ifneq ($(filter exynos, $(TARGET_SOC_NAME)),) +openmax_dirs := \ + videocodec \ + openmax + +include $(call all-named-subdir-makefiles,$(openmax_dirs)) +else +PREFIX := $(shell echo $(TARGET_BOARD_PLATFORM) | head -c 6) +ifneq ($(filter exynos, $(PREFIX)),) +openmax_dirs := \ + videocodec \ + openmax + +include $(call all-named-subdir-makefiles,$(openmax_dirs)) +endif +endif diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/Android.mk b/openmax/Android.mk new file mode 100644 index 0000000..af59183 --- /dev/null +++ b/openmax/Android.mk @@ -0,0 +1,81 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +BOARD_USE_ANDROID := true +BOARD_USE_SKYPE_HD := true + +# Set to false to use Android's OMX header files +BOARD_USE_KHRONOS_OMX_HEADER := false + +ifeq ($(BOARD_USE_ANDROID), false) +BOARD_USE_KHRONOS_OMX_HEADER := true +endif + +EXYNOS_OMX_SUPPORT_TUNNELING := false +EXYNOS_OMX_SUPPORT_EGL_IMAGE := false + +EXYNOS_OMX_TOP := $(LOCAL_PATH) + +EXYNOS_OMX_INC := $(EXYNOS_OMX_TOP)/include +EXYNOS_OMX_COMPONENT := $(EXYNOS_OMX_TOP)/component + +EXYNOS_VIDEO_CODEC := \ + $(EXYNOS_OMX_TOP)/../videocodec +ifeq ($(BOARD_USE_ALP_AUDIO), true) + ifeq ($(BOARD_USE_SEIREN_AUDIO), true) + EXYNOS_AUDIO_CODEC += \ + hardware/samsung_slsi/exynos/libseiren + else + EXYNOS_AUDIO_CODEC += \ + hardware/samsung_slsi/exynos/libsrp + endif +endif + +include $(EXYNOS_OMX_TOP)/osal/Android.mk +include $(EXYNOS_OMX_TOP)/core/Android.mk + +include $(EXYNOS_OMX_COMPONENT)/common/Android.mk +include $(EXYNOS_OMX_COMPONENT)/video/dec/Android.mk +include $(EXYNOS_OMX_COMPONENT)/video/dec/h264/Android.mk +include $(EXYNOS_OMX_COMPONENT)/video/dec/hevc/Android.mk +include $(EXYNOS_OMX_COMPONENT)/video/dec/mpeg4/Android.mk +include $(EXYNOS_OMX_COMPONENT)/video/dec/vp8/Android.mk +include $(EXYNOS_OMX_COMPONENT)/video/dec/mpeg2/Android.mk +include $(EXYNOS_OMX_COMPONENT)/video/dec/vc1/Android.mk + +include $(EXYNOS_OMX_COMPONENT)/video/enc/Android.mk +include $(EXYNOS_OMX_COMPONENT)/video/enc/h264/Android.mk +include $(EXYNOS_OMX_COMPONENT)/video/enc/mpeg4/Android.mk +include $(EXYNOS_OMX_COMPONENT)/video/enc/vp8/Android.mk + +ifeq ($(BOARD_USE_HEVCENC_SUPPORT), true) +include $(EXYNOS_OMX_COMPONENT)/video/enc/hevc/Android.mk +endif +ifeq ($(BOARD_USE_VP9DEC_SUPPORT), true) +include $(EXYNOS_OMX_COMPONENT)/video/dec/vp9/Android.mk +endif +ifeq ($(BOARD_USE_VP9ENC_SUPPORT), true) +include $(EXYNOS_OMX_COMPONENT)/video/enc/vp9/Android.mk +endif +ifeq ($(BOARD_USE_WFDENC_SUPPORT), true) +include $(EXYNOS_OMX_COMPONENT)/video/enc/h264wfd/Android.mk +include $(EXYNOS_OMX_COMPONENT)/video/enc/hevcwfd/Android.mk +endif + +ifeq ($(BOARD_USE_ALP_AUDIO), true) + include $(EXYNOS_OMX_COMPONENT)/audio/common/Android.mk + ifeq ($(BOARD_USE_SEIREN_AUDIO), true) + include $(EXYNOS_OMX_COMPONENT)/audio/seiren_dec/Android.mk + include $(EXYNOS_OMX_COMPONENT)/audio/seiren_dec/mp3/Android.mk + include $(EXYNOS_OMX_COMPONENT)/audio/seiren_dec/aac/Android.mk + include $(EXYNOS_OMX_COMPONENT)/audio/seiren_dec/flac/Android.mk + else + include $(EXYNOS_OMX_COMPONENT)/audio/dec/Android.mk + include $(EXYNOS_OMX_COMPONENT)/audio/dec/mp3/Android.mk + endif +endif + +ifeq ($(BOARD_USE_WMA_CODEC), true) +include $(EXYNOS_OMX_COMPONENT)/audio/dec/wma/Android.mk +endif diff --git a/openmax/NOTICE b/openmax/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/audio/common/Android.mk b/openmax/component/audio/common/Android.mk new file mode 100644 index 0000000..60dadb4 --- /dev/null +++ b/openmax/component/audio/common/Android.mk @@ -0,0 +1,36 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_ABasecomponent.c \ + Exynos_OMX_ABaseport.c + +LOCAL_MODULE := libExynosOMX_ABasecomponent +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +LOCAL_STATIC_LIBRARIES := libExynosOMX_OSAL +LOCAL_SHARED_LIBRARIES := libcutils libutils + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(EXYNOS_OMX_SUPPORT_EGL_IMAGE), true) +LOCAL_CFLAGS += -DEGL_IMAGE_SUPPORT +endif + +include $(BUILD_STATIC_LIBRARY) diff --git a/openmax/component/audio/common/Exynos_OMX_ABasecomponent.c b/openmax/component/audio/common/Exynos_OMX_ABasecomponent.c new file mode 100644 index 0000000..d3d64a8 --- /dev/null +++ b/openmax/component/audio/common/Exynos_OMX_ABasecomponent.c @@ -0,0 +1,1727 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_ABasecomponent.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Event.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OMX_ABaseport.h" +#include "Exynos_OMX_ABasecomponent.h" +#include "Exynos_OMX_Resourcemanager.h" +#include "Exynos_OMX_Macros.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_ABASE_COMP" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +static OMX_ERRORTYPE Exynos_SetPortFlush(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam); +static OMX_ERRORTYPE Exynos_SetPortEnable(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam); +static OMX_ERRORTYPE Exynos_SetPortDisable(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam); + +/* Change CHECK_SIZE_VERSION Macro */ +OMX_ERRORTYPE Exynos_OMX_Check_SizeVersion(OMX_PTR header, OMX_U32 size) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_VERSIONTYPE *version = NULL; + + if (header == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + version = (OMX_VERSIONTYPE*)((char*)header + sizeof(OMX_U32)); + if (*((OMX_U32*)header) != size) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_FUNC_TRACE, "[%s] nVersionMajor:%d, nVersionMinor:%d", __FUNCTION__, version->s.nVersionMajor, version->s.nVersionMinor); + + if ((version->s.nVersionMajor != VERSIONMAJOR_NUMBER) || + (version->s.nVersionMinor > VERSIONMINOR_NUMBER)) { + ret = OMX_ErrorVersionMismatch; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetComponentVersion( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STRING pComponentName, + OMX_OUT OMX_VERSIONTYPE *pComponentVersion, + OMX_OUT OMX_VERSIONTYPE *pSpecVersion, + OMX_OUT OMX_UUIDTYPE *pComponentUUID) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + unsigned long compUUID[3]; + + FunctionIn(); + + /* check parameters */ + if (hComponent == NULL || + pComponentName == NULL || pComponentVersion == NULL || + pSpecVersion == NULL || pComponentUUID == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Strcpy(pComponentName, pExynosComponent->componentName); + Exynos_OSAL_Memcpy(pComponentVersion, &(pExynosComponent->componentVersion), sizeof(OMX_VERSIONTYPE)); + Exynos_OSAL_Memcpy(pSpecVersion, &(pExynosComponent->specVersion), sizeof(OMX_VERSIONTYPE)); + + /* Fill UUID with handle address, PID and UID. + * This should guarantee uiniqness */ + compUUID[0] = (unsigned long)pOMXComponent; + compUUID[1] = (unsigned long)getpid(); + compUUID[2] = (unsigned long)getuid(); + Exynos_OSAL_Memcpy(*pComponentUUID, compUUID, 3 * sizeof(*compUUID)); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetState ( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STATETYPE *pState) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pState == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + *pState = pExynosComponent->currentState; + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentStateSet(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 messageParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_MESSAGE *message; + OMX_STATETYPE destState = messageParam; + OMX_STATETYPE currentState = pExynosComponent->currentState; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + unsigned int i = 0, j = 0; + int k = 0; + + FunctionIn(); + + /* check parameters */ + if (currentState == destState) { + ret = OMX_ErrorSameState; + goto EXIT; + } + if (currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] current:(%s) dest:(%s)", pExynosComponent, __FUNCTION__, stateString(currentState), stateString(destState)); + switch (destState) { + case OMX_StateInvalid: + switch (currentState) { + case OMX_StateWaitForResources: + Exynos_OMX_Out_WaitForResource(pOMXComponent); + case OMX_StateIdle: + case OMX_StateExecuting: + case OMX_StatePause: + case OMX_StateLoaded: + pExynosComponent->currentState = OMX_StateInvalid; + ret = pExynosComponent->exynos_BufferProcessTerminate(pOMXComponent); + + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].dataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].dataBuffer.bufferMutex = NULL; + + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].hPortMutex); + pExynosComponent->pExynosPort[i].hPortMutex = NULL; + } + + Exynos_OSAL_SignalTerminate(pExynosComponent->pauseEvent); + pExynosComponent->pauseEvent = NULL; + + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SemaphoreTerminate(pExynosComponent->pExynosPort[i].bufferSemID); + pExynosComponent->pExynosPort[i].bufferSemID = NULL; + } + + if (currentState != OMX_StateLoaded) + pExynosComponent->exynos_codec_componentTerminate(pOMXComponent); + + Exynos_OSAL_SignalSet(pExynosComponent->abendStateEvent); + + ret = OMX_ErrorInvalidState; + break; + default: + ret = OMX_ErrorInvalidState; + break; + } + break; + case OMX_StateLoaded: + switch (currentState) { + case OMX_StateIdle: + for(i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateDisabling; + + ret = pExynosComponent->exynos_BufferProcessTerminate(pOMXComponent); + + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].dataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].dataBuffer.bufferMutex = NULL; + + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].hPortMutex); + pExynosComponent->pExynosPort[i].hPortMutex = NULL; + } + + Exynos_OSAL_SignalTerminate(pExynosComponent->pauseEvent); + pExynosComponent->pauseEvent = NULL; + + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SemaphoreTerminate(pExynosComponent->pExynosPort[i].bufferSemID); + pExynosComponent->pExynosPort[i].bufferSemID = NULL; + } + + pExynosComponent->exynos_codec_componentTerminate(pOMXComponent); + + for (i = 0; i < (pExynosComponent->portParam.nPorts); i++) { + pExynosPort = (pExynosComponent->pExynosPort + i); +#ifdef TUNNELING_SUPPORT + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + while (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > 0) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message != NULL) + Exynos_OSAL_Free(message); + } + ret = pExynosComponent->exynos_FreeTunnelBuffer(pExynosPort, i); + if (OMX_ErrorNone != ret) { + goto EXIT; + } + } else +#endif + { + if (CHECK_PORT_ENABLED(pExynosPort)) { + if (pExynosPort->assignedBufferNum > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port is waiting for unloadedResource", + pExynosComponent, __FUNCTION__, + (i == INPUT_PORT_INDEX)? "input":"output"); + Exynos_OSAL_SemaphoreWait(pExynosPort->unloadedResource); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] unloadedResource about %s port is posted", + pExynosComponent, __FUNCTION__, + (i == INPUT_PORT_INDEX)? "input":"output"); + } + + while (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > 0) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message != NULL) + Exynos_OSAL_Free(message); + } + + Exynos_OSAL_Set_SemaphoreCount(pExynosPort->unloadedResource, 0); + } + } + + if (pExynosComponent->abendState != OMX_TRUE) + pExynosPort->portState = EXYNOS_OMX_PortStateLoaded; + } + + /* this signal will be handled by invalid state handling + if (pExynosComponent->abendState == OMX_TRUE) { + Exynos_OSAL_SignalSet(pExynosComponent->abendStateEvent); + goto EXIT; + } + */ + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateLoaded; + break; + case OMX_StateWaitForResources: + ret = Exynos_OMX_Out_WaitForResource(pOMXComponent); + pExynosComponent->currentState = OMX_StateLoaded; + break; + case OMX_StateExecuting: + case OMX_StatePause: + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StateIdle: + switch (currentState) { + case OMX_StateLoaded: + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &(pExynosComponent->pExynosPort[i]); + + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + +#ifdef TUNNELING_SUPPORT + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = pExynosComponent->exynos_AllocateTunnelBuffer(pExynosPort, i); + if (ret!=OMX_ErrorNone) + goto EXIT; + } + } else +#endif + { + if (CHECK_PORT_ENABLED(pExynosPort)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port is waiting for loadedResource", + pExynosComponent, __FUNCTION__, + (i == INPUT_PORT_INDEX)? "input":"output"); + Exynos_OSAL_SemaphoreWait(pExynosComponent->pExynosPort[i].loadedResource); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] loadedResource about %s port is posted", + pExynosComponent, __FUNCTION__, + (i == INPUT_PORT_INDEX)? "input":"output"); + + Exynos_OSAL_Set_SemaphoreCount(pExynosPort->loadedResource, 0); + } + } + + if (pExynosComponent->abendState != OMX_TRUE) + pExynosPort->portState = EXYNOS_OMX_PortStateIdle; + } + + if (pExynosComponent->abendState == OMX_TRUE) { + Exynos_OSAL_SignalSet(pExynosComponent->abendStateEvent); + goto EXIT; + } + + Exynos_OSAL_Get_Log_Property(); // For debuging, Function called when GetHandle function is success + ret = pExynosComponent->exynos_codec_componentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { +#ifdef TUNNELING_SUPPORT + /* + * if (CHECK_PORT_TUNNELED == OMX_TRUE) thenTunnel Buffer Free + */ +#endif + Exynos_OSAL_SignalSet(pExynosComponent->abendStateEvent); + goto EXIT; + } + + Exynos_OSAL_SignalCreate(&pExynosComponent->pauseEvent); + + for (i = 0; i < ALL_PORT_NUM; i++) { + ret = Exynos_OSAL_SemaphoreCreate(&pExynosComponent->pExynosPort[i].bufferSemID); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SemaphoreCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + } + for (i = 0; i < ALL_PORT_NUM; i++) { + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->pExynosPort[i].dataBuffer.bufferMutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to MutexCreate (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->pExynosPort[i].hPortMutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to MutexCreate (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + } + + ret = pExynosComponent->exynos_BufferProcessCreate(pOMXComponent); + if (ret != OMX_ErrorNone) { +#ifdef TUNNELING_SUPPORT + /* + * if (CHECK_PORT_TUNNELED == OMX_TRUE) thenTunnel Buffer Free + */ +#endif + Exynos_OSAL_SignalTerminate(pExynosComponent->pauseEvent); + pExynosComponent->pauseEvent = NULL; + + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].dataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].dataBuffer.bufferMutex = NULL; + + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].hPortMutex); + pExynosComponent->pExynosPort[i].hPortMutex = NULL; + } + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SemaphoreTerminate(pExynosComponent->pExynosPort[i].bufferSemID); + pExynosComponent->pExynosPort[i].bufferSemID = NULL; + } + + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateIdle; + break; + case OMX_StateExecuting: + Exynos_SetPortFlush(pExynosComponent, ALL_PORT_INDEX); + Exynos_OMX_BufferFlushProcess(pOMXComponent, ALL_PORT_INDEX, OMX_FALSE); + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateIdle; + break; + case OMX_StatePause: + Exynos_SetPortFlush(pExynosComponent, ALL_PORT_INDEX); + Exynos_OMX_BufferFlushProcess(pOMXComponent, ALL_PORT_INDEX, OMX_FALSE); + pExynosComponent->currentState = OMX_StateIdle; + break; + case OMX_StateWaitForResources: + pExynosComponent->currentState = OMX_StateIdle; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StateExecuting: + switch (currentState) { + case OMX_StateLoaded: + ret = OMX_ErrorIncorrectStateTransition; + break; + case OMX_StateIdle: + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort) && CHECK_PORT_ENABLED(pExynosPort)) { + for (j = 0; j < pExynosPort->tunnelBufferNum; j++) { + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[i].bufferSemID); + } + } + } + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateExecuting; + + Exynos_OSAL_SignalSet(pExynosComponent->pauseEvent); + break; + case OMX_StatePause: + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort) && CHECK_PORT_ENABLED(pExynosPort)) { + OMX_S32 semaValue = 0, cnt = 0; + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[i].bufferSemID, &semaValue); + if (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > semaValue) { + cnt = Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) - semaValue; + for (k = 0; k < cnt; k++) { + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[i].bufferSemID); + } + } + } + } + + pExynosComponent->currentState = OMX_StateExecuting; + + Exynos_OSAL_SignalSet(pExynosComponent->pauseEvent); + break; + case OMX_StateWaitForResources: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StatePause: + switch (currentState) { + case OMX_StateLoaded: + ret = OMX_ErrorIncorrectStateTransition; + break; + case OMX_StateIdle: + pExynosComponent->currentState = OMX_StatePause; + break; + case OMX_StateExecuting: + pExynosComponent->currentState = OMX_StatePause; + break; + case OMX_StateWaitForResources: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StateWaitForResources: + switch (currentState) { + case OMX_StateLoaded: + ret = Exynos_OMX_In_WaitForResource(pOMXComponent); + pExynosComponent->currentState = OMX_StateWaitForResources; + break; + case OMX_StateIdle: + case OMX_StateExecuting: + case OMX_StatePause: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + if (pExynosComponent->pCallbacks != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, OMX_CommandStateSet, + destState, NULL); + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + if (pExynosComponent->pCallbacks != NULL) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_MessageHandlerThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + OMX_U32 messageType = 0, portIndex = 0; + + FunctionIn(); + + if (threadData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + while (pExynosComponent->bExitMessageHandlerThread == OMX_FALSE) { + Exynos_OSAL_SemaphoreWait(pExynosComponent->msgSemaphoreHandle); + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosComponent->messageQ); + if (message != NULL) { + messageType = message->messageType; + switch (messageType) { + case OMX_CommandStateSet: + ret = Exynos_OMX_ComponentStateSet(pOMXComponent, message->messageParam); + break; + case OMX_CommandFlush: + Exynos_SetPortFlush(pExynosComponent, message->messageParam); + ret = Exynos_OMX_BufferFlushProcess(pOMXComponent, message->messageParam, OMX_TRUE); + break; + case OMX_CommandPortDisable: + Exynos_SetPortDisable(pExynosComponent, message->messageParam); + ret = Exynos_OMX_PortDisableProcess(pOMXComponent, message->messageParam); + break; + case OMX_CommandPortEnable: + Exynos_SetPortEnable(pExynosComponent, message->messageParam); + ret = Exynos_OMX_PortEnableProcess(pOMXComponent, message->messageParam); + break; + case OMX_CommandMarkBuffer: + portIndex = message->messageParam; + pExynosComponent->pExynosPort[portIndex].markType.hMarkTargetComponent = ((OMX_MARKTYPE *)message->pCmdData)->hMarkTargetComponent; + pExynosComponent->pExynosPort[portIndex].markType.pMarkData = ((OMX_MARKTYPE *)message->pCmdData)->pMarkData; + break; + case (OMX_COMMANDTYPE)EXYNOS_OMX_CommandComponentDeInit: + pExynosComponent->bExitMessageHandlerThread = OMX_TRUE; + break; + default: + break; + } + Exynos_OSAL_Free(message); + message = NULL; + } + } + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_SetPortFlush(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nPortIndex = nParam; + + OMX_U16 i = 0, cnt = 0, index = 0; + + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + if ((nPortIndex != ALL_PORT_INDEX) && + ((OMX_S32)nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateFlushing; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateFlushing; + } + } else { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + return ret; +} + +static OMX_ERRORTYPE Exynos_SetPortEnable(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nPortIndex = nParam; + + OMX_U16 i = 0; + + FunctionIn(); + + if ((nPortIndex != ALL_PORT_INDEX) && + ((OMX_S32)nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; + +} + +static OMX_ERRORTYPE Exynos_SetPortDisable(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nPortIndex = nParam; + + OMX_U16 i = 0; + + FunctionIn(); + + if ((nPortIndex != ALL_PORT_INDEX) && + ((OMX_S32)nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateDisabling; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateDisabling; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_SetMarkBuffer(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (nParam >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorIncorrectStateOperation; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE Exynos_StateSet(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_U32 destState = nParam; + OMX_U32 i = 0; + + if ((destState == OMX_StateIdle) && (pExynosComponent->currentState == OMX_StateLoaded)) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateLoadedToIdle; + + for(i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateEnabling; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateLoaded to OMX_StateIdle", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateLoaded) && (pExynosComponent->currentState == OMX_StateIdle)) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateIdleToLoaded; + + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateDisabling; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateLoaded", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateIdle) && (pExynosComponent->currentState == OMX_StateExecuting)) { + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + pExynosComponent->transientState = EXYNOS_OMX_TransStateExecutingToIdle; + + pExynosPort = &(pExynosComponent->pExynosPort[INPUT_PORT_INDEX]); + if ((pExynosPort->portDefinition.bEnabled == OMX_FALSE) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + pExynosPort->exceptionFlag = INVALID_STATE; + Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource); + } + + pExynosPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + if ((pExynosPort->portDefinition.bEnabled == OMX_FALSE) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + pExynosPort->exceptionFlag = INVALID_STATE; + Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource); + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateExecuting to OMX_StateIdle", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateIdle) && (pExynosComponent->currentState == OMX_StatePause)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StatePause to OMX_StateIdle", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateExecuting) && (pExynosComponent->currentState == OMX_StateIdle)) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateIdleToExecuting; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateExecuting", pExynosComponent, __FUNCTION__); + } else if (destState == OMX_StateInvalid) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateInvalid; + } + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE Exynos_OMX_CommandQueue( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COMMANDTYPE Cmd, + OMX_U32 nParam, + OMX_PTR pCmdData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_MESSAGE *command = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_MESSAGE)); + + if (command == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + command->messageType = (OMX_U32)Cmd; + command->messageParam = nParam; + command->pCmdData = pCmdData; + + ret = Exynos_OSAL_Queue(&pExynosComponent->messageQ, (void *)command); + if (ret != 0) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + ret = Exynos_OSAL_SemaphorePost(pExynosComponent->msgSemaphoreHandle); + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SendCommand( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_COMMANDTYPE Cmd, + OMX_IN OMX_U32 nParam, + OMX_IN OMX_PTR pCmdData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (Cmd) { + case OMX_CommandStateSet : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandStateSet", pExynosComponent, __FUNCTION__); + Exynos_StateSet(pExynosComponent, nParam); + break; + case OMX_CommandFlush : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandFlush", pExynosComponent, __FUNCTION__); + ret = Exynos_SetPortFlush(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + break; + case OMX_CommandPortDisable : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandPortDisable", pExynosComponent, __FUNCTION__); + ret = Exynos_SetPortDisable(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + break; + case OMX_CommandPortEnable : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandPortEnable", pExynosComponent, __FUNCTION__); + ret = Exynos_SetPortEnable(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + break; + case OMX_CommandMarkBuffer : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandMarkBuffer", pExynosComponent, __FUNCTION__); + ret = Exynos_SetMarkBuffer(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + break; + default: + break; + } + + ret = Exynos_OMX_CommandQueue(pExynosComponent, Cmd, nParam, pCmdData); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR ComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (ComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nParamIndex) { + case OMX_IndexParamAudioInit: + case OMX_IndexParamVideoInit: + case OMX_IndexParamImageInit: + case OMX_IndexParamOtherInit: + { + OMX_PORT_PARAM_TYPE *portParam = (OMX_PORT_PARAM_TYPE *)ComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(portParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + portParam->nPorts = 0; + portParam->nStartPortNumber = 0; + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)ComponentParameterStructure; + OMX_U32 portIndex = portDefinition->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(portDefinition, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + Exynos_OSAL_Memcpy(((char *)portDefinition) + nOffset, + ((char *)&pExynosPort->portDefinition) + nOffset, + portDefinition->nSize - nOffset); + } + break; + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *compPriority = (OMX_PRIORITYMGMTTYPE *)ComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(compPriority, sizeof(OMX_PRIORITYMGMTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + compPriority->nGroupID = pExynosComponent->compPriority.nGroupID; + compPriority->nGroupPriority = pExynosComponent->compPriority.nGroupPriority; + } + break; + + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplier = (OMX_PARAM_BUFFERSUPPLIERTYPE *)ComponentParameterStructure; + OMX_U32 portIndex = bufferSupplier->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort; + + if ((pExynosComponent->currentState == OMX_StateLoaded) || + (pExynosComponent->currentState == OMX_StateWaitForResources)) { + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(bufferSupplier, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + + + if (pExynosPort->portDefinition.eDir == OMX_DirInput) { + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyInput; + } else if (CHECK_PORT_TUNNELED(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyOutput; + } else { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyUnspecified; + } + } else { + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyOutput; + } else if (CHECK_PORT_TUNNELED(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyInput; + } else { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyUnspecified; + } + } + } + else + { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + break; + default: + { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + + ret = OMX_ErrorNone; + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR ComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (ComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + case OMX_IndexParamAudioInit: + case OMX_IndexParamVideoInit: + case OMX_IndexParamImageInit: + case OMX_IndexParamOtherInit: + { + OMX_PORT_PARAM_TYPE *portParam = (OMX_PORT_PARAM_TYPE *)ComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(portParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + /* ret = OMX_ErrorUndefined; */ + /* Exynos_OSAL_Memcpy(&pExynosComponent->portParam, portParam, sizeof(OMX_PORT_PARAM_TYPE)); */ + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)ComponentParameterStructure; + OMX_U32 portIndex = portDefinition->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(portDefinition, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + if (portDefinition->nBufferCountActual < pExynosPort->portDefinition.nBufferCountMin) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Memcpy(((char *)&pExynosPort->portDefinition) + nOffset, + ((char *)portDefinition) + nOffset, + portDefinition->nSize - nOffset); + } + break; + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *compPriority = (OMX_PRIORITYMGMTTYPE *)ComponentParameterStructure; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(compPriority, sizeof(OMX_PRIORITYMGMTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosComponent->compPriority.nGroupID = compPriority->nGroupID; + pExynosComponent->compPriority.nGroupPriority = compPriority->nGroupPriority; + } + break; + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplier = (OMX_PARAM_BUFFERSUPPLIERTYPE *)ComponentParameterStructure; + OMX_U32 portIndex = bufferSupplier->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(bufferSupplier, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyUnspecified) { + ret = OMX_ErrorNone; + goto EXIT; + } + if (CHECK_PORT_TUNNELED(pExynosPort) == 0) { + ret = OMX_ErrorNone; /*OMX_ErrorNone ?????*/ + goto EXIT; + } + + if (pExynosPort->portDefinition.eDir == OMX_DirInput) { + if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyInput) { + /* + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorNone; + } + */ + pExynosPort->tunnelFlags |= EXYNOS_TUNNEL_IS_SUPPLIER; + bufferSupplier->nPortIndex = pExynosPort->tunneledPort; + ret = OMX_SetParameter(pExynosPort->tunneledComponent, OMX_IndexParamCompBufferSupplier, bufferSupplier); + goto EXIT; + } else if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyOutput) { + ret = OMX_ErrorNone; + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + pExynosPort->tunnelFlags &= ~EXYNOS_TUNNEL_IS_SUPPLIER; + bufferSupplier->nPortIndex = pExynosPort->tunneledPort; + ret = OMX_SetParameter(pExynosPort->tunneledComponent, OMX_IndexParamCompBufferSupplier, bufferSupplier); + } + goto EXIT; + } + } else if (pExynosPort->portDefinition.eDir == OMX_DirOutput) { + if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyInput) { + ret = OMX_ErrorNone; + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + pExynosPort->tunnelFlags &= ~EXYNOS_TUNNEL_IS_SUPPLIER; + ret = OMX_ErrorNone; + } + goto EXIT; + } else if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyOutput) { + /* + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorNone; + } + */ + pExynosPort->tunnelFlags |= EXYNOS_TUNNEL_IS_SUPPLIER; + ret = OMX_ErrorNone; + goto EXIT; + } + } + } + break; + default: + { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + + ret = OMX_ErrorNone; + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_PTR Exynos_OMX_MakeDynamicConfigCMD( + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_PTR ret = NULL; + OMX_S32 nConfigStructureSize = 0; + + switch ((int)nIndex) { + case OMX_IndexConfigVideoIntraPeriod: + { + nConfigStructureSize = sizeof(OMX_U32); + ret = Exynos_OSAL_Malloc(sizeof(OMX_U32) + nConfigStructureSize); + } + break; + case OMX_IndexConfigVideoRoiInfo: + { + EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *pRoiInfo = (EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *)pComponentConfigStructure; + OMX_S32 nRoiMBInfoSize = 0; + nConfigStructureSize = *(OMX_U32 *)pComponentConfigStructure; + if (pRoiInfo->bUseRoiInfo == OMX_TRUE) + nRoiMBInfoSize = pRoiInfo->nRoiMBInfoSize; + ret = Exynos_OSAL_Malloc(sizeof(OMX_U32) + nConfigStructureSize + nRoiMBInfoSize); + if (ret != NULL) + Exynos_OSAL_Memcpy((OMX_PTR)((OMX_U8 *)ret + sizeof(OMX_U32) + nConfigStructureSize), pRoiInfo->pRoiMBInfo, nRoiMBInfoSize); + } + break; + default: + nConfigStructureSize = *(OMX_U32 *)pComponentConfigStructure; + ret = Exynos_OSAL_Malloc(sizeof(OMX_U32) + nConfigStructureSize); + break; + } + + if (ret != NULL) { + *((OMX_S32 *)ret) = (OMX_S32)nIndex; + Exynos_OSAL_Memcpy((OMX_PTR)((OMX_U8 *)ret + sizeof(OMX_U32)), pComponentConfigStructure, nConfigStructureSize); + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_INOUT OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if ((cParameterName == NULL) || (pIndexType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + ret = OMX_ErrorBadParameter; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SetCallbacks ( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_CALLBACKTYPE* pCallbacks, + OMX_IN OMX_PTR pAppData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pCallbacks == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + if (pExynosComponent->currentState != OMX_StateLoaded) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosComponent->pCallbacks = pCallbacks; + pExynosComponent->callbackData = pAppData; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +#ifdef EGL_IMAGE_SUPPORT +OMX_ERRORTYPE Exynos_OMX_UseEGLImage( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN void *eglImage) +{ + return OMX_ErrorNotImplemented; +} +#endif + +void Exynos_OMX_Component_abnormalTermination( + OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + int i = 0; + + FunctionIn(); + + if (hComponent == NULL) + goto EXIT; + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + if (pOMXComponent->pComponentPrivate == NULL) + goto EXIT; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + /* clear a msg command piled on queue */ + while(Exynos_OSAL_GetElemNum(&pExynosComponent->messageQ) > 0) + Exynos_OSAL_Free(Exynos_OSAL_Dequeue(&pExynosComponent->messageQ)); + + pExynosComponent->abendState = OMX_TRUE; + + /* post semaphore for msg handler thread, if it is waiting */ + for (i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + if ((pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle) || + (pExynosPort->portState == EXYNOS_OMX_PortStateInvalid) || + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { // enabling exception + pExynosComponent->abendState = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] post loadedResource about %s port", + pExynosComponent, __FUNCTION__, + (i == INPUT_PORT_INDEX)? "input":"output"); + Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource); + } + + if ((pExynosComponent->transientState == EXYNOS_OMX_TransStateIdleToLoaded) || + (pExynosPort->portState == EXYNOS_OMX_PortStateInvalid) || + (pExynosPort->portState == EXYNOS_OMX_PortStateFlushingForDisable) || + (pExynosPort->portState == EXYNOS_OMX_PortStateDisabling)) { // disabling exception + pExynosComponent->abendState = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] post unloadedResource about %s port", + pExynosComponent, __FUNCTION__, + (i == INPUT_PORT_INDEX)? "input":"output"); + Exynos_OSAL_SemaphorePost(pExynosPort->unloadedResource); + } + } + + /* change to invalid state except for Loaded state */ + if (pExynosComponent->transientState != EXYNOS_OMX_TransStateLoadedToIdle) + Exynos_OMX_SendCommand(hComponent, OMX_CommandStateSet, OMX_StateInvalid, NULL); + + /* wait for state change or LoaedToIdle handling */ + Exynos_OSAL_SignalWait(pExynosComponent->abendStateEvent, 1000); + Exynos_OSAL_SignalReset(pExynosComponent->abendStateEvent); + +EXIT: + FunctionOut(); + + return; +} + +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Constructor( + OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] lib version is %s", __FUNCTION__, IS_64BIT_OS? "64bit":"32bit"); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x)", __FUNCTION__, ret); + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BASECOMPONENT)); + if (pExynosComponent == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Malloc (0x%x)", __FUNCTION__, ret); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent, 0, sizeof(EXYNOS_OMX_BASECOMPONENT)); + pOMXComponent->pComponentPrivate = (OMX_PTR)pExynosComponent; + + ret = Exynos_OSAL_SemaphoreCreate(&pExynosComponent->msgSemaphoreHandle); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SemaphoreCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->compMutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to MutexCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + ret = Exynos_OSAL_SignalCreate(&pExynosComponent->abendStateEvent); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SignalCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pExynosComponent->bExitMessageHandlerThread = OMX_FALSE; + Exynos_OSAL_QueueCreate(&pExynosComponent->messageQ, MAX_QUEUE_ELEMENTS); + ret = Exynos_OSAL_ThreadCreate(&pExynosComponent->hMessageHandler, Exynos_OMX_MessageHandlerThread, pOMXComponent); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ThreadCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pOMXComponent->GetComponentVersion = &Exynos_OMX_GetComponentVersion; + pOMXComponent->SendCommand = &Exynos_OMX_SendCommand; + pOMXComponent->GetState = &Exynos_OMX_GetState; + pOMXComponent->SetCallbacks = &Exynos_OMX_SetCallbacks; + +#ifdef EGL_IMAGE_SUPPORT + pOMXComponent->UseEGLImage = &Exynos_OMX_UseEGLImage; +#endif + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Destructor( + OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 semaValue = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + Exynos_OMX_CommandQueue(pExynosComponent, (OMX_COMMANDTYPE)EXYNOS_OMX_CommandComponentDeInit, 0, NULL); + Exynos_OSAL_SleepMillisec(0); + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->msgSemaphoreHandle, &semaValue); + if (semaValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->msgSemaphoreHandle); + Exynos_OSAL_SemaphorePost(pExynosComponent->msgSemaphoreHandle); + + Exynos_OSAL_ThreadTerminate(pExynosComponent->hMessageHandler); + pExynosComponent->hMessageHandler = NULL; + + Exynos_OSAL_SignalTerminate(pExynosComponent->abendStateEvent); + pExynosComponent->abendStateEvent = NULL; + Exynos_OSAL_MutexTerminate(pExynosComponent->compMutex); + pExynosComponent->compMutex = NULL; + Exynos_OSAL_SemaphoreTerminate(pExynosComponent->msgSemaphoreHandle); + pExynosComponent->msgSemaphoreHandle = NULL; + Exynos_OSAL_QueueTerminate(&pExynosComponent->messageQ); + + Exynos_OSAL_Free(pExynosComponent); + pExynosComponent = NULL; + + ret = OMX_ErrorNone; +EXIT: + FunctionOut(); + + return ret; +} + + diff --git a/openmax/component/audio/common/Exynos_OMX_ABasecomponent.h b/openmax/component/audio/common/Exynos_OMX_ABasecomponent.h new file mode 100644 index 0000000..b714095 --- /dev/null +++ b/openmax/component/audio/common/Exynos_OMX_ABasecomponent.h @@ -0,0 +1,158 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_ABasecomponent.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_ABASECOMP +#define EXYNOS_OMX_ABASECOMP + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OSAL_Queue.h" +#include "Exynos_OMX_ABaseport.h" + + +typedef struct _EXYNOS_OMX_MESSAGE +{ + OMX_U32 messageType; + OMX_U32 messageParam; + OMX_PTR pCmdData; +} EXYNOS_OMX_MESSAGE; + +/* for Check TimeStamp after Seek */ +typedef struct _EXYNOS_OMX_TIMESTAMP +{ + OMX_BOOL needSetStartTimeStamp; + OMX_BOOL needCheckStartTimeStamp; + OMX_TICKS startTimeStamp; + OMX_U32 nStartFlags; +} EXYNOS_OMX_TIMESTAMP; + +typedef struct _EXYNOS_OMX_BASECOMPONENT +{ + OMX_STRING componentName; + OMX_VERSIONTYPE componentVersion; + OMX_VERSIONTYPE specVersion; + + OMX_STATETYPE currentState; + EXYNOS_OMX_TRANS_STATETYPE transientState; + OMX_BOOL abendState; + OMX_HANDLETYPE abendStateEvent; + + EXYNOS_CODEC_TYPE codecType; + EXYNOS_OMX_PRIORITYMGMTTYPE compPriority; + OMX_MARKTYPE propagateMarkType; + OMX_HANDLETYPE compMutex; + + OMX_HANDLETYPE hComponentHandle; + + /* Message Handler */ + OMX_BOOL bExitMessageHandlerThread; + OMX_HANDLETYPE hMessageHandler; + OMX_HANDLETYPE msgSemaphoreHandle; + EXYNOS_QUEUE messageQ; + + /* Port */ + OMX_PORT_PARAM_TYPE portParam; + EXYNOS_OMX_BASEPORT *pExynosPort; + + OMX_HANDLETYPE pauseEvent; + + /* Callback function */ + OMX_CALLBACKTYPE *pCallbacks; + OMX_PTR callbackData; + + /* Save Timestamp */ + OMX_TICKS timeStamp[MAX_TIMESTAMP]; + EXYNOS_OMX_TIMESTAMP checkTimeStamp; + + /* Save Flags */ + OMX_U32 nFlags[MAX_FLAGS]; + + OMX_BOOL getAllDelayBuffer; + OMX_BOOL reInputData; + + OMX_BOOL bUseFlagEOF; + OMX_BOOL bSaveFlagEOS; /* bSaveFlagEOS is OMX_TRUE, if EOS flag is incoming. */ + OMX_BOOL bBehaviorEOS; /* bBehaviorEOS is OMX_TRUE, if EOS flag with Data are incoming. */ + + OMX_ERRORTYPE (*exynos_codec_componentInit)(OMX_COMPONENTTYPE *pOMXComponent); + OMX_ERRORTYPE (*exynos_codec_componentTerminate)(OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef TUNNELING_SUPPORT + OMX_ERRORTYPE (*exynos_AllocateTunnelBuffer)(EXYNOS_OMX_BASEPORT *pOMXBasePort, OMX_U32 nPortIndex); + OMX_ERRORTYPE (*exynos_FreeTunnelBuffer)(EXYNOS_OMX_BASEPORT *pOMXBasePort, OMX_U32 nPortIndex); +#endif + + OMX_ERRORTYPE (*exynos_BufferProcessCreate)(OMX_HANDLETYPE pOMXComponent); + OMX_ERRORTYPE (*exynos_BufferProcessTerminate)(OMX_HANDLETYPE pOMXComponent); + OMX_ERRORTYPE (*exynos_BufferFlush)(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex, OMX_BOOL bEvent); +} EXYNOS_OMX_BASECOMPONENT; + +OMX_ERRORTYPE Exynos_OMX_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR ComponentParameterStructure); + +OMX_ERRORTYPE Exynos_OMX_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR ComponentParameterStructure); + +OMX_PTR Exynos_OMX_MakeDynamicConfigCMD( + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure); + +OMX_ERRORTYPE Exynos_OMX_GetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_INOUT OMX_PTR pComponentConfigStructure); + +OMX_ERRORTYPE Exynos_OMX_SetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure); + +OMX_ERRORTYPE Exynos_OMX_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType); + +void Exynos_OMX_Component_abnormalTermination(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Constructor(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Destructor(OMX_IN OMX_HANDLETYPE hComponent); + +#ifdef __cplusplus +extern "C" { +#endif + + OMX_ERRORTYPE Exynos_OMX_Check_SizeVersion(OMX_PTR header, OMX_U32 size); + + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/audio/common/Exynos_OMX_ABaseport.c b/openmax/component/audio/common/Exynos_OMX_ABaseport.c new file mode 100644 index 0000000..7c4ed9a --- /dev/null +++ b/openmax/component/audio/common/Exynos_OMX_ABaseport.c @@ -0,0 +1,992 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_ABaseport.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * HyeYeon Chung (hyeon.chung@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_Memory.h" + +#include "Exynos_OMX_ABaseport.h" +#include "Exynos_OMX_ABasecomponent.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_ABASE_PORT" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +#ifdef PERFORMANCE_DEBUG +#include "Exynos_OSAL_ETC.h" +#endif + +#include "Exynos_OSAL_Platform.h" + + +OMX_ERRORTYPE Exynos_OMX_InputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE* bufferHeader) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 i = 0; + OMX_BOOL bBufferFind = OMX_FALSE; + + Exynos_OSAL_MutexLock(pExynosPort->hPortMutex); + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (bufferHeader == pExynosPort->extendBufferHeader[i].OMXBufferHeader) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_TRUE) { + pExynosPort->extendBufferHeader[i].bBufferInOMX = OMX_FALSE; + bBufferFind = OMX_TRUE; + break; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Trying to return the input buffer without ownership!!", pExynosComponent, __FUNCTION__); + } + } + } + + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + + if ((bBufferFind == OMX_TRUE) && + (bufferHeader != NULL) && + (bufferHeader->pBuffer != NULL)) { + pExynosComponent->pCallbacks->EmptyBufferDone(pOMXComponent, pExynosComponent->callbackData, bufferHeader); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader: %p", pExynosComponent, __FUNCTION__, bufferHeader); + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_OutputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE* bufferHeader) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 i = 0; + OMX_BOOL bBufferFind = OMX_FALSE; + Exynos_OSAL_MutexLock(pExynosPort->hPortMutex); + for (i = 0; i < MAX_BUFFER_NUM; i++) { + if (bufferHeader == pExynosPort->extendBufferHeader[i].OMXBufferHeader) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_TRUE) { + bBufferFind = OMX_TRUE; + pExynosPort->extendBufferHeader[i].bBufferInOMX = OMX_FALSE; + break; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Trying to return the output buffer without ownership!!", pExynosComponent, __FUNCTION__); + } + } + } + + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + + if ((bBufferFind == OMX_TRUE) && + (bufferHeader != NULL) && + (bufferHeader->pBuffer != NULL)) { + pExynosComponent->pCallbacks->FillBufferDone(pOMXComponent, pExynosComponent->callbackData, bufferHeader); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader: %p", pExynosComponent, __FUNCTION__, bufferHeader); + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferFlushProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex, + OMX_BOOL bEvent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + cnt = (nPortIndex == ALL_PORT_INDEX) ? ALL_PORT_NUM : 1; + for (i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Flush %s Port", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + ret = pExynosComponent->exynos_BufferFlush(pOMXComponent, nIndex, bEvent); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port is flushed", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + if (ret == OMX_ErrorNone) { + pExynosComponent->pExynosPort[nIndex].portState = EXYNOS_OMX_PortStateIdle; + + if (bEvent == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(EventCmdComplete/Flush/%s port)", + pExynosComponent, __FUNCTION__, (nIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandFlush, nIndex, NULL); + } + } + } + +EXIT: + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + if ((pOMXComponent != NULL) && + (pExynosComponent != NULL)) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_EnablePort( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + OMX_U32 i = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port is waiting for loadedResource", + pExynosComponent, __FUNCTION__, (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + Exynos_OSAL_SemaphoreWait(pExynosPort->loadedResource); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] loadedResource about %s port is posted", + pExynosComponent, __FUNCTION__, (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + + if (!CHECK_PORT_POPULATED(pExynosPort)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] buffer allocation on %s port is not completed (%d/%d)", + pExynosComponent, __FUNCTION__, (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosPort->assignedBufferNum, pExynosPort->portDefinition.nBufferCountActual); + } + + if (pExynosPort->exceptionFlag == INVALID_STATE) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] %s port is in the INVALID_STATE", pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosPort->exceptionFlag = NEED_PORT_DISABLE; + goto EXIT; + } + + if (pExynosComponent->abendState == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] component is abendstate. semaphore on port(%d) is posted", pExynosComponent, __FUNCTION__, nPortIndex); + pExynosPort->exceptionFlag = NEED_PORT_DISABLE; + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + pExynosPort->exceptionFlag = GENERAL_STATE; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_PortEnableProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + cnt = (nPortIndex == ALL_PORT_INDEX) ? ALL_PORT_NUM : 1; + for (i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Enable %s Port", pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + ret = Exynos_OMX_EnablePort(pOMXComponent, nIndex); + if (ret == OMX_ErrorNone) { + if (CHECK_PORT_ENABLED((&pExynosComponent->pExynosPort[nIndex]))) + pExynosComponent->pExynosPort[nIndex].portState = EXYNOS_OMX_PortStateIdle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(EventCmdComplete/Enable/%s port)", + pExynosComponent, __FUNCTION__, (nIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortEnable, nIndex, NULL); + } + } + +EXIT: + if ((ret != OMX_ErrorNone) && + (pOMXComponent != NULL) && + (pExynosComponent != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_DisablePort( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosComponent->currentState != OMX_StateLoaded) { + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + while (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > 0) { + message = (EXYNOS_OMX_MESSAGE*)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + Exynos_OSAL_Free(message); + } + } + + if (pExynosPort->exceptionFlag == NEED_PORT_DISABLE) + pExynosPort->exceptionFlag = GENERAL_STATE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port is waiting for unloadedResource", + pExynosComponent, __FUNCTION__, (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + Exynos_OSAL_SemaphoreWait(pExynosPort->unloadedResource); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] unloadedResource about %s port is posted", + pExynosComponent, __FUNCTION__, (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + + if (pExynosPort->assignedBufferNum > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] buffer free on %s port is not completed (%d/%d)", + pExynosComponent, __FUNCTION__, (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosPort->assignedBufferNum, pExynosPort->portDefinition.nBufferCountActual); + } + + if (pExynosComponent->abendState == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] component is abendstate. semaphore on port(%d) is posted", pExynosComponent, __FUNCTION__, nPortIndex); + pExynosPort->exceptionFlag = NEED_PORT_DISABLE; + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + pExynosPort->portDefinition.bEnabled = OMX_FALSE; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_PortDisableProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + cnt = (nPortIndex == ALL_PORT_INDEX ) ? ALL_PORT_NUM : 1; + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + /* port flush*/ + for(i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Before disabling %s port, do flush", + pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosComponent->pExynosPort[nIndex].portState = EXYNOS_OMX_PortStateFlushingForDisable; + ret = pExynosComponent->exynos_BufferFlush(pOMXComponent, nIndex, OMX_FALSE); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s Port is flushed", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + if (ret != OMX_ErrorNone) + goto EXIT; + } + } + + for(i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Disable %s Port", + pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosComponent->pExynosPort[nIndex].portState = EXYNOS_OMX_PortStateDisabling; + ret = Exynos_OMX_DisablePort(pOMXComponent, nIndex); + if (ret == OMX_ErrorNone) { + if (!CHECK_PORT_ENABLED((&pExynosComponent->pExynosPort[nIndex]))) + pExynosComponent->pExynosPort[nIndex].portState = EXYNOS_OMX_PortStateLoaded; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(EventCmdComplete/Disable/%s port)", + pExynosComponent, __FUNCTION__, (nIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortDisable, nIndex, NULL); + } + } + +EXIT: + if ((ret != OMX_ErrorNone) && + (pOMXComponent != NULL) && + (pExynosComponent != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_EmptyThisBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + OMX_U32 i = 0; + OMX_BOOL bFindBuffer = OMX_FALSE; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pBuffer->nInputPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StateExecuting) && + (pExynosComponent->currentState != OMX_StatePause)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + if ((!CHECK_PORT_ENABLED(pExynosPort)) || + (CHECK_PORT_BEING_FLUSHED(pExynosPort) && + (!CHECK_PORT_TUNNELED(pExynosPort) || !CHECK_PORT_BUFFER_SUPPLIER(pExynosPort))) || + ((pExynosComponent->transientState == EXYNOS_OMX_TransStateExecutingToIdle) && + (CHECK_PORT_TUNNELED(pExynosPort) && !CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] enabled(%d), state(%x), tunneld(%d), supplier(%d)", pExynosComponent, __FUNCTION__, + CHECK_PORT_ENABLED(pExynosPort), pExynosPort->portState, + CHECK_PORT_TUNNELED(pExynosPort), CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + Exynos_OSAL_MutexLock(pExynosPort->hPortMutex); + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pBuffer == pExynosPort->extendBufferHeader[i].OMXBufferHeader) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_FALSE) { + pExynosPort->extendBufferHeader[i].bBufferInOMX = OMX_TRUE; + bFindBuffer = OMX_TRUE; + break; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] input buffer(%p) was already entered!", pExynosComponent, __FUNCTION__, pBuffer); + } + } + } + + if (bFindBuffer == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] EmptyThisBuffer is failed : %p", pExynosComponent, __FUNCTION__, pBuffer); + ret = OMX_ErrorBadParameter; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + + message = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_MESSAGE)); + if (message == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + message->messageType = EXYNOS_OMX_CommandEmptyBuffer; + message->messageParam = (OMX_U32) i; + message->pCmdData = (OMX_PTR)pBuffer; + + ret = Exynos_OSAL_Queue(&pExynosPort->bufferQ, (void *)message); + if (ret != 0) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + ret = Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader:%p, nAllocLen:%d, nFilledLen:%d, nOffset:%d, nFlags:%x", + pExynosComponent, __FUNCTION__, + pBuffer, pBuffer->nAllocLen, pBuffer->nFilledLen, pBuffer->nOffset, pBuffer->nFlags); + + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FillThisBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + OMX_U32 i = 0; + OMX_BOOL bFindBuffer = OMX_FALSE; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pBuffer->nOutputPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StateExecuting) && + (pExynosComponent->currentState != OMX_StatePause)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + if ((!CHECK_PORT_ENABLED(pExynosPort)) || + ((CHECK_PORT_BEING_FLUSHED(pExynosPort)) && + (!CHECK_PORT_TUNNELED(pExynosPort) || !CHECK_PORT_BUFFER_SUPPLIER(pExynosPort))) || + ((pExynosComponent->transientState == EXYNOS_OMX_TransStateExecutingToIdle) && + (CHECK_PORT_TUNNELED(pExynosPort) && !CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] enabled(%d), state(%x), tunneld(%d), supplier(%d)", pExynosComponent, __FUNCTION__, + CHECK_PORT_ENABLED(pExynosPort), pExynosPort->portState, + CHECK_PORT_TUNNELED(pExynosPort), CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + Exynos_OSAL_MutexLock(pExynosPort->hPortMutex); + for (i = 0; i < MAX_BUFFER_NUM; i++) { + if (pBuffer == pExynosPort->extendBufferHeader[i].OMXBufferHeader) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_FALSE) { + pExynosPort->extendBufferHeader[i].bBufferInOMX = OMX_TRUE; + bFindBuffer = OMX_TRUE; + break; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] output buffer(%p) was already entered!", pExynosComponent, __FUNCTION__, pBuffer); + } + } + } + + if (bFindBuffer == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] FillThisBuffer is failed : %p", pExynosComponent, __FUNCTION__, pBuffer); + ret = OMX_ErrorBadParameter; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + + message = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_MESSAGE)); + if (message == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + message->messageType = EXYNOS_OMX_CommandFillBuffer; + message->messageParam = (OMX_U32) i; + message->pCmdData = (OMX_PTR)pBuffer; + + ret = Exynos_OSAL_Queue(&pExynosPort->bufferQ, (void *)message); + if (ret != 0) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + + ret = Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader:%p", pExynosComponent, __FUNCTION__, pBuffer); + + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Port_Constructor(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_BASEPORT *pExynosInputPort = NULL; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = NULL; + int i = 0, j = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x) Line:%d", __FUNCTION__, ret, __LINE__); + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x) Line:%d", __FUNCTION__, ret, __LINE__); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + INIT_SET_SIZE_VERSION(&pExynosComponent->portParam, OMX_PORT_PARAM_TYPE); + pExynosComponent->portParam.nPorts = ALL_PORT_NUM; + pExynosComponent->portParam.nStartPortNumber = INPUT_PORT_INDEX; + + pExynosPort = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BASEPORT) * ALL_PORT_NUM); + if (pExynosPort == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort, 0, sizeof(EXYNOS_OMX_BASEPORT) * ALL_PORT_NUM); + pExynosComponent->pExynosPort = pExynosPort; + + /* Input Port */ + pExynosInputPort = &pExynosPort[INPUT_PORT_INDEX]; + + Exynos_OSAL_QueueCreate(&pExynosInputPort->bufferQ, MAX_QUEUE_ELEMENTS); + + pExynosInputPort->extendBufferHeader = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + if (pExynosInputPort->extendBufferHeader == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosInputPort->extendBufferHeader, 0, sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + + pExynosInputPort->bufferStateAllocate = Exynos_OSAL_Malloc(sizeof(OMX_U32) * MAX_BUFFER_NUM); + if (pExynosInputPort->bufferStateAllocate == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosInputPort->bufferStateAllocate, 0, sizeof(OMX_U32) * MAX_BUFFER_NUM); + + pExynosInputPort->bufferSemID = NULL; + pExynosInputPort->assignedBufferNum = 0; + pExynosInputPort->portState = EXYNOS_OMX_PortStateLoaded; + pExynosInputPort->tunneledComponent = NULL; + pExynosInputPort->tunneledPort = 0; + pExynosInputPort->tunnelBufferNum = 0; + pExynosInputPort->bufferSupplier = OMX_BufferSupplyUnspecified; + pExynosInputPort->tunnelFlags = 0; + pExynosInputPort->supportFormat = NULL; + + ret = Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->loadedResource); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SemaphoreCreate (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + + ret = Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->unloadedResource); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SemaphoreCreate (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + + INIT_SET_SIZE_VERSION(&pExynosInputPort->portDefinition, OMX_PARAM_PORTDEFINITIONTYPE); + pExynosInputPort->portDefinition.nPortIndex = INPUT_PORT_INDEX; + pExynosInputPort->portDefinition.eDir = OMX_DirInput; + pExynosInputPort->portDefinition.nBufferCountActual = 0; + pExynosInputPort->portDefinition.nBufferCountMin = 0; + pExynosInputPort->portDefinition.nBufferSize = 0; + pExynosInputPort->portDefinition.bEnabled = OMX_FALSE; + pExynosInputPort->portDefinition.bPopulated = OMX_FALSE; + pExynosInputPort->portDefinition.eDomain = OMX_PortDomainMax; + pExynosInputPort->portDefinition.bBuffersContiguous = OMX_FALSE; + pExynosInputPort->portDefinition.nBufferAlignment = 0; + pExynosInputPort->markType.hMarkTargetComponent = NULL; + pExynosInputPort->markType.pMarkData = NULL; + pExynosInputPort->exceptionFlag = GENERAL_STATE; + + /* Output Port */ + pExynosOutputPort = &pExynosPort[OUTPUT_PORT_INDEX]; + + Exynos_OSAL_QueueCreate(&pExynosOutputPort->bufferQ, MAX_QUEUE_ELEMENTS); /* For in case of "Output Buffer Share", MAX ELEMENTS(DPB + EDPB) */ + + pExynosOutputPort->extendBufferHeader = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + if (pExynosOutputPort->extendBufferHeader == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosOutputPort->extendBufferHeader, 0, sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + + pExynosOutputPort->bufferStateAllocate = Exynos_OSAL_Malloc(sizeof(OMX_U32) * MAX_BUFFER_NUM); + if (pExynosOutputPort->bufferStateAllocate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosOutputPort->bufferStateAllocate, 0, sizeof(OMX_U32) * MAX_BUFFER_NUM); + + pExynosOutputPort->bufferSemID = NULL; + pExynosOutputPort->assignedBufferNum = 0; + pExynosOutputPort->portState = EXYNOS_OMX_PortStateLoaded; + pExynosOutputPort->tunneledComponent = NULL; + pExynosOutputPort->tunneledPort = 0; + pExynosOutputPort->tunnelBufferNum = 0; + pExynosOutputPort->bufferSupplier = OMX_BufferSupplyUnspecified; + pExynosOutputPort->tunnelFlags = 0; + pExynosOutputPort->supportFormat = NULL; + + ret = Exynos_OSAL_SemaphoreCreate(&pExynosOutputPort->loadedResource); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SemaphoreCreate (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + + ret = Exynos_OSAL_SemaphoreCreate(&pExynosOutputPort->unloadedResource); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SemaphoreCreate (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + + INIT_SET_SIZE_VERSION(&pExynosOutputPort->portDefinition, OMX_PARAM_PORTDEFINITIONTYPE); + pExynosOutputPort->portDefinition.nPortIndex = OUTPUT_PORT_INDEX; + pExynosOutputPort->portDefinition.eDir = OMX_DirOutput; + pExynosOutputPort->portDefinition.nBufferCountActual = 0; + pExynosOutputPort->portDefinition.nBufferCountMin = 0; + pExynosOutputPort->portDefinition.nBufferSize = 0; + pExynosOutputPort->portDefinition.bEnabled = OMX_FALSE; + pExynosOutputPort->portDefinition.bPopulated = OMX_FALSE; + pExynosOutputPort->portDefinition.eDomain = OMX_PortDomainMax; + pExynosOutputPort->portDefinition.bBuffersContiguous = OMX_FALSE; + pExynosOutputPort->portDefinition.nBufferAlignment = 0; + pExynosOutputPort->markType.hMarkTargetComponent = NULL; + pExynosOutputPort->markType.pMarkData = NULL; + pExynosOutputPort->exceptionFlag = GENERAL_STATE; + + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.startTimeStamp = 0; + pExynosComponent->checkTimeStamp.nStartFlags = 0x0; + + pOMXComponent->EmptyThisBuffer = &Exynos_OMX_EmptyThisBuffer; + pOMXComponent->FillThisBuffer = &Exynos_OMX_FillThisBuffer; + + ret = OMX_ErrorNone; + +EXIT: + if ((ret != OMX_ErrorNone) && + (pExynosComponent != NULL) && + (pExynosComponent->pExynosPort != NULL)) { + for (i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + Exynos_OSAL_SemaphoreTerminate(pExynosPort->loadedResource); + pExynosPort->loadedResource = NULL; + Exynos_OSAL_SemaphoreTerminate(pExynosPort->unloadedResource); + pExynosPort->unloadedResource = NULL; + Exynos_OSAL_Free(pExynosPort->bufferStateAllocate); + pExynosPort->bufferStateAllocate = NULL; + Exynos_OSAL_Free(pExynosPort->extendBufferHeader); + pExynosPort->extendBufferHeader = NULL; + + Exynos_OSAL_QueueTerminate(&pExynosPort->bufferQ); + } + + Exynos_OSAL_Free(pExynosComponent->pExynosPort); + pExynosComponent->pExynosPort = NULL; + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Port_Destructor(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + int i = 0, j = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + for (i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + Exynos_OSAL_SemaphoreTerminate(pExynosPort->loadedResource); + pExynosPort->loadedResource = NULL; + Exynos_OSAL_SemaphoreTerminate(pExynosPort->unloadedResource); + pExynosPort->unloadedResource = NULL; + Exynos_OSAL_Free(pExynosPort->bufferStateAllocate); + pExynosPort->bufferStateAllocate = NULL; + Exynos_OSAL_Free(pExynosPort->extendBufferHeader); + pExynosPort->extendBufferHeader = NULL; + + Exynos_OSAL_QueueTerminate(&pExynosPort->bufferQ); + } + + Exynos_OSAL_Free(pExynosComponent->pExynosPort); + pExynosComponent->pExynosPort = NULL; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_ResetCodecData(EXYNOS_OMX_DATA *pData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + /* caution: nPlanes in buffer structure might be used all times */ + Exynos_OSAL_Memset(&(pData->buffer.fd), 0, sizeof(pData->buffer.fd)); + Exynos_OSAL_Memset(&(pData->buffer.addr), 0, sizeof(pData->buffer.addr)); + + pData->dataLen = 0; + pData->usedDataLen = 0; + pData->remainDataLen = 0; + pData->nFlags = 0; + pData->timeStamp = 0; + pData->pPrivate = NULL; + pData->bufferHeader = NULL; + +EXIT: + return ret; +} diff --git a/openmax/component/audio/common/Exynos_OMX_ABaseport.h b/openmax/component/audio/common/Exynos_OMX_ABaseport.h new file mode 100644 index 0000000..1db51c3 --- /dev/null +++ b/openmax/component/audio/common/Exynos_OMX_ABaseport.h @@ -0,0 +1,157 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_ABaseport.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * HyeYeon Chung (hyeon.chung@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_ABASE_PORT +#define EXYNOS_OMX_ABASE_PORT + +#include "OMX_Component.h" +#include "Exynos_OMX_Def.h" +#include "Exynos_OSAL_Queue.h" +#include "Exynos_OMX_Def.h" + +#ifdef PERFORMANCE_DEBUG +#include +#endif + +#define BUFFER_STATE_ALLOCATED (1 << 0) +#define BUFFER_STATE_ASSIGNED (1 << 1) +#define HEADER_STATE_ALLOCATED (1 << 2) +#define BUFFER_STATE_FREE 0 + +#define MAX_BUFFER_NUM 40 + +#define INPUT_PORT_INDEX 0 +#define OUTPUT_PORT_INDEX 1 +#define ALL_PORT_INDEX -1 +#define ALL_PORT_NUM 2 + + +typedef struct _EXYNOS_OMX_BUFFERHEADERTYPE +{ + OMX_BUFFERHEADERTYPE *OMXBufferHeader; + OMX_BOOL bBufferInOMX; +} EXYNOS_OMX_BUFFERHEADERTYPE; + +typedef struct _EXYNOS_OMX_DATABUFFER +{ + OMX_HANDLETYPE bufferMutex; + OMX_BUFFERHEADERTYPE* bufferHeader; + OMX_BOOL dataValid; + OMX_U32 allocSize; + OMX_U32 dataLen; + OMX_U32 usedDataLen; + OMX_U32 remainDataLen; + OMX_U32 nFlags; + OMX_TICKS timeStamp; + OMX_PTR pPrivate; +} EXYNOS_OMX_DATABUFFER; + +typedef struct _EXYNOS_OMX_MULTIPLANE_BUFFER +{ + OMX_U32 nPlanes; + unsigned long fd[MAX_BUFFER_PLANE]; + OMX_PTR addr[MAX_BUFFER_PLANE]; + OMX_COLOR_FORMATTYPE eColorFormat; +} EXYNOS_OMX_MULTIPLANE_BUFFER; + +typedef struct _EXYNOS_OMX_DATA +{ + EXYNOS_OMX_MULTIPLANE_BUFFER buffer; + OMX_U32 allocSize; + OMX_U32 dataLen; + OMX_U32 usedDataLen; + OMX_U32 remainDataLen; + OMX_U32 nFlags; + OMX_TICKS timeStamp; + OMX_PTR pPrivate; + + /* For Share Buffer */ + OMX_BUFFERHEADERTYPE *bufferHeader; +} EXYNOS_OMX_DATA; + +typedef enum _EXYNOS_OMX_EXCEPTION_STATE +{ + GENERAL_STATE = 0x00, + NEED_PORT_FLUSH, + NEED_PORT_DISABLE, + INVALID_STATE, +} EXYNOS_OMX_EXCEPTION_STATE; + +typedef struct _EXYNOS_OMX_BASEPORT +{ + EXYNOS_OMX_BUFFERHEADERTYPE *extendBufferHeader; + OMX_U32 *bufferStateAllocate; + OMX_PARAM_PORTDEFINITIONTYPE portDefinition; + OMX_HANDLETYPE bufferSemID; + EXYNOS_QUEUE bufferQ; + OMX_S32 assignedBufferNum; + EXYNOS_OMX_PORT_STATETYPE portState; + OMX_HANDLETYPE loadedResource; + OMX_HANDLETYPE unloadedResource; + + OMX_MARKTYPE markType; + + /* Tunnel Info */ + OMX_HANDLETYPE tunneledComponent; + OMX_U32 tunneledPort; + OMX_U32 tunnelBufferNum; + OMX_BUFFERSUPPLIERTYPE bufferSupplier; + OMX_U32 tunnelFlags; + + OMX_COLOR_FORMATTYPE *supportFormat; + + OMX_HANDLETYPE pauseEvent; + + EXYNOS_OMX_DATABUFFER dataBuffer; + + /* Data */ + EXYNOS_OMX_DATA processData; + + OMX_HANDLETYPE hPortMutex; + EXYNOS_OMX_EXCEPTION_STATE exceptionFlag; +} EXYNOS_OMX_BASEPORT; + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OMX_PortEnableProcess(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_PortDisableProcess(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_BufferFlushProcess(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex, OMX_BOOL bEvent); +OMX_ERRORTYPE Exynos_OMX_Port_Constructor(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_Port_Destructor(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_ResetCodecData(EXYNOS_OMX_DATA *pData); +OMX_ERRORTYPE Exynos_OMX_InputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE *bufferHeader); +OMX_ERRORTYPE Exynos_OMX_OutputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE *bufferHeader); + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/openmax/component/audio/common/NOTICE b/openmax/component/audio/common/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/audio/common/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/audio/dec/Android.mk b/openmax/component/audio/dec/Android.mk new file mode 100644 index 0000000..600fa9f --- /dev/null +++ b/openmax/component/audio/dec/Android.mk @@ -0,0 +1,31 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + Exynos_OMX_Adec.c + +LOCAL_MODULE := libExynosOMX_Adec +LOCAL_ARM_MODE := arm +LOCAL_MODULE_TAGS := optional +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_STATIC_LIBRARIES := libsrpapi + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/audio/dec \ + $(EXYNOS_AUDIO_CODEC)/alp/include + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +endif +endif + +include $(BUILD_STATIC_LIBRARY) diff --git a/openmax/component/audio/dec/Exynos_OMX_Adec.c b/openmax/component/audio/dec/Exynos_OMX_Adec.c new file mode 100644 index 0000000..9d294c6 --- /dev/null +++ b/openmax/component/audio/dec/Exynos_OMX_Adec.c @@ -0,0 +1,1538 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Adec.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#include +#include +#include +#include "Exynos_OMX_Macros.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OMX_Adec.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_ETC.h" +#include "srp_api.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_AUDIO_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + temp_bufferHeader = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (temp_bufferHeader == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(temp_bufferHeader, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = temp_bufferHeader; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ASSIGNED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(temp_bufferHeader, OMX_BUFFERHEADERTYPE); + temp_bufferHeader->pBuffer = pBuffer; + temp_bufferHeader->nAllocLen = nSizeBytes; + temp_bufferHeader->pAppPrivate = pAppPrivate; + if (nPortIndex == INPUT_PORT_INDEX) + temp_bufferHeader->nInputPortIndex = INPUT_PORT_INDEX; + else + temp_bufferHeader->nOutputPortIndex = OUTPUT_PORT_INDEX; + + pExynosPort->assignedBufferNum++; + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + /* Exynos_OSAL_MutexLock(pExynosComponent->compMutex); */ + Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource); + /* Exynos_OSAL_MutexUnlock(pExynosComponent->compMutex); */ + } + *ppBufferHdr = temp_bufferHeader; + ret = OMX_ErrorNone; + goto EXIT; + } + } + + Exynos_OSAL_Free(temp_bufferHeader); + ret = OMX_ErrorInsufficientResources; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + temp_buffer = Exynos_OSAL_Malloc(sizeof(OMX_U8) * nSizeBytes); + if (temp_buffer == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + temp_bufferHeader = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (temp_bufferHeader == NULL) { + Exynos_OSAL_Free(temp_buffer); + temp_buffer = NULL; + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(temp_bufferHeader, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = temp_bufferHeader; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ALLOCATED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(temp_bufferHeader, OMX_BUFFERHEADERTYPE); + temp_bufferHeader->pBuffer = temp_buffer; + temp_bufferHeader->nAllocLen = nSizeBytes; + temp_bufferHeader->pAppPrivate = pAppPrivate; + if (nPortIndex == INPUT_PORT_INDEX) + temp_bufferHeader->nInputPortIndex = INPUT_PORT_INDEX; + else + temp_bufferHeader->nOutputPortIndex = OUTPUT_PORT_INDEX; + pExynosPort->assignedBufferNum++; + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + /* Exynos_OSAL_MutexLock(pExynosComponent->compMutex); */ + Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource); + /* Exynos_OSAL_MutexUnlock(pExynosComponent->compMutex); */ + } + *ppBuffer = temp_bufferHeader; + ret = OMX_ErrorNone; + goto EXIT; + } + } + + Exynos_OSAL_Free(temp_bufferHeader); + Exynos_OSAL_Free(temp_buffer); + ret = OMX_ErrorInsufficientResources; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosPort->portState != EXYNOS_OMX_PortStateDisabling) && + (pExynosPort->portState != EXYNOS_OMX_PortStateFlushingForDisable) && + (pExynosPort->portState != EXYNOS_OMX_PortStateInvalid)) { + (*(pExynosComponent->pCallbacks->EventHandler)) (pOMXComponent, + pExynosComponent->callbackData, + (OMX_U32)OMX_EventError, + (OMX_U32)OMX_ErrorPortUnpopulated, + nPortIndex, NULL); + } + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (((pExynosPort->bufferStateAllocate[i] | BUFFER_STATE_FREE) != 0) && (pExynosPort->extendBufferHeader[i].OMXBufferHeader != NULL)) { + if (pExynosPort->extendBufferHeader[i].OMXBufferHeader->pBuffer == pBufferHdr->pBuffer) { + if (pExynosPort->bufferStateAllocate[i] & BUFFER_STATE_ALLOCATED) { + Exynos_OSAL_Free(pExynosPort->extendBufferHeader[i].OMXBufferHeader->pBuffer); + pExynosPort->extendBufferHeader[i].OMXBufferHeader->pBuffer = NULL; + pBufferHdr->pBuffer = NULL; + } else if (pExynosPort->bufferStateAllocate[i] & BUFFER_STATE_ASSIGNED) { + ; /* None*/ + } + pExynosPort->assignedBufferNum--; + if (pExynosPort->bufferStateAllocate[i] & HEADER_STATE_ALLOCATED) { + Exynos_OSAL_Free(pExynosPort->extendBufferHeader[i].OMXBufferHeader); + pExynosPort->extendBufferHeader[i].OMXBufferHeader = NULL; + pBufferHdr = NULL; + } + pExynosPort->bufferStateAllocate[i] = BUFFER_STATE_FREE; + ret = OMX_ErrorNone; + goto EXIT; + } + } + } + +EXIT: + if (ret == OMX_ErrorNone) { + if (pExynosPort->assignedBufferNum == 0) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pExynosPort->unloadedResource signal set"); + /* Exynos_OSAL_MutexLock(pExynosComponent->compMutex); */ + Exynos_OSAL_SemaphorePost(pExynosPort->unloadedResource); + /* Exynos_OSAL_MutexUnlock(pExynosComponent->compMutex); */ + pExynosPort->portDefinition.bPopulated = OMX_FALSE; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AllocateTunnelBuffer(EXYNOS_OMX_BASEPORT *pOMXBasePort, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + OMX_U32 bufferSize = 0; + OMX_PARAM_PORTDEFINITIONTYPE portDefinition; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FreeTunnelBuffer(EXYNOS_OMX_BASEPORT *pOMXBasePort, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT* pExynosPort = NULL; + OMX_BUFFERHEADERTYPE* temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + OMX_U32 bufferSize = 0; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentTunnelRequest( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 nPort, + OMX_IN OMX_HANDLETYPE hTunneledComp, + OMX_IN OMX_U32 nTunneledPort, + OMX_INOUT OMX_TUNNELSETUPTYPE *pTunnelSetup) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} + +OMX_BOOL Exynos_Check_BufferProcess_State(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + if ((pExynosComponent->currentState == OMX_StateExecuting) && + (pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portState == EXYNOS_OMX_PortStateIdle) && + (pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portState == EXYNOS_OMX_PortStateIdle) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateIdleToExecuting)) { + return OMX_TRUE; + } else { + return OMX_FALSE; + } +} + +OMX_ERRORTYPE Exynos_InputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *exynosOMXInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOMXOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *dataBuffer = &exynosOMXInputPort->dataBuffer; + OMX_BUFFERHEADERTYPE *bufferHeader = dataBuffer->bufferHeader; + + FunctionIn(); + + if (bufferHeader != NULL) { + if (exynosOMXInputPort->markType.hMarkTargetComponent != NULL ) { + bufferHeader->hMarkTargetComponent = exynosOMXInputPort->markType.hMarkTargetComponent; + bufferHeader->pMarkData = exynosOMXInputPort->markType.pMarkData; + exynosOMXInputPort->markType.hMarkTargetComponent = NULL; + exynosOMXInputPort->markType.pMarkData = NULL; + } + + if (bufferHeader->hMarkTargetComponent != NULL) { + if (bufferHeader->hMarkTargetComponent == pOMXComponent) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventMark, + 0, 0, bufferHeader->pMarkData); + } else { + pExynosComponent->propagateMarkType.hMarkTargetComponent = bufferHeader->hMarkTargetComponent; + pExynosComponent->propagateMarkType.pMarkData = bufferHeader->pMarkData; + } + } + + bufferHeader->nFilledLen = 0; + Exynos_OMX_InputBufferReturn(pOMXComponent, bufferHeader); + } + + if ((pExynosComponent->currentState == OMX_StatePause) && + ((!CHECK_PORT_BEING_FLUSHED(exynosOMXInputPort) && !CHECK_PORT_BEING_FLUSHED(exynosOMXOutputPort)))) { + Exynos_OSAL_SignalWait(pExynosComponent->pauseEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pExynosComponent->pauseEvent); + } + + dataBuffer->dataValid = OMX_FALSE; + dataBuffer->dataLen = 0; + dataBuffer->remainDataLen = 0; + dataBuffer->usedDataLen = 0; + dataBuffer->bufferHeader = NULL; + dataBuffer->nFlags = 0; + dataBuffer->timeStamp = 0; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_InputBufferGetQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_DATABUFFER *dataBuffer = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + FunctionIn(); + + pExynosPort= &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + dataBuffer = &pExynosPort->dataBuffer; + + if (pExynosComponent->currentState != OMX_StateExecuting) { + ret = OMX_ErrorUndefined; + goto EXIT; + } else { + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + Exynos_OSAL_MutexLock(dataBuffer->bufferMutex); + if (dataBuffer->dataValid != OMX_TRUE) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message == NULL) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(dataBuffer->bufferMutex); + goto EXIT; + } + + dataBuffer->bufferHeader = (OMX_BUFFERHEADERTYPE *)(message->pCmdData); + dataBuffer->allocSize = dataBuffer->bufferHeader->nAllocLen; + dataBuffer->dataLen = dataBuffer->bufferHeader->nFilledLen; + dataBuffer->remainDataLen = dataBuffer->dataLen; + dataBuffer->usedDataLen = 0; + dataBuffer->dataValid = OMX_TRUE; + dataBuffer->nFlags = dataBuffer->bufferHeader->nFlags; + dataBuffer->timeStamp = dataBuffer->bufferHeader->nTimeStamp; + + Exynos_OSAL_Free(message); + + if (dataBuffer->allocSize <= dataBuffer->dataLen) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "Input Buffer Full, Check input buffer size! allocSize:%d, dataLen:%d", dataBuffer->allocSize, dataBuffer->dataLen); + } else { + Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + } + Exynos_OSAL_MutexUnlock(dataBuffer->bufferMutex); + ret = OMX_ErrorNone; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OutputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *exynosOMXInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOMXOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *dataBuffer = &exynosOMXOutputPort->dataBuffer; + OMX_BUFFERHEADERTYPE *bufferHeader = dataBuffer->bufferHeader; + + FunctionIn(); + + if (bufferHeader != NULL) { + bufferHeader->nFilledLen = dataBuffer->remainDataLen; + bufferHeader->nOffset = 0; + bufferHeader->nFlags = dataBuffer->nFlags; + bufferHeader->nTimeStamp = dataBuffer->timeStamp; + + if (pExynosComponent->propagateMarkType.hMarkTargetComponent != NULL) { + bufferHeader->hMarkTargetComponent = pExynosComponent->propagateMarkType.hMarkTargetComponent; + bufferHeader->pMarkData = pExynosComponent->propagateMarkType.pMarkData; + pExynosComponent->propagateMarkType.hMarkTargetComponent = NULL; + pExynosComponent->propagateMarkType.pMarkData = NULL; + } + + if (bufferHeader->nFlags & OMX_BUFFERFLAG_EOS) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventBufferFlag, + OUTPUT_PORT_INDEX, + bufferHeader->nFlags, NULL); + } + + Exynos_OMX_OutputBufferReturn(pOMXComponent, bufferHeader); + } + + if ((pExynosComponent->currentState == OMX_StatePause) && + ((!CHECK_PORT_BEING_FLUSHED(exynosOMXInputPort) && !CHECK_PORT_BEING_FLUSHED(exynosOMXOutputPort)))) { + Exynos_OSAL_SignalWait(pExynosComponent->pauseEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pExynosComponent->pauseEvent); + } + + /* reset dataBuffer */ + dataBuffer->dataValid = OMX_FALSE; + dataBuffer->dataLen = 0; + dataBuffer->remainDataLen = 0; + dataBuffer->usedDataLen = 0; + dataBuffer->bufferHeader = NULL; + dataBuffer->nFlags = 0; + dataBuffer->timeStamp = 0; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OutputBufferGetQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_DATABUFFER *dataBuffer = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + FunctionIn(); + + pExynosPort= &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + dataBuffer = &pExynosPort->dataBuffer; + + if (pExynosComponent->currentState != OMX_StateExecuting) { + ret = OMX_ErrorUndefined; + goto EXIT; + } else { + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + Exynos_OSAL_MutexLock(dataBuffer->bufferMutex); + if (dataBuffer->dataValid != OMX_TRUE) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message == NULL) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(dataBuffer->bufferMutex); + goto EXIT; + } + + dataBuffer->bufferHeader = (OMX_BUFFERHEADERTYPE *)(message->pCmdData); + dataBuffer->allocSize = dataBuffer->bufferHeader->nAllocLen; + dataBuffer->dataLen = 0; //dataBuffer->bufferHeader->nFilledLen; + dataBuffer->remainDataLen = dataBuffer->dataLen; + dataBuffer->usedDataLen = 0; //dataBuffer->bufferHeader->nOffset; + dataBuffer->dataValid = OMX_TRUE; + /* dataBuffer->nFlags = dataBuffer->bufferHeader->nFlags; */ + /* dataBuffer->nTimeStamp = dataBuffer->bufferHeader->nTimeStamp; */ + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = dataBuffer->bufferHeader->pBuffer; + pExynosPort->processData.allocSize = dataBuffer->bufferHeader->nAllocLen; + + Exynos_OSAL_Free(message); + } else { + Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + } + Exynos_OSAL_MutexUnlock(dataBuffer->bufferMutex); + ret = OMX_ErrorNone; + } +EXIT: + FunctionOut(); + + return ret; + +} + +OMX_BOOL Exynos_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *inputUseBuffer = &exynosInputPort->dataBuffer; + EXYNOS_OMX_DATA *inputData = &exynosInputPort->processData; + OMX_U32 copySize = 0; + OMX_BYTE checkInputStream = NULL; + OMX_U32 checkInputStreamLen = 0; + OMX_U32 checkedSize = 0; + OMX_BOOL flagEOF = OMX_FALSE; + OMX_BOOL previousFrameEOF = OMX_FALSE; + + FunctionIn(); + + if (inputUseBuffer->dataValid == OMX_TRUE) { + checkInputStream = inputUseBuffer->bufferHeader->pBuffer + inputUseBuffer->usedDataLen; + checkInputStreamLen = inputUseBuffer->remainDataLen; + + if (inputData->dataLen == 0) { + previousFrameEOF = OMX_TRUE; + } else { + previousFrameEOF = OMX_FALSE; + } + + /* Audio extractor should parse into frame units. */ + flagEOF = OMX_TRUE; + checkedSize = checkInputStreamLen; + copySize = checkedSize; + + if (inputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + + if (((inputData->allocSize) - (inputData->dataLen)) >= copySize) { + if (copySize > 0) + Exynos_OSAL_Memcpy((char*)inputData->buffer.addr[AUDIO_DATA_PLANE] + inputData->dataLen, checkInputStream, copySize); + + inputUseBuffer->dataLen -= copySize; + inputUseBuffer->remainDataLen -= copySize; + inputUseBuffer->usedDataLen += copySize; + + inputData->dataLen += copySize; + inputData->remainDataLen += copySize; + + if (previousFrameEOF == OMX_TRUE) { + inputData->timeStamp = inputUseBuffer->timeStamp; + inputData->nFlags = inputUseBuffer->nFlags; + } + + if (pExynosComponent->bUseFlagEOF == OMX_TRUE) { + if (pExynosComponent->bSaveFlagEOS == OMX_TRUE) { + inputData->nFlags |= OMX_BUFFERFLAG_EOS; + flagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + } else { + inputData->nFlags = (inputData->nFlags & (~OMX_BUFFERFLAG_EOS)); + } + } else { + if ((checkedSize == checkInputStreamLen) && (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + if ((inputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) && + ((inputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG) || + (inputData->dataLen == 0))) { + inputData->nFlags |= OMX_BUFFERFLAG_EOS; + flagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + } else if ((inputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) && + (!(inputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) && + (inputData->dataLen != 0)) { + inputData->nFlags = (inputData->nFlags & (~OMX_BUFFERFLAG_EOS)); + flagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + } + } else { + inputData->nFlags = (inputUseBuffer->nFlags & (~OMX_BUFFERFLAG_EOS)); + } + } + } else { + /*????????????????????????????????? Error ?????????????????????????????????*/ + Exynos_InputBufferReturn(pOMXComponent); + Exynos_ResetCodecData(inputData); + flagEOF = OMX_FALSE; + } + + if ((inputUseBuffer->remainDataLen == 0) || + (CHECK_PORT_BEING_FLUSHED(exynosInputPort))) + Exynos_InputBufferReturn(pOMXComponent); + else + inputUseBuffer->dataValid = OMX_TRUE; + } + + if (flagEOF == OMX_TRUE) { + if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) { + /* Flush SRP buffers */ + SRP_Flush(); + pAudioDec->outFrames = 0; + pAudioDec->baseTime = 0; + pAudioDec->bFirstFrame = OMX_TRUE; + + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_TRUE; + pExynosComponent->checkTimeStamp.startTimeStamp = inputData->timeStamp; + pExynosComponent->checkTimeStamp.nStartFlags = inputData->nFlags; + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "first frame timestamp after seeking %lld us (%.2f secs)", + inputData->timeStamp, inputData->timeStamp / 1E6); + } + + ret = OMX_TRUE; + } else { + ret = OMX_FALSE; + } + + FunctionOut(); + + return ret; +} + +OMX_BOOL Exynos_Postprocess_OutputData(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *outputUseBuffer = &exynosOutputPort->dataBuffer; + EXYNOS_OMX_DATA *outputData = &exynosOutputPort->processData; + OMX_U32 copySize = 0; + + FunctionIn(); + + if (outputUseBuffer->dataValid == OMX_TRUE) { + if (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE) { + if (pExynosComponent->checkTimeStamp.startTimeStamp == outputData->timeStamp) { + pExynosComponent->checkTimeStamp.startTimeStamp = RESET_TIMESTAMP_VAL; + pExynosComponent->checkTimeStamp.nStartFlags = 0x0; + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + } else { + ret = OMX_TRUE; + goto EXIT; + } + } else if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) { + ret = OMX_TRUE; + goto EXIT; + } + + if (outputData->remainDataLen <= (outputUseBuffer->allocSize - outputUseBuffer->dataLen)) { + copySize = outputData->remainDataLen; + + outputUseBuffer->dataLen += copySize; + outputUseBuffer->remainDataLen += copySize; + outputUseBuffer->nFlags = outputData->nFlags; + outputUseBuffer->timeStamp = outputData->timeStamp; + + ret = OMX_TRUE; + + if ((outputUseBuffer->remainDataLen > 0) || + (outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) || + (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + Exynos_OutputBufferReturn(pOMXComponent); + + /* reset outputData */ + Exynos_ResetCodecData(outputData); + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "output buffer is smaller than decoded data size Out Length"); + + ret = OMX_FALSE; + + /* reset outputData */ + Exynos_ResetCodecData(outputData); + } + } else { + ret = OMX_FALSE; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferProcess(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *inputUseBuffer = &exynosInputPort->dataBuffer; + EXYNOS_OMX_DATABUFFER *outputUseBuffer = &exynosOutputPort->dataBuffer; + EXYNOS_OMX_DATA *inputData = &exynosInputPort->processData; + EXYNOS_OMX_DATA *outputData = &exynosOutputPort->processData; + OMX_U32 copySize = 0; + + pExynosComponent->reInputData = OMX_FALSE; + + FunctionIn(); + + while (!pAudioDec->bExitBufferProcessThread) { + Exynos_OSAL_SleepMillisec(0); + + if (((pExynosComponent->currentState == OMX_StatePause) || + (pExynosComponent->currentState == OMX_StateIdle) || + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle) || + (pExynosComponent->transientState == EXYNOS_OMX_TransStateExecutingToIdle)) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateIdleToLoaded)&& + ((!CHECK_PORT_BEING_FLUSHED(exynosInputPort) && !CHECK_PORT_BEING_FLUSHED(exynosOutputPort)))) { + Exynos_OSAL_SignalWait(pExynosComponent->pauseEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pExynosComponent->pauseEvent); + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent)) && (!pAudioDec->bExitBufferProcessThread)) { + Exynos_OSAL_SleepMillisec(0); + + Exynos_OSAL_MutexLock(outputUseBuffer->bufferMutex); + if ((outputUseBuffer->dataValid != OMX_TRUE) && + (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + Exynos_OSAL_MutexUnlock(outputUseBuffer->bufferMutex); + ret = Exynos_OutputBufferGetQueue(pExynosComponent); + if ((ret == OMX_ErrorUndefined) || + (exynosInputPort->portState != EXYNOS_OMX_PortStateIdle) || + (exynosOutputPort->portState != EXYNOS_OMX_PortStateIdle)) { + break; + } + } else { + Exynos_OSAL_MutexUnlock(outputUseBuffer->bufferMutex); + } + + if (pExynosComponent->reInputData == OMX_FALSE) { + Exynos_OSAL_MutexLock(inputUseBuffer->bufferMutex); + if ((Exynos_Preprocessor_InputData(pOMXComponent) == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(exynosInputPort))) { + Exynos_OSAL_MutexUnlock(inputUseBuffer->bufferMutex); + ret = Exynos_InputBufferGetQueue(pExynosComponent); + break; + } + + Exynos_OSAL_MutexUnlock(inputUseBuffer->bufferMutex); + } + + Exynos_OSAL_MutexLock(inputUseBuffer->bufferMutex); + Exynos_OSAL_MutexLock(outputUseBuffer->bufferMutex); + ret = pAudioDec->exynos_codec_bufferProcess(pOMXComponent, inputData, outputData); + Exynos_OSAL_MutexUnlock(outputUseBuffer->bufferMutex); + Exynos_OSAL_MutexUnlock(inputUseBuffer->bufferMutex); + + if (ret == (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet) + pExynosComponent->reInputData = OMX_TRUE; + else + pExynosComponent->reInputData = OMX_FALSE; + + Exynos_OSAL_MutexLock(outputUseBuffer->bufferMutex); + Exynos_Postprocess_OutputData(pOMXComponent); + Exynos_OSAL_MutexUnlock(outputUseBuffer->bufferMutex); + } + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetFlushBuffer(EXYNOS_OMX_BASEPORT *pExynosPort, EXYNOS_OMX_DATABUFFER **pDataBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + *pDataBuffer = &pExynosPort->dataBuffer; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FlushPort(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 portIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_DATABUFFER *flushPortBuffer = NULL; + OMX_BUFFERHEADERTYPE *bufferHeader = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + OMX_U32 flushNum = 0; + OMX_S32 semValue = 0; + + FunctionIn(); + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + while (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > 0) { + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[portIndex].bufferSemID, &semValue); + if (semValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[portIndex].bufferSemID); + Exynos_OSAL_SemaphoreWait(pExynosComponent->pExynosPort[portIndex].bufferSemID); + + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message != NULL) { + bufferHeader = (OMX_BUFFERHEADERTYPE *)message->pCmdData; + bufferHeader->nFilledLen = 0; + + if (portIndex == OUTPUT_PORT_INDEX) { + Exynos_OMX_OutputBufferReturn(pOMXComponent, bufferHeader); + } else { + Exynos_OMX_InputBufferReturn(pOMXComponent, bufferHeader); + } + + Exynos_OSAL_Free(message); + message = NULL; + } + } + + Exynos_OMX_GetFlushBuffer(pExynosPort, &flushPortBuffer); + if (flushPortBuffer != NULL) { + if (flushPortBuffer->dataValid == OMX_TRUE) { + if (portIndex == INPUT_PORT_INDEX) + Exynos_InputBufferReturn(pOMXComponent); + else if (portIndex == OUTPUT_PORT_INDEX) + Exynos_OutputBufferReturn(pOMXComponent); + + Exynos_ResetCodecData(&(pExynosPort->processData)); + } + } + + while(1) { + OMX_S32 cnt = 0; + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[portIndex].bufferSemID, &cnt); + if (cnt <= 0) + break; + Exynos_OSAL_SemaphoreWait(pExynosComponent->pExynosPort[portIndex].bufferSemID); + } + Exynos_OSAL_SetElemNum(&pExynosPort->bufferQ, 0); + + pExynosPort->processData.dataLen = 0; + pExynosPort->processData.nFlags = 0; + pExynosPort->processData.remainDataLen = 0; + pExynosPort->processData.timeStamp = 0; + pExynosPort->processData.usedDataLen = 0; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferFlush(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex, OMX_BOOL bEvent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_DATABUFFER *flushPortBuffer = NULL; + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_SignalSet(pExynosComponent->pauseEvent); + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + Exynos_OMX_GetFlushBuffer(pExynosPort, &flushPortBuffer); + + Exynos_OSAL_MutexLock(flushPortBuffer->bufferMutex); + ret = Exynos_OMX_FlushPort(pOMXComponent, nPortIndex); + Exynos_OSAL_MutexUnlock(flushPortBuffer->bufferMutex); + + if (nPortIndex == INPUT_PORT_INDEX) { + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_TRUE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->reInputData = OMX_FALSE; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR ComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (ComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + switch (nParamIndex) { + case OMX_IndexParamAudioInit: + { + OMX_PORT_PARAM_TYPE *portParam = (OMX_PORT_PARAM_TYPE *)ComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(portParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + portParam->nPorts = pExynosComponent->portParam.nPorts; + portParam->nStartPortNumber = pExynosComponent->portParam.nStartPortNumber; + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamAudioPortFormat: + { + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormat = (OMX_AUDIO_PARAM_PORTFORMATTYPE *)ComponentParameterStructure; + OMX_U32 portIndex = portFormat->nPortIndex; + OMX_U32 index = portFormat->nIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = NULL; + OMX_U32 supportFormatNum = 0; /* supportFormatNum = N-1 */ + + ret = Exynos_OMX_Check_SizeVersion(portFormat, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((portIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + + if (portIndex == INPUT_PORT_INDEX) { + supportFormatNum = INPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1; + if (index > supportFormatNum) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + portDefinition = &pExynosPort->portDefinition; + + portFormat->eEncoding = portDefinition->format.audio.eEncoding; + } else if (portIndex == OUTPUT_PORT_INDEX) { + supportFormatNum = OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1; + if (index > supportFormatNum) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + portDefinition = &pExynosPort->portDefinition; + + portFormat->eEncoding = portDefinition->format.audio.eEncoding; + } + ret = OMX_ErrorNone; + } + break; + default: + { + ret = Exynos_OMX_GetParameter(hComponent, nParamIndex, ComponentParameterStructure); + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} +OMX_ERRORTYPE Exynos_OMX_AudioDecodeSetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR ComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (ComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + switch (nIndex) { + case OMX_IndexParamAudioPortFormat: + { + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormat = (OMX_AUDIO_PARAM_PORTFORMATTYPE *)ComponentParameterStructure; + OMX_U32 portIndex = portFormat->nPortIndex; + OMX_U32 index = portFormat->nIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = NULL; + OMX_U32 supportFormatNum = 0; /* supportFormatNum = N-1 */ + + ret = Exynos_OMX_Check_SizeVersion(portFormat, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((portIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + portDefinition = &pExynosPort->portDefinition; + + portDefinition->format.audio.eEncoding = portFormat->eEncoding; + ret = OMX_ErrorNone; + } + break; + default: + { + ret = Exynos_OMX_SetParameter(hComponent, nIndex, ComponentParameterStructure); + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = Exynos_OMX_GetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeSetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + case OMX_IndexConfigAudioMute: + { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX_IndexConfigAudioMute"); + ret = OMX_ErrorUnsupportedIndex; + } + break; + case OMX_IndexConfigAudioVolume: + { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX_IndexConfigAudioVolume"); + ret = OMX_ErrorUnsupportedIndex; + } + break; + default: + ret = Exynos_OMX_SetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if ((cParameterName == NULL) || (pIndexType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + ret = Exynos_OMX_GetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_BufferProcessThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pSECComponent = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + FunctionIn(); + + if (threadData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + pSECComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + Exynos_OMX_BufferProcess(pOMXComponent); + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferProcess_Create(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + FunctionIn(); + + pAudioDec->bExitBufferProcessThread = OMX_FALSE; + + ret = Exynos_OSAL_ThreadCreate(&pAudioDec->hBufferProcessThread, + Exynos_OMX_BufferProcessThread, + pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferProcess_Terminate(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + OMX_S32 countValue = 0; + unsigned int i = 0; + + FunctionIn(); + + pAudioDec->bExitBufferProcessThread = OMX_TRUE; + + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[i].bufferSemID, &countValue); + if (countValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[i].bufferSemID); + } + + Exynos_OSAL_SignalSet(pExynosComponent->pauseEvent); + Exynos_OSAL_ThreadTerminate(pAudioDec->hBufferProcessThread); + pAudioDec->hBufferProcessThread = NULL; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + goto EXIT; + } + + ret = Exynos_OMX_BaseComponent_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + goto EXIT; + } + + ret = Exynos_OMX_Port_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pAudioDec = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_AUDIODEC_COMPONENT)); + if (pAudioDec == NULL) { + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + + Exynos_OSAL_Memset(pAudioDec, 0, sizeof(EXYNOS_OMX_AUDIODEC_COMPONENT)); + pExynosComponent->hComponentHandle = (OMX_HANDLETYPE)pAudioDec; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pAudioDec->bFirstFrame = OMX_TRUE; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = MAX_AUDIO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MAX_AUDIO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = DEFAULT_AUDIO_INPUT_BUFFER_SIZE; + pExynosPort->portDefinition.eDomain = OMX_PortDomainAudio; + + pExynosPort->portDefinition.format.audio.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/raw"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingUnused; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = MAX_AUDIO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MAX_AUDIO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.eDomain = OMX_PortDomainAudio; + + pExynosPort->portDefinition.format.audio.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/raw"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingUnused; + + + pOMXComponent->UseBuffer = &Exynos_OMX_UseBuffer; + pOMXComponent->AllocateBuffer = &Exynos_OMX_AllocateBuffer; + pOMXComponent->FreeBuffer = &Exynos_OMX_FreeBuffer; + pOMXComponent->ComponentTunnelRequest = &Exynos_OMX_ComponentTunnelRequest; + +#ifdef TUNNELING_SUPPORT + pExynosComponent->exynos_AllocateTunnelBuffer = &Exynos_OMX_AllocateTunnelBuffer; + pExynosComponent->exynos_FreeTunnelBuffer = &Exynos_OMX_FreeTunnelBuffer; +#endif + pExynosComponent->exynos_BufferProcessCreate = &Exynos_OMX_BufferProcess_Create; + pExynosComponent->exynos_BufferProcessTerminate = &Exynos_OMX_BufferProcess_Terminate; + pExynosComponent->exynos_BufferFlush = &Exynos_OMX_BufferFlush; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = NULL; + int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + Exynos_OSAL_Free(pAudioDec); + pExynosComponent->hComponentHandle = pAudioDec = NULL; + + for(i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + Exynos_OSAL_Free(pExynosPort->portDefinition.format.audio.cMIMEType); + pExynosPort->portDefinition.format.audio.cMIMEType = NULL; + } + + ret = Exynos_OMX_Port_Destructor(pOMXComponent); + + ret = Exynos_OMX_BaseComponent_Destructor(hComponent); + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/audio/dec/Exynos_OMX_Adec.h b/openmax/component/audio/dec/Exynos_OMX_Adec.h new file mode 100644 index 0000000..4413bee --- /dev/null +++ b/openmax/component/audio/dec/Exynos_OMX_Adec.h @@ -0,0 +1,144 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Adec.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#ifndef EXYNOS_OMX_AUDIO_DECODE +#define EXYNOS_OMX_AUDIO_DECODE + +#include "OMX_Component.h" +#include "Exynos_OMX_Def.h" +#include "Exynos_OSAL_Queue.h" +#include "Exynos_OMX_ABaseport.h" +#include "Exynos_OMX_ABasecomponent.h" + +#define MAX_AUDIO_INPUTBUFFER_NUM 2 +#define MAX_AUDIO_OUTPUTBUFFER_NUM 2 + +#define DEFAULT_AUDIO_INPUT_BUFFER_SIZE (16 * 1024) +#define DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE (32 * 1024) + +#define DEFAULT_AUDIO_SAMPLING_FREQ 44100 +#define DEFAULT_AUDIO_CHANNELS_NUM 2 +#define DEFAULT_AUDIO_BIT_PER_SAMPLE 16 + +#define INPUT_PORT_SUPPORTFORMAT_NUM_MAX 1 +#define OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX 1 + +#define AUDIO_DATA_PLANE 0 + + +typedef struct _SRP_DEC_INPUT_BUFFER +{ + void *PhyAddr; // physical address + void *VirAddr; // virtual address + int bufferSize; // input buffer alloc size + int dataSize; // Data length +} SRP_DEC_INPUT_BUFFER; + +typedef struct _EXYNOS_OMX_AUDIODEC_COMPONENT +{ + OMX_HANDLETYPE hCodecHandle; + + OMX_BOOL bFirstFrame; + OMX_PTR pInputBuffer; + SRP_DEC_INPUT_BUFFER SRPDecInputBuffer[MAX_AUDIO_INPUTBUFFER_NUM]; + OMX_U32 indexInputBuffer; + OMX_TICKS outFrames; + OMX_TICKS baseTime; + + /* Buffer Process */ + OMX_BOOL bExitBufferProcessThread; + OMX_HANDLETYPE hBufferProcessThread; + + OMX_ERRORTYPE (*exynos_codec_bufferProcess) (OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData, EXYNOS_OMX_DATA *pOutputData); + + int (*exynos_checkInputFrame)(OMX_U8 *pInputStream, OMX_U32 buffSize, OMX_U32 flag, OMX_BOOL bPreviousFrameEOF, OMX_BOOL *pbEndOfFrame); +} EXYNOS_OMX_AUDIODEC_COMPONENT; + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer); +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes); +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr); +OMX_ERRORTYPE Exynos_OMX_AllocateTunnelBuffer( + EXYNOS_OMX_BASEPORT *pOMXBasePort, + OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_FreeTunnelBuffer( + EXYNOS_OMX_BASEPORT *pOMXBasePort, + OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_ComponentTunnelRequest( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 nPort, + OMX_IN OMX_HANDLETYPE hTunneledComp, + OMX_IN OMX_U32 nTunneledPort, + OMX_INOUT OMX_TUNNELSETUPTYPE *pTunnelSetup); +OMX_ERRORTYPE Exynos_OMX_BufferProcess(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR ComponentParameterStructure); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeSetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR ComponentParameterStructure); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeSetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent); +OMX_BOOL Exynos_Check_BufferProcess_State(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); + +#ifdef __cplusplus +} +#endif + +#endif /* EXYNOS_OMX_AUDIO_DECODE */ diff --git a/openmax/component/audio/dec/NOTICE b/openmax/component/audio/dec/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/audio/dec/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/audio/dec/mp3/Android.mk b/openmax/component/audio/dec/mp3/Android.mk new file mode 100644 index 0000000..4c28be6 --- /dev/null +++ b/openmax/component/audio/dec/mp3/Android.mk @@ -0,0 +1,41 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Mp3dec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.MP3.Decoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Adec libExynosOMX_OSAL libExynosOMX_ABasecomponent \ + libsrpapi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/audio/dec \ + $(EXYNOS_AUDIO_CODEC)/alp/include + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/audio/dec/mp3/Exynos_OMX_Mp3dec.c b/openmax/component/audio/dec/mp3/Exynos_OMX_Mp3dec.c new file mode 100644 index 0000000..6fb940f --- /dev/null +++ b/openmax/component/audio/dec/mp3/Exynos_OMX_Mp3dec.c @@ -0,0 +1,938 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Mp3dec.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_ABasecomponent.h" +#include "Exynos_OMX_ABaseport.h" +#include "Exynos_OMX_Adec.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Mp3dec.h" +#include "srp_api.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_MP3_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +//#define SRP_DUMP_TO_FILE +#ifdef SRP_DUMP_TO_FILE +#include "stdio.h" + +FILE *inFile; +FILE *outFile; +#endif + +OMX_ERRORTYPE Exynos_SRP_Mp3Dec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nParamIndex) { + case OMX_IndexParamAudioMp3: + { + OMX_AUDIO_PARAM_MP3TYPE *pDstMp3Param = (OMX_AUDIO_PARAM_MP3TYPE *)pComponentParameterStructure; + OMX_AUDIO_PARAM_MP3TYPE *pSrcMp3Param = NULL; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstMp3Param, sizeof(OMX_AUDIO_PARAM_MP3TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstMp3Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMp3Dec = (EXYNOS_MP3_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pSrcMp3Param = &pMp3Dec->mp3Param; + + Exynos_OSAL_Memcpy(pDstMp3Param, pSrcMp3Param, sizeof(OMX_AUDIO_PARAM_MP3TYPE)); + } + break; + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pDstPcmParam = (OMX_AUDIO_PARAM_PCMMODETYPE *)pComponentParameterStructure; + OMX_AUDIO_PARAM_PCMMODETYPE *pSrcPcmParam = NULL; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstPcmParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMp3Dec = (EXYNOS_MP3_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pSrcPcmParam = &pMp3Dec->pcmParam; + + Exynos_OSAL_Memcpy(pDstPcmParam, pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_S32 codecType; + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_MP3_DEC_ROLE); + } + break; + default: + ret = Exynos_OMX_AudioDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SRP_Mp3Dec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + case OMX_IndexParamAudioMp3: + { + OMX_AUDIO_PARAM_MP3TYPE *pDstMp3Param = NULL; + OMX_AUDIO_PARAM_MP3TYPE *pSrcMp3Param = (OMX_AUDIO_PARAM_MP3TYPE *)pComponentParameterStructure; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcMp3Param, sizeof(OMX_AUDIO_PARAM_MP3TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcMp3Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMp3Dec = (EXYNOS_MP3_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDstMp3Param = &pMp3Dec->mp3Param; + + Exynos_OSAL_Memcpy(pDstMp3Param, pSrcMp3Param, sizeof(OMX_AUDIO_PARAM_MP3TYPE)); + } + break; + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pDstPcmParam = NULL; + OMX_AUDIO_PARAM_PCMMODETYPE *pSrcPcmParam = (OMX_AUDIO_PARAM_PCMMODETYPE *)pComponentParameterStructure; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcPcmParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMp3Dec = (EXYNOS_MP3_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDstPcmParam = &pMp3Dec->pcmParam; + + Exynos_OSAL_Memcpy(pDstPcmParam, pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_MP3_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingMP3; + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + default: + ret = Exynos_OMX_AudioDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SRP_Mp3Dec_GetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = Exynos_OMX_AudioDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SRP_Mp3Dec_SetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = Exynos_OMX_AudioDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SRP_Mp3Dec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if ((cParameterName == NULL) || (pIndexType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + ret = Exynos_OMX_AudioDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SRP_Mp3Dec_ComponentRoleEnum( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_U8 *cRole, + OMX_IN OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 codecType; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex != (MAX_COMPONENT_ROLE_NUM - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_MP3_DEC_ROLE); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SRP_Mp3Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MP3_HANDLE *pMp3Dec = (EXYNOS_MP3_HANDLE *)pAudioDec->hCodecHandle; + + FunctionIn(); + + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pExynosComponent->bUseFlagEOF = OMX_TRUE; /* Mp3 extractor should parse into frame unit. */ + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pMp3Dec->hSRPMp3Handle.bConfiguredSRP = OMX_FALSE; + pMp3Dec->hSRPMp3Handle.bSRPSendEOS = OMX_FALSE; + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + +#ifdef SRP_DUMP_TO_FILE + inFile = fopen("/data/InFile.mp3", "w+"); + outFile = fopen("/data/OutFile.pcm", "w+"); +#endif + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SRP_Mp3Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + FunctionIn(); + +#ifdef SRP_DUMP_TO_FILE + fclose(inFile); + fclose(outFile); +#endif + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SRP_Mp3_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData, EXYNOS_OMX_DATA *pOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MP3_HANDLE *pMp3Dec = (EXYNOS_MP3_HANDLE *)pAudioDec->hCodecHandle; + struct srp_dec_info codecDecInfo; + OMX_S32 returnCodec = 0; + unsigned long isSRPStopped = 0; + OMX_PTR dataBuffer = NULL; + unsigned int dataLen = 0; + OMX_BOOL isSRPIbufOverflow = OMX_FALSE; + + FunctionIn(); + +#ifdef SRP_DUMP_TO_FILE + if (pExynosComponent->reInputData == OMX_FALSE) { + fwrite(pInputData->buffer.addr[AUDIO_DATA_PLANE], pInputData->dataLen, 1, inFile); + } +#endif + + /* Save timestamp and flags of input data */ + if (pAudioDec->bFirstFrame) { + pOutputData->timeStamp = pInputData->timeStamp; + pAudioDec->baseTime = pInputData->timeStamp; + pAudioDec->bFirstFrame = OMX_FALSE; + } + pOutputData->nFlags = pInputData->nFlags & (~OMX_BUFFERFLAG_EOS); + + /* Decoding mp3 frames by SRP */ + if (pExynosComponent->getAllDelayBuffer == OMX_FALSE) { + returnCodec = SRP_Decode(pInputData->buffer.addr[AUDIO_DATA_PLANE], pInputData->dataLen); + + if (returnCodec >= 0) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) { + SRP_Send_EOS(); + pMp3Dec->hSRPMp3Handle.bSRPSendEOS = OMX_TRUE; + } + } else if (returnCodec == SRP_ERROR_IBUF_OVERFLOW) { + isSRPIbufOverflow = OMX_TRUE; + ret = OMX_ErrorInputDataDecodeYet; + } + } + + if (pMp3Dec->hSRPMp3Handle.bConfiguredSRP == OMX_FALSE) { + if ((pInputData->dataLen <= 0) && (pInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + pOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pMp3Dec->hSRPMp3Handle.bSRPSendEOS = OMX_FALSE; + ret = OMX_ErrorNone; + goto EXIT; + } + + returnCodec = SRP_Get_Dec_Info(&codecDecInfo); + if (returnCodec < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "SRP_Get_Dec_Info failed: %d", returnCodec); + ret = OMX_ErrorHardware; + goto EXIT; + } + + if (!codecDecInfo.sample_rate || !codecDecInfo.channels) { + if (pMp3Dec->hSRPMp3Handle.bSRPSendEOS == OMX_TRUE) { + pOutputData->dataLen = 0; + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + ret = OMX_ErrorInputDataDecodeYet; + } else { + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + if (isSRPIbufOverflow) + ret = OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + } + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "numChannels(%d), samplingRate(%d)", + codecDecInfo.channels, codecDecInfo.sample_rate); + + if (pMp3Dec->pcmParam.nChannels != codecDecInfo.channels || + pMp3Dec->pcmParam.nSamplingRate != codecDecInfo.sample_rate) { + /* Change channel count and sampling rate information */ + pMp3Dec->pcmParam.nChannels = codecDecInfo.channels; + pMp3Dec->pcmParam.nSamplingRate = codecDecInfo.sample_rate; + + /* Send Port Settings changed call back */ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + + pMp3Dec->hSRPMp3Handle.bConfiguredSRP = OMX_TRUE; + + if (pMp3Dec->hSRPMp3Handle.bSRPSendEOS == OMX_TRUE) { + pOutputData->dataLen = 0; + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + ret = OMX_ErrorInputDataDecodeYet; + } else { + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + if (isSRPIbufOverflow) + ret = OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + } + goto EXIT; + } + + /* Get decoded data from SRP */ + returnCodec = SRP_Get_PCM(&dataBuffer, &dataLen); + if (pMp3Dec->hSRPMp3Handle.bConfiguredSRP == OMX_TRUE) { + pOutputData->timeStamp = pAudioDec->baseTime + pAudioDec->outFrames * 1000 * 1000 / (OMX_TICKS)pMp3Dec->pcmParam.nSamplingRate; + int frames = dataLen / pMp3Dec->pcmParam.nChannels / 2; + pAudioDec->outFrames += frames; + } + if (dataLen > 0) { + pOutputData->dataLen = dataLen; + Exynos_OSAL_Memcpy(pOutputData->buffer.addr[AUDIO_DATA_PLANE], dataBuffer, dataLen); + } else { + pOutputData->dataLen = 0; + } + +#ifdef SRP_DUMP_TO_FILE + if (pOutputData->dataLen > 0) + fwrite(pOutputData->buffer.addr[AUDIO_DATA_PLANE], pOutputData->dataLen, 1, outFile); +#endif + + /* Delay EOS signal until all the PCM is returned from the SRP driver. */ + if (pMp3Dec->hSRPMp3Handle.bSRPSendEOS == OMX_TRUE) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) { + returnCodec = SRP_GetParams(SRP_STOP_EOS_STATE, &isSRPStopped); + if (returnCodec != 0) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Fail SRP_STOP_EOS_STATE"); + if (isSRPStopped == 1) { + pOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + pMp3Dec->hSRPMp3Handle.bSRPSendEOS = OMX_FALSE; /* for repeating one song */ + ret = OMX_ErrorNone; + } else { + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + ret = OMX_ErrorInputDataDecodeYet; + } + } else { /* Flush after EOS */ + pMp3Dec->hSRPMp3Handle.bSRPSendEOS = OMX_FALSE; + } + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SRP_Mp3Dec_bufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData, EXYNOS_OMX_DATA *pOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || (!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pInputPort)) || (!CHECK_PORT_POPULATED(pOutputPort))) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + ret = OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent)) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + ret = OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + + goto EXIT; + } + + ret = Exynos_SRP_Mp3_Decode_Block(pOMXComponent, pInputData, pOutputData); + + if (ret != OMX_ErrorNone) { + if (ret == (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet) { + pOutputData->usedDataLen = 0; + pOutputData->remainDataLen = pOutputData->dataLen; + } else { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + pInputData->usedDataLen += pInputData->dataLen; + pInputData->remainDataLen = pInputData->dataLen - pInputData->usedDataLen; + pInputData->dataLen -= pInputData->usedDataLen; + pInputData->usedDataLen = 0; + + pOutputData->usedDataLen = 0; + pOutputData->remainDataLen = pOutputData->dataLen; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = NULL; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + OMX_PTR pInputBuffer = NULL; + OMX_PTR pOutputBuffer = NULL; + unsigned int inputBufferSize = 0; + unsigned int inputBufferNum = 0; + unsigned int outputBufferSize = 0; + unsigned int outputBufferNum = 0; + OMX_S32 returnCodec; + int i = 0; + + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: parameters are null, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MP3_DEC, componentName) != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: componentName(%s) error, ret: %X", __FUNCTION__, componentName, ret); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_AudioDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_AudioDecodeComponentInit error, ret: %X", __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = HW_AUDIO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: componentName alloc error, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_1; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_MP3_DEC); + + pMp3Dec = Exynos_OSAL_Malloc(sizeof(EXYNOS_MP3_HANDLE)); + if (pMp3Dec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: EXYNOS_MP3_HANDLE alloc error, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_2; + } + Exynos_OSAL_Memset(pMp3Dec, 0, sizeof(EXYNOS_MP3_HANDLE)); + pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pAudioDec->hCodecHandle = (OMX_HANDLETYPE)pMp3Dec; + + /* Create and Init SRP */ + pMp3Dec->hSRPMp3Handle.bSRPLoaded = OMX_FALSE; + returnCodec = SRP_Create(SRP_INIT_BLOCK_MODE); + if (returnCodec < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "SRP_Create failed: %d", returnCodec); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_3; + } + pMp3Dec->hSRPMp3Handle.hSRPHandle = returnCodec; /* SRP's fd */ + + returnCodec = SRP_Init(); + if (returnCodec < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "SRP_Init failed: %d", returnCodec); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_4; + } + pMp3Dec->hSRPMp3Handle.bSRPLoaded = OMX_TRUE; + + /* Get input buffer info from SRP */ + returnCodec = SRP_Get_Ibuf_Info(&pInputBuffer, &inputBufferSize, &inputBufferNum); + if (returnCodec < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "SRP_Get_Ibuf_Info failed: %d", returnCodec); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_5; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->processData.allocSize = inputBufferSize; + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = Exynos_OSAL_Malloc(inputBufferSize); + if (pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Input data buffer alloc failed"); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_5; + } + + /* Get output buffer info from SRP */ + returnCodec = SRP_Get_Obuf_Info(&pOutputBuffer, &outputBufferSize, &outputBufferNum); + if (returnCodec < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "SRP_Get_Obuf_Info failed: %d", returnCodec); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_6; + } + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = inputBufferNum; + pExynosPort->portDefinition.nBufferCountMin = inputBufferNum; + pExynosPort->portDefinition.nBufferSize = inputBufferSize; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.audio.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/mpeg"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingMP3; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = outputBufferNum; + pExynosPort->portDefinition.nBufferCountMin = outputBufferNum; + pExynosPort->portDefinition.nBufferSize = outputBufferSize; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.audio.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/raw"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingPCM; + + /* Default values for Mp3 audio param */ + INIT_SET_SIZE_VERSION(&pMp3Dec->mp3Param, OMX_AUDIO_PARAM_MP3TYPE); + pMp3Dec->mp3Param.nPortIndex = INPUT_PORT_INDEX; + pMp3Dec->mp3Param.nChannels = DEFAULT_AUDIO_CHANNELS_NUM; + pMp3Dec->mp3Param.nBitRate = 0; + pMp3Dec->mp3Param.nSampleRate = DEFAULT_AUDIO_SAMPLING_FREQ; + pMp3Dec->mp3Param.nAudioBandWidth = 0; + pMp3Dec->mp3Param.eChannelMode = OMX_AUDIO_ChannelModeStereo; + pMp3Dec->mp3Param.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3; + + /* Default values for PCM audio param */ + INIT_SET_SIZE_VERSION(&pMp3Dec->pcmParam, OMX_AUDIO_PARAM_PCMMODETYPE); + pMp3Dec->pcmParam.nPortIndex = OUTPUT_PORT_INDEX; + pMp3Dec->pcmParam.nChannels = DEFAULT_AUDIO_CHANNELS_NUM; + pMp3Dec->pcmParam.eNumData = OMX_NumericalDataSigned; + pMp3Dec->pcmParam.eEndian = OMX_EndianLittle; + pMp3Dec->pcmParam.bInterleaved = OMX_TRUE; + pMp3Dec->pcmParam.nBitPerSample = DEFAULT_AUDIO_BIT_PER_SAMPLE; + pMp3Dec->pcmParam.nSamplingRate = DEFAULT_AUDIO_SAMPLING_FREQ; + pMp3Dec->pcmParam.ePCMMode = OMX_AUDIO_PCMModeLinear; + pMp3Dec->pcmParam.eChannelMapping[0] = OMX_AUDIO_ChannelLF; + pMp3Dec->pcmParam.eChannelMapping[1] = OMX_AUDIO_ChannelRF; + + pOMXComponent->GetParameter = &Exynos_SRP_Mp3Dec_GetParameter; + pOMXComponent->SetParameter = &Exynos_SRP_Mp3Dec_SetParameter; + pOMXComponent->GetConfig = &Exynos_SRP_Mp3Dec_GetConfig; + pOMXComponent->SetConfig = &Exynos_SRP_Mp3Dec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_SRP_Mp3Dec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_SRP_Mp3Dec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + /* ToDo: Change the function name associated with a specific codec */ + pExynosComponent->exynos_codec_componentInit = &Exynos_SRP_Mp3Dec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_SRP_Mp3Dec_Terminate; + pAudioDec->exynos_codec_bufferProcess = &Exynos_SRP_Mp3Dec_bufferProcess; + pAudioDec->exynos_checkInputFrame = NULL; + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + goto EXIT; /* This function is performed successfully. */ + +EXIT_ERROR_6: + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + Exynos_OSAL_Free(pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE]); + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = NULL; + pExynosPort->processData.allocSize = 0; +EXIT_ERROR_5: + SRP_Deinit(); +EXIT_ERROR_4: + SRP_Terminate(); +EXIT_ERROR_3: + Exynos_OSAL_Free(pMp3Dec); + pAudioDec->hCodecHandle = NULL; +EXIT_ERROR_2: + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; +EXIT_ERROR_1: + Exynos_OMX_AudioDecodeComponentDeinit(pOMXComponent); +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + if (pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE]) { + Exynos_OSAL_Free(pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE]); + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = NULL; + pExynosPort->processData.allocSize = 0; + } + + pMp3Dec = (EXYNOS_MP3_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + if (pMp3Dec != NULL) { + if (pMp3Dec->hSRPMp3Handle.bSRPLoaded == OMX_TRUE) { + SRP_Deinit(); + SRP_Terminate(); + } + Exynos_OSAL_Free(pMp3Dec); + ((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + } + + ret = Exynos_OMX_AudioDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/audio/dec/mp3/Exynos_OMX_Mp3dec.h b/openmax/component/audio/dec/mp3/Exynos_OMX_Mp3dec.h new file mode 100644 index 0000000..6e871b5 --- /dev/null +++ b/openmax/component/audio/dec/mp3/Exynos_OMX_Mp3dec.h @@ -0,0 +1,63 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Mp3dec.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#ifndef EXYNOS_OMX_MP3_DEC_COMPONENT +#define EXYNOS_OMX_MP3_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" + +typedef struct _EXYNOS_SRP_MP3_HANDLE +{ + OMX_U32 hSRPHandle; + OMX_BOOL bConfiguredSRP; + OMX_BOOL bSRPLoaded; + OMX_BOOL bSRPSendEOS; + OMX_S32 returnCodec; +} EXYNOS_SRP_MP3_HANDLE; + +typedef struct _EXYNOS_MP3_HANDLE +{ + /* OMX Codec specific */ + OMX_AUDIO_PARAM_MP3TYPE mp3Param; + OMX_AUDIO_PARAM_PCMMODETYPE pcmParam; + + /* SEC SRP Codec specific */ + EXYNOS_SRP_MP3_HANDLE hSRPMp3Handle; +} EXYNOS_MP3_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); + OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +#ifdef __cplusplus +}; +#endif + +#endif /* EXYNOS_OMX_MP3_DEC_COMPONENT */ diff --git a/openmax/component/audio/dec/mp3/NOTICE b/openmax/component/audio/dec/mp3/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/audio/dec/mp3/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/audio/dec/mp3/library_register.c b/openmax/component/audio/dec/mp3/library_register.c new file mode 100644 index 0000000..f0775cc --- /dev/null +++ b/openmax/component/audio/dec/mp3/library_register.c @@ -0,0 +1,58 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_MP3_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - audio decoder MP3 */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_MP3_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_MP3_DEC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + return MAX_COMPONENT_NUM; +} + diff --git a/openmax/component/audio/dec/mp3/library_register.h b/openmax/component/audio/dec/mp3/library_register.h new file mode 100644 index 0000000..7b9c34a --- /dev/null +++ b/openmax/component/audio/dec/mp3/library_register.h @@ -0,0 +1,54 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#ifndef EXYNOS_OMX_MP3_DEC_REG +#define EXYNOS_OMX_MP3_DEC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 1 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* MP3 */ +#define EXYNOS_OMX_COMPONENT_MP3_DEC "OMX.Exynos.MP3.Decoder" +#define EXYNOS_OMX_COMPONENT_MP3_DEC_ROLE "audio_decoder.mp3" + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif /* EXYNOS_OMX_MP3_DEC_REG */ + diff --git a/openmax/component/audio/dec/wma/Android.mk b/openmax/component/audio/dec/wma/Android.mk new file mode 100644 index 0000000..0b51c45 --- /dev/null +++ b/openmax/component/audio/dec/wma/Android.mk @@ -0,0 +1,34 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Wmadec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.WMA.Decoder +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Adec libExynosOMX_OSAL libExynosOMX_ABasecomponent \ + libsrpapi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libffmpegapi\ + +LOCAL_C_INCLUDES := $(EXYNOS_OMX_INC)/khronos \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/audio/dec \ + $(EXYNOS_AUDIO_CODEC)/alp/include \ + $(EXYNOS_AUDIO_CODEC)/ffmpeg/include + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/audio/dec/wma/Exynos_OMX_Wmadec.c b/openmax/component/audio/dec/wma/Exynos_OMX_Wmadec.c new file mode 100644 index 0000000..601a0c2 --- /dev/null +++ b/openmax/component/audio/dec/wma/Exynos_OMX_Wmadec.c @@ -0,0 +1,750 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Wmadec.c + * @brief + * @author Sungyeon Kim (sy85.kim@samsung.com) + * @version 1.0.0 + * @history + * 2012.09.07 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_ABasecomponent.h" +#include "Exynos_OMX_ABaseport.h" +#include "Exynos_OMX_Adec.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Wmadec.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_WMA_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OMX_ERRORTYPE Exynos_FFMPEG_WmaDec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nParamIndex) { + case OMX_IndexParamAudioWma: + { + OMX_AUDIO_PARAM_WMATYPE *pDstWmaParam = (OMX_AUDIO_PARAM_WMATYPE *)pComponentParameterStructure; + OMX_AUDIO_PARAM_WMATYPE *pSrcWmaParam = NULL; + EXYNOS_WMA_HANDLE *pWmaDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstWmaParam, sizeof(OMX_AUDIO_PARAM_WMATYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pDstWmaParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pWmaDec = (EXYNOS_WMA_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pSrcWmaParam = &pWmaDec->wmaParam; + + Exynos_OSAL_Memcpy(pDstWmaParam, pSrcWmaParam, sizeof(OMX_AUDIO_PARAM_WMATYPE)); + } + break; + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pDstPcmParam = (OMX_AUDIO_PARAM_PCMMODETYPE *)pComponentParameterStructure; + OMX_AUDIO_PARAM_PCMMODETYPE *pSrcPcmParam = NULL; + EXYNOS_WMA_HANDLE *pWmaDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pDstPcmParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pWmaDec = (EXYNOS_WMA_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pSrcPcmParam = &pWmaDec->pcmParam; + + Exynos_OSAL_Memcpy(pDstPcmParam, pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_S32 codecType; + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_WMA_DEC_ROLE); + } + break; + default: + ret = Exynos_OMX_AudioDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_FFMPEG_WmaDec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + case OMX_IndexParamAudioWma: + { + OMX_AUDIO_PARAM_WMATYPE *pDstWmaParam = NULL; + OMX_AUDIO_PARAM_WMATYPE *pSrcWmaParam = (OMX_AUDIO_PARAM_WMATYPE *)pComponentParameterStructure; + EXYNOS_WMA_HANDLE *pWmaDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcWmaParam, sizeof(OMX_AUDIO_PARAM_WMATYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcWmaParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pWmaDec = (EXYNOS_WMA_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDstWmaParam = &pWmaDec->wmaParam; + + Exynos_OSAL_Memcpy(pDstWmaParam, pSrcWmaParam, sizeof(OMX_AUDIO_PARAM_WMATYPE)); + } + break; + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pDstPcmParam = NULL; + OMX_AUDIO_PARAM_PCMMODETYPE *pSrcPcmParam = (OMX_AUDIO_PARAM_PCMMODETYPE *)pComponentParameterStructure; + EXYNOS_WMA_HANDLE *pWmaDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcPcmParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pWmaDec = (EXYNOS_WMA_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDstPcmParam = &pWmaDec->pcmParam; + + Exynos_OSAL_Memcpy(pDstPcmParam, pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_WMA_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingWMA; + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + default: + ret = Exynos_OMX_AudioDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_FFMPEG_WmaDec_GetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + /* TODO : Support for various OMX_INDEXTYPE */ + default: + ret = Exynos_OMX_AudioDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_FFMPEG_WmaDec_SetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + /* TODO : Support for various OMX_INDEXTYPE */ + default: + ret = Exynos_OMX_AudioDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_FFMPEG_WmaDec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if ((cParameterName == NULL) || (pIndexType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + ret = Exynos_OMX_AudioDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_FFMPEG_WmaDec_ComponentRoleEnum( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_U8 *cRole, + OMX_IN OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 codecType; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex != (MAX_COMPONENT_ROLE_NUM - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_WMA_DEC_ROLE); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_FFMPEG_WmaDec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMA_HANDLE *pWmaDec = (EXYNOS_WMA_HANDLE *)pAudioDec->hCodecHandle; + + FunctionIn(); + + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pExynosComponent->bUseFlagEOF = OMX_TRUE; /* Wma extractor should parse into frame unit. */ + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + FFmpeg_Init(&pWmaDec->ffmpeg); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_FFMPEG_WmaDec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMA_HANDLE *pWmaDec = (EXYNOS_WMA_HANDLE *)pAudioDec->hCodecHandle; + + FunctionIn(); + + FFmpeg_DeInit(&pWmaDec->ffmpeg); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_FFMPEG_WmaDec_codecConfigure(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMA_HANDLE *pWmaDec = (EXYNOS_WMA_HANDLE *)pAudioDec->hCodecHandle; + + const int codec_info_size = 18; + + FFmpeg *ffmpeg = &pWmaDec->ffmpeg; + CodecInfoHhr codecInfo; + char extra_data[10]; + + Exynos_OSAL_Memcpy(&codecInfo, pInputData->buffer.addr[AUDIO_DATA_PLANE], codec_info_size); + Exynos_OSAL_Memcpy(extra_data, ((char*)pInputData->buffer.addr[AUDIO_DATA_PLANE]) + codec_info_size, + codecInfo.codecSpecificDataSize); + + return FFmpeg_CodecOpen(ffmpeg, codecInfo.codecID, codecInfo.averageNumberOfbytesPerSecond * 8, + extra_data, codecInfo.codecSpecificDataSize, codecInfo.sampleRates, + codecInfo.numberOfChannels, codecInfo.blockAlignment); +} + +OMX_ERRORTYPE Exynos_FFMPEG_WmaDec_bufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData, EXYNOS_OMX_DATA *pOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMA_HANDLE *pWmaDec = (EXYNOS_WMA_HANDLE *)pAudioDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || (!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pInputPort)) || (!CHECK_PORT_POPULATED(pOutputPort))) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + ret = OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent)) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + ret = OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + + goto EXIT; + } + if (pInputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + ret = Exynos_FFMPEG_WmaDec_codecConfigure(pOMXComponent, pInputData); + } else { + /* Save timestamp and flags of input data */ + pOutputData->timeStamp = pInputData->timeStamp; + pOutputData->nFlags = pInputData->nFlags & (~OMX_BUFFERFLAG_EOS); + + /* WARNING IT DOESNT GUARANTEE WORKING WELL TO MULTIPLE FRAMES */ + pInputData->dataLen = pInputData->allocSize; + pOutputData->dataLen = pOutputData->allocSize; + ret = FFmpeg_Decode(&pWmaDec->ffmpeg, + pInputData->buffer.addr[AUDIO_DATA_PLANE], (int*)&pInputData->dataLen, + pOutputData->buffer.addr[AUDIO_DATA_PLANE], (int*)&pOutputData->dataLen); + } + + if (ret != OMX_ErrorNone) { + if (ret == OMX_ErrorInputDataDecodeYet) { + pOutputData->usedDataLen = 0; + pOutputData->remainDataLen = pOutputData->dataLen; + } else { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + pInputData->usedDataLen += pInputData->dataLen; + pInputData->remainDataLen = pInputData->dataLen - pInputData->usedDataLen; + pInputData->dataLen -= pInputData->usedDataLen; + pInputData->usedDataLen = 0; + + pOutputData->usedDataLen = 0; + pOutputData->remainDataLen = pOutputData->dataLen; + + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + pOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = NULL; + EXYNOS_WMA_HANDLE *pWmaDec = NULL; + OMX_PTR pInputBuffer = NULL; + OMX_PTR pOutputBuffer = NULL; + unsigned int inputBufferSize = AUDIO_INBUF_SIZE; + unsigned int inputBufferNum = 1; + unsigned int outputBufferSize = AVCODEC_MAX_AUDIO_FRAME_SIZE; + unsigned int outputBufferNum = 1; + OMX_S32 returnCodec; + int i = 0; + + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: parameters are null, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_WMA_DEC, componentName) != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: componentName(%s) error, ret: %X", __FUNCTION__, componentName, ret); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_AudioDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_AudioDecodeComponentInit error, ret: %X", __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = HW_AUDIO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: componentName alloc error, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_1; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_WMA_DEC); + + pWmaDec = Exynos_OSAL_Malloc(sizeof(EXYNOS_WMA_HANDLE)); + if (pWmaDec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: EXYNOS_WMA_HANDLE alloc error, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_2; + } + Exynos_OSAL_Memset(pWmaDec, 0, sizeof(EXYNOS_WMA_HANDLE)); + pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pAudioDec->hCodecHandle = (OMX_HANDLETYPE)pWmaDec; + + /* Get input buffer info */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = Exynos_OSAL_Malloc(inputBufferSize); + if (pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Input data buffer alloc failed"); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_3; + } + pExynosPort->processData.allocSize = inputBufferSize; + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = inputBufferNum; + pExynosPort->portDefinition.nBufferCountMin = inputBufferNum; + pExynosPort->portDefinition.nBufferSize = inputBufferSize; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.audio.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/x-ms-wma"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingWMA; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = outputBufferNum; + pExynosPort->portDefinition.nBufferCountMin = outputBufferNum; + pExynosPort->portDefinition.nBufferSize = outputBufferSize; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.audio.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/raw"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingPCM; + + /* Default values for Wma audio param */ + INIT_SET_SIZE_VERSION(&pWmaDec->wmaParam, OMX_AUDIO_PARAM_WMATYPE); + pWmaDec->wmaParam.nPortIndex = INPUT_PORT_INDEX; + pWmaDec->wmaParam.nChannels = DEFAULT_AUDIO_CHANNELS_NUM; + pWmaDec->wmaParam.nBitRate = 0; + pWmaDec->wmaParam.nSamplingRate = DEFAULT_AUDIO_SAMPLING_FREQ; + pWmaDec->wmaParam.eFormat = OMX_AUDIO_WMAFormat9; + + /* Default values for PCM audio param */ + INIT_SET_SIZE_VERSION(&pWmaDec->pcmParam, OMX_AUDIO_PARAM_PCMMODETYPE); + pWmaDec->pcmParam.nPortIndex = OUTPUT_PORT_INDEX; + pWmaDec->pcmParam.nChannels = DEFAULT_AUDIO_CHANNELS_NUM; + pWmaDec->pcmParam.eNumData = OMX_NumericalDataSigned; + pWmaDec->pcmParam.eEndian = OMX_EndianLittle; + pWmaDec->pcmParam.bInterleaved = OMX_TRUE; + pWmaDec->pcmParam.nBitPerSample = DEFAULT_AUDIO_BIT_PER_SAMPLE; + pWmaDec->pcmParam.nSamplingRate = DEFAULT_AUDIO_SAMPLING_FREQ; + pWmaDec->pcmParam.ePCMMode = OMX_AUDIO_PCMModeLinear; + pWmaDec->pcmParam.eChannelMapping[0] = OMX_AUDIO_ChannelLF; + pWmaDec->pcmParam.eChannelMapping[1] = OMX_AUDIO_ChannelRF; + + pOMXComponent->GetParameter = &Exynos_FFMPEG_WmaDec_GetParameter; + pOMXComponent->SetParameter = &Exynos_FFMPEG_WmaDec_SetParameter; + pOMXComponent->GetConfig = &Exynos_FFMPEG_WmaDec_GetConfig; + pOMXComponent->SetConfig = &Exynos_FFMPEG_WmaDec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_FFMPEG_WmaDec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_FFMPEG_WmaDec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + /* ToDo: Change the function name associated with a specific codec */ + pExynosComponent->exynos_codec_componentInit = &Exynos_FFMPEG_WmaDec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_FFMPEG_WmaDec_Terminate; + pAudioDec->exynos_codec_bufferProcess = &Exynos_FFMPEG_WmaDec_bufferProcess; + pAudioDec->exynos_checkInputFrame = NULL; + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + goto EXIT; /* This function is performed successfully. */ + +EXIT_ERROR_3: + Exynos_OSAL_Free(pWmaDec); + pAudioDec->hCodecHandle = NULL; +EXIT_ERROR_2: + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; +EXIT_ERROR_1: + Exynos_OMX_AudioDecodeComponentDeinit(pOMXComponent); +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_WMA_HANDLE *pWmaDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + if (pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE]) { + Exynos_OSAL_Free(pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE]); + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = NULL; + pExynosPort->processData.allocSize = 0; + } + + pWmaDec = (EXYNOS_WMA_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + if (pWmaDec != NULL) { + Exynos_OSAL_Free(pWmaDec); + ((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + } + + ret = Exynos_OMX_AudioDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/audio/dec/wma/Exynos_OMX_Wmadec.h b/openmax/component/audio/dec/wma/Exynos_OMX_Wmadec.h new file mode 100644 index 0000000..9cef0c4 --- /dev/null +++ b/openmax/component/audio/dec/wma/Exynos_OMX_Wmadec.h @@ -0,0 +1,68 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Wmadec.h + * @brief + * @author Sungyeon Kim (sy85.kim@samsung.com) + * @version 1.0.0 + * @history + * 2012.09.07 : Create + */ + +#ifndef EXYNOS_OMX_WMA_DEC_COMPONENT +#define EXYNOS_OMX_WMA_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "ffmpeg_api.h" + +/* + * This structure is the same as BitmapInfoHhr struct in pv_avifile_typedefs.h file + */ +typedef struct _CodecInfoHhr +{ + OMX_U16 codecID; + OMX_U16 numberOfChannels; + OMX_U32 sampleRates; + OMX_U32 averageNumberOfbytesPerSecond; + OMX_U16 blockAlignment; + OMX_U16 bitsPerSample; + OMX_U16 codecSpecificDataSize; +} CodecInfoHhr; + +typedef struct _EXYNOS_WMA_HANDLE +{ + /* OMX Codec specific */ + OMX_AUDIO_PARAM_WMATYPE wmaParam; + OMX_AUDIO_PARAM_PCMMODETYPE pcmParam; + + FFmpeg ffmpeg; +} EXYNOS_WMA_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); + OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +#ifdef __cplusplus +}; +#endif + +#endif /* EXYNOS_OMX_WMA_DEC_COMPONENT */ diff --git a/openmax/component/audio/dec/wma/NOTICE b/openmax/component/audio/dec/wma/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/audio/dec/wma/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/audio/dec/wma/library_register.c b/openmax/component/audio/dec/wma/library_register.c new file mode 100644 index 0000000..a2122c0 --- /dev/null +++ b/openmax/component/audio/dec/wma/library_register.c @@ -0,0 +1,57 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author Sungyeon Kim (sy85.kim@samsung.com) + * @version 1.0.0 + * @history + * 2012.09.07 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_WMA_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - audio decoder WMA */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_WMA_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_WMA_DEC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + return MAX_COMPONENT_NUM; +} diff --git a/openmax/component/audio/dec/wma/library_register.h b/openmax/component/audio/dec/wma/library_register.h new file mode 100644 index 0000000..0e7aaad --- /dev/null +++ b/openmax/component/audio/dec/wma/library_register.h @@ -0,0 +1,53 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author Sungyeon Kim (sy85.kim@samsung.com) + * @version 1.0.0 + * @history + * 2012.09.07 : Create + */ + +#ifndef EXYNOS_OMX_WMA_DEC_REG +#define EXYNOS_OMX_WMA_DEC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 1 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* WMA */ +#define EXYNOS_OMX_COMPONENT_WMA_DEC "OMX.Exynos.WMA.Decoder" +#define EXYNOS_OMX_COMPONENT_WMA_DEC_ROLE "audio_decoder.wma" + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif /* EXYNOS_OMX_WMA_DEC_REG */ diff --git a/openmax/component/audio/seiren_dec/Android.mk b/openmax/component/audio/seiren_dec/Android.mk new file mode 100644 index 0000000..89c4ba1 --- /dev/null +++ b/openmax/component/audio/seiren_dec/Android.mk @@ -0,0 +1,29 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + Exynos_OMX_Adec.c + +LOCAL_MODULE := libExynosOMX_Adec +LOCAL_ARM_MODE := arm +LOCAL_MODULE_TAGS := optional +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_STATIC_LIBRARIES := libseirenhw + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/audio/seiren_dec \ + $(EXYNOS_AUDIO_CODEC)/include + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +LOCAL_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif + +include $(BUILD_STATIC_LIBRARY) diff --git a/openmax/component/audio/seiren_dec/Exynos_OMX_Adec.c b/openmax/component/audio/seiren_dec/Exynos_OMX_Adec.c new file mode 100644 index 0000000..4ca8bfa --- /dev/null +++ b/openmax/component/audio/seiren_dec/Exynos_OMX_Adec.c @@ -0,0 +1,1537 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Adec.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#include +#include +#include +#include "Exynos_OMX_Macros.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OMX_Adec.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_ETC.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_AUDIO_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + temp_bufferHeader = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (temp_bufferHeader == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(temp_bufferHeader, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = temp_bufferHeader; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ASSIGNED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(temp_bufferHeader, OMX_BUFFERHEADERTYPE); + temp_bufferHeader->pBuffer = pBuffer; + temp_bufferHeader->nAllocLen = nSizeBytes; + temp_bufferHeader->pAppPrivate = pAppPrivate; + if (nPortIndex == INPUT_PORT_INDEX) + temp_bufferHeader->nInputPortIndex = INPUT_PORT_INDEX; + else + temp_bufferHeader->nOutputPortIndex = OUTPUT_PORT_INDEX; + + pExynosPort->assignedBufferNum++; + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + /* Exynos_OSAL_MutexLock(pExynosComponent->compMutex); */ + Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource); + /* Exynos_OSAL_MutexUnlock(pExynosComponent->compMutex); */ + } + *ppBufferHdr = temp_bufferHeader; + ret = OMX_ErrorNone; + goto EXIT; + } + } + + Exynos_OSAL_Free(temp_bufferHeader); + ret = OMX_ErrorInsufficientResources; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + temp_buffer = Exynos_OSAL_Malloc(sizeof(OMX_U8) * nSizeBytes); + if (temp_buffer == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + temp_bufferHeader = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (temp_bufferHeader == NULL) { + Exynos_OSAL_Free(temp_buffer); + temp_buffer = NULL; + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(temp_bufferHeader, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = temp_bufferHeader; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ALLOCATED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(temp_bufferHeader, OMX_BUFFERHEADERTYPE); + temp_bufferHeader->pBuffer = temp_buffer; + temp_bufferHeader->nAllocLen = nSizeBytes; + temp_bufferHeader->pAppPrivate = pAppPrivate; + if (nPortIndex == INPUT_PORT_INDEX) + temp_bufferHeader->nInputPortIndex = INPUT_PORT_INDEX; + else + temp_bufferHeader->nOutputPortIndex = OUTPUT_PORT_INDEX; + pExynosPort->assignedBufferNum++; + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + /* Exynos_OSAL_MutexLock(pExynosComponent->compMutex); */ + Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource); + /* Exynos_OSAL_MutexUnlock(pExynosComponent->compMutex); */ + } + *ppBuffer = temp_bufferHeader; + ret = OMX_ErrorNone; + goto EXIT; + } + } + + Exynos_OSAL_Free(temp_bufferHeader); + Exynos_OSAL_Free(temp_buffer); + ret = OMX_ErrorInsufficientResources; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosPort->portState != EXYNOS_OMX_PortStateDisabling) && + (pExynosPort->portState != EXYNOS_OMX_PortStateFlushingForDisable) && + (pExynosPort->portState != EXYNOS_OMX_PortStateInvalid)) { + (*(pExynosComponent->pCallbacks->EventHandler)) (pOMXComponent, + pExynosComponent->callbackData, + (OMX_U32)OMX_EventError, + (OMX_U32)OMX_ErrorPortUnpopulated, + nPortIndex, NULL); + } + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (((pExynosPort->bufferStateAllocate[i] | BUFFER_STATE_FREE) != 0) && (pExynosPort->extendBufferHeader[i].OMXBufferHeader != NULL)) { + if (pExynosPort->extendBufferHeader[i].OMXBufferHeader->pBuffer == pBufferHdr->pBuffer) { + if (pExynosPort->bufferStateAllocate[i] & BUFFER_STATE_ALLOCATED) { + Exynos_OSAL_Free(pExynosPort->extendBufferHeader[i].OMXBufferHeader->pBuffer); + pExynosPort->extendBufferHeader[i].OMXBufferHeader->pBuffer = NULL; + pBufferHdr->pBuffer = NULL; + } else if (pExynosPort->bufferStateAllocate[i] & BUFFER_STATE_ASSIGNED) { + ; /* None*/ + } + pExynosPort->assignedBufferNum--; + if (pExynosPort->bufferStateAllocate[i] & HEADER_STATE_ALLOCATED) { + Exynos_OSAL_Free(pExynosPort->extendBufferHeader[i].OMXBufferHeader); + pExynosPort->extendBufferHeader[i].OMXBufferHeader = NULL; + pBufferHdr = NULL; + } + pExynosPort->bufferStateAllocate[i] = BUFFER_STATE_FREE; + ret = OMX_ErrorNone; + goto EXIT; + } + } + } + +EXIT: + if (ret == OMX_ErrorNone) { + if (pExynosPort->assignedBufferNum == 0) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pExynosPort->unloadedResource signal set"); + /* Exynos_OSAL_MutexLock(pExynosComponent->compMutex); */ + Exynos_OSAL_SemaphorePost(pExynosPort->unloadedResource); + /* Exynos_OSAL_MutexUnlock(pExynosComponent->compMutex); */ + pExynosPort->portDefinition.bPopulated = OMX_FALSE; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AllocateTunnelBuffer(EXYNOS_OMX_BASEPORT *pOMXBasePort, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + OMX_U32 bufferSize = 0; + OMX_PARAM_PORTDEFINITIONTYPE portDefinition; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FreeTunnelBuffer(EXYNOS_OMX_BASEPORT *pOMXBasePort, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT* pExynosPort = NULL; + OMX_BUFFERHEADERTYPE* temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + OMX_U32 bufferSize = 0; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentTunnelRequest( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 nPort, + OMX_IN OMX_HANDLETYPE hTunneledComp, + OMX_IN OMX_U32 nTunneledPort, + OMX_INOUT OMX_TUNNELSETUPTYPE *pTunnelSetup) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} + +OMX_BOOL Exynos_Check_BufferProcess_State(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + if ((pExynosComponent->currentState == OMX_StateExecuting) && + (pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portState == EXYNOS_OMX_PortStateIdle) && + (pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portState == EXYNOS_OMX_PortStateIdle) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateIdleToExecuting)) { + return OMX_TRUE; + } else { + return OMX_FALSE; + } +} + +OMX_ERRORTYPE Exynos_InputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *exynosOMXInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOMXOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *dataBuffer = &exynosOMXInputPort->dataBuffer; + OMX_BUFFERHEADERTYPE *bufferHeader = dataBuffer->bufferHeader; + + FunctionIn(); + + if (bufferHeader != NULL) { + if (exynosOMXInputPort->markType.hMarkTargetComponent != NULL ) { + bufferHeader->hMarkTargetComponent = exynosOMXInputPort->markType.hMarkTargetComponent; + bufferHeader->pMarkData = exynosOMXInputPort->markType.pMarkData; + exynosOMXInputPort->markType.hMarkTargetComponent = NULL; + exynosOMXInputPort->markType.pMarkData = NULL; + } + + if (bufferHeader->hMarkTargetComponent != NULL) { + if (bufferHeader->hMarkTargetComponent == pOMXComponent) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventMark, + 0, 0, bufferHeader->pMarkData); + } else { + pExynosComponent->propagateMarkType.hMarkTargetComponent = bufferHeader->hMarkTargetComponent; + pExynosComponent->propagateMarkType.pMarkData = bufferHeader->pMarkData; + } + } + + bufferHeader->nFilledLen = 0; + Exynos_OMX_InputBufferReturn(pOMXComponent, bufferHeader); + } + + if ((pExynosComponent->currentState == OMX_StatePause) && + ((!CHECK_PORT_BEING_FLUSHED(exynosOMXInputPort) && !CHECK_PORT_BEING_FLUSHED(exynosOMXOutputPort)))) { + Exynos_OSAL_SignalWait(pExynosComponent->pauseEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pExynosComponent->pauseEvent); + } + + dataBuffer->dataValid = OMX_FALSE; + dataBuffer->dataLen = 0; + dataBuffer->remainDataLen = 0; + dataBuffer->usedDataLen = 0; + dataBuffer->bufferHeader = NULL; + dataBuffer->nFlags = 0; + dataBuffer->timeStamp = 0; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_InputBufferGetQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_DATABUFFER *dataBuffer = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + FunctionIn(); + + pExynosPort= &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + dataBuffer = &pExynosPort->dataBuffer; + + if (pExynosComponent->currentState != OMX_StateExecuting) { + ret = OMX_ErrorUndefined; + goto EXIT; + } else { + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + Exynos_OSAL_MutexLock(dataBuffer->bufferMutex); + if (dataBuffer->dataValid != OMX_TRUE) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message == NULL) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(dataBuffer->bufferMutex); + goto EXIT; + } + + dataBuffer->bufferHeader = (OMX_BUFFERHEADERTYPE *)(message->pCmdData); + dataBuffer->allocSize = dataBuffer->bufferHeader->nAllocLen; + dataBuffer->dataLen = dataBuffer->bufferHeader->nFilledLen; + dataBuffer->remainDataLen = dataBuffer->dataLen; + dataBuffer->usedDataLen = 0; + dataBuffer->dataValid = OMX_TRUE; + dataBuffer->nFlags = dataBuffer->bufferHeader->nFlags; + dataBuffer->timeStamp = dataBuffer->bufferHeader->nTimeStamp; + + Exynos_OSAL_Free(message); + + if (dataBuffer->allocSize <= dataBuffer->dataLen) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "Input Buffer Full, Check input buffer size! allocSize:%d, dataLen:%d", dataBuffer->allocSize, dataBuffer->dataLen); + } + Exynos_OSAL_MutexUnlock(dataBuffer->bufferMutex); + ret = OMX_ErrorNone; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OutputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *exynosOMXInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOMXOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *dataBuffer = &exynosOMXOutputPort->dataBuffer; + OMX_BUFFERHEADERTYPE *bufferHeader = dataBuffer->bufferHeader; + + FunctionIn(); + + if (bufferHeader != NULL) { + bufferHeader->nFilledLen = dataBuffer->remainDataLen; + bufferHeader->nOffset = 0; + bufferHeader->nFlags = dataBuffer->nFlags; + bufferHeader->nTimeStamp = dataBuffer->timeStamp; + + if (pExynosComponent->propagateMarkType.hMarkTargetComponent != NULL) { + bufferHeader->hMarkTargetComponent = pExynosComponent->propagateMarkType.hMarkTargetComponent; + bufferHeader->pMarkData = pExynosComponent->propagateMarkType.pMarkData; + pExynosComponent->propagateMarkType.hMarkTargetComponent = NULL; + pExynosComponent->propagateMarkType.pMarkData = NULL; + } + + if (bufferHeader->nFlags & OMX_BUFFERFLAG_EOS) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventBufferFlag, + OUTPUT_PORT_INDEX, + bufferHeader->nFlags, NULL); + } + + Exynos_OMX_OutputBufferReturn(pOMXComponent, bufferHeader); + } + + if ((pExynosComponent->currentState == OMX_StatePause) && + ((!CHECK_PORT_BEING_FLUSHED(exynosOMXInputPort) && !CHECK_PORT_BEING_FLUSHED(exynosOMXOutputPort)))) { + Exynos_OSAL_SignalWait(pExynosComponent->pauseEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pExynosComponent->pauseEvent); + } + + /* reset dataBuffer */ + dataBuffer->dataValid = OMX_FALSE; + dataBuffer->dataLen = 0; + dataBuffer->remainDataLen = 0; + dataBuffer->usedDataLen = 0; + dataBuffer->bufferHeader = NULL; + dataBuffer->nFlags = 0; + dataBuffer->timeStamp = 0; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OutputBufferGetQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_DATABUFFER *dataBuffer = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + FunctionIn(); + + pExynosPort= &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + dataBuffer = &pExynosPort->dataBuffer; + + if (pExynosComponent->currentState != OMX_StateExecuting) { + ret = OMX_ErrorUndefined; + goto EXIT; + } else { + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + Exynos_OSAL_MutexLock(dataBuffer->bufferMutex); + if (dataBuffer->dataValid != OMX_TRUE) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message == NULL) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(dataBuffer->bufferMutex); + goto EXIT; + } + + dataBuffer->bufferHeader = (OMX_BUFFERHEADERTYPE *)(message->pCmdData); + dataBuffer->allocSize = dataBuffer->bufferHeader->nAllocLen; + dataBuffer->dataLen = 0; //dataBuffer->bufferHeader->nFilledLen; + dataBuffer->remainDataLen = dataBuffer->dataLen; + dataBuffer->usedDataLen = 0; //dataBuffer->bufferHeader->nOffset; + dataBuffer->dataValid = OMX_TRUE; + /* dataBuffer->nFlags = dataBuffer->bufferHeader->nFlags; */ + /* dataBuffer->nTimeStamp = dataBuffer->bufferHeader->nTimeStamp; */ + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = dataBuffer->bufferHeader->pBuffer; + pExynosPort->processData.allocSize = dataBuffer->bufferHeader->nAllocLen; + + Exynos_OSAL_Free(message); + } + Exynos_OSAL_MutexUnlock(dataBuffer->bufferMutex); + ret = OMX_ErrorNone; + } +EXIT: + FunctionOut(); + + return ret; + +} + +OMX_BOOL Exynos_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *inputUseBuffer = &exynosInputPort->dataBuffer; + EXYNOS_OMX_DATA *inputData = &exynosInputPort->processData; + OMX_U32 copySize = 0; + OMX_BYTE checkInputStream = NULL; + OMX_U32 checkInputStreamLen = 0; + OMX_U32 checkedSize = 0; + OMX_BOOL flagEOF = OMX_FALSE; + OMX_BOOL previousFrameEOF = OMX_FALSE; + + FunctionIn(); + + if (inputUseBuffer->dataValid == OMX_TRUE) { + checkInputStream = inputUseBuffer->bufferHeader->pBuffer + inputUseBuffer->usedDataLen; + checkInputStreamLen = inputUseBuffer->remainDataLen; + + if (inputData->dataLen == 0) { + previousFrameEOF = OMX_TRUE; + } else { + previousFrameEOF = OMX_FALSE; + } + + /* Audio extractor should parse into frame units. */ + flagEOF = OMX_TRUE; + checkedSize = checkInputStreamLen; + copySize = checkedSize; + + if (inputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + + if (((inputData->allocSize) - (inputData->dataLen)) >= copySize) { + if (copySize > 0) + Exynos_OSAL_Memcpy((char*)inputData->buffer.addr[AUDIO_DATA_PLANE] + inputData->dataLen, checkInputStream, copySize); + + inputUseBuffer->dataLen -= copySize; + inputUseBuffer->remainDataLen -= copySize; + inputUseBuffer->usedDataLen += copySize; + + inputData->dataLen += copySize; + inputData->remainDataLen += copySize; + + if (previousFrameEOF == OMX_TRUE) { + inputData->timeStamp = inputUseBuffer->timeStamp; + inputData->nFlags = inputUseBuffer->nFlags; + } + + if (pExynosComponent->bUseFlagEOF == OMX_TRUE) { + if (pExynosComponent->bSaveFlagEOS == OMX_TRUE) { + inputData->nFlags |= OMX_BUFFERFLAG_EOS; + flagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + } else { + inputData->nFlags = (inputData->nFlags & (~OMX_BUFFERFLAG_EOS)); + } + } else { + if ((checkedSize == checkInputStreamLen) && (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + if ((inputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) && + ((inputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG) || + (inputData->dataLen == 0))) { + inputData->nFlags |= OMX_BUFFERFLAG_EOS; + flagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + } else if ((inputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) && + (!(inputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) && + (inputData->dataLen != 0)) { + inputData->nFlags = (inputData->nFlags & (~OMX_BUFFERFLAG_EOS)); + flagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + } + } else { + inputData->nFlags = (inputUseBuffer->nFlags & (~OMX_BUFFERFLAG_EOS)); + } + } + } else { + /*????????????????????????????????? Error ?????????????????????????????????*/ + Exynos_InputBufferReturn(pOMXComponent); + Exynos_ResetCodecData(inputData); + flagEOF = OMX_FALSE; + } + + if ((inputUseBuffer->remainDataLen == 0) || + (CHECK_PORT_BEING_FLUSHED(exynosInputPort))) + Exynos_InputBufferReturn(pOMXComponent); + else + inputUseBuffer->dataValid = OMX_TRUE; + } + + if (flagEOF == OMX_TRUE) { + if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) { + /* Flush seiren buffers */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "EOFFFFFFFF!!!!!!!!OMX_FLUSH_SEIREN"); + + pAudioDec->exynos_codec_flushSeiren(pOMXComponent, PORT_OUT); + //ADec_Flush(NULL, PORT_OUT); + + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_TRUE; + pExynosComponent->checkTimeStamp.startTimeStamp = inputData->timeStamp; + pExynosComponent->checkTimeStamp.nStartFlags = inputData->nFlags; + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "first frame timestamp after seeking %lld us (%.2f secs)", + inputData->timeStamp, inputData->timeStamp / 1E6); + } + + ret = OMX_TRUE; + } else { + ret = OMX_FALSE; + } + + FunctionOut(); + + return ret; +} + +OMX_BOOL Exynos_Postprocess_OutputData(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *outputUseBuffer = &exynosOutputPort->dataBuffer; + EXYNOS_OMX_DATA *outputData = &exynosOutputPort->processData; + OMX_U32 copySize = 0; + + FunctionIn(); + + if (outputUseBuffer->dataValid == OMX_TRUE) { + if (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE) { + if (pExynosComponent->checkTimeStamp.startTimeStamp == outputData->timeStamp) { + pExynosComponent->checkTimeStamp.startTimeStamp = RESET_TIMESTAMP_VAL; + pExynosComponent->checkTimeStamp.nStartFlags = 0x0; + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + } else { + ret = OMX_TRUE; + goto EXIT; + } + } else if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) { + ret = OMX_TRUE; + goto EXIT; + } + + if (outputData->remainDataLen <= (outputUseBuffer->allocSize - outputUseBuffer->dataLen)) { + copySize = outputData->remainDataLen; + + outputUseBuffer->dataLen += copySize; + outputUseBuffer->remainDataLen += copySize; + outputUseBuffer->nFlags = outputData->nFlags; + outputUseBuffer->timeStamp = outputData->timeStamp; + + ret = OMX_TRUE; + + if ((outputUseBuffer->remainDataLen > 0) || + (outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) || + (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + Exynos_OutputBufferReturn(pOMXComponent); + + /* reset outputData */ + Exynos_ResetCodecData(outputData); + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "output buffer is smaller than decoded data size Out Length"); + + ret = OMX_FALSE; + + /* reset outputData */ + Exynos_ResetCodecData(outputData); + } + } else { + ret = OMX_FALSE; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferProcess(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *inputUseBuffer = &exynosInputPort->dataBuffer; + EXYNOS_OMX_DATABUFFER *outputUseBuffer = &exynosOutputPort->dataBuffer; + EXYNOS_OMX_DATA *inputData = &exynosInputPort->processData; + EXYNOS_OMX_DATA *outputData = &exynosOutputPort->processData; + OMX_U32 copySize = 0; + + pExynosComponent->reInputData = OMX_FALSE; + + FunctionIn(); + + while (!pAudioDec->bExitBufferProcessThread) { + if (((pExynosComponent->currentState == OMX_StatePause) || + (pExynosComponent->currentState == OMX_StateIdle) || + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle) || + (pExynosComponent->transientState == EXYNOS_OMX_TransStateExecutingToIdle)) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateIdleToLoaded)&& + ((!CHECK_PORT_BEING_FLUSHED(exynosInputPort) && !CHECK_PORT_BEING_FLUSHED(exynosOutputPort)))) { + Exynos_OSAL_SignalWait(pExynosComponent->pauseEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pExynosComponent->pauseEvent); + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent)) && (!pAudioDec->bExitBufferProcessThread)) { + Exynos_OSAL_MutexLock(outputUseBuffer->bufferMutex); + if ((outputUseBuffer->dataValid != OMX_TRUE) && + (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + Exynos_OSAL_MutexUnlock(outputUseBuffer->bufferMutex); + ret = Exynos_OutputBufferGetQueue(pExynosComponent); + if ((ret == OMX_ErrorUndefined) || + (exynosInputPort->portState != EXYNOS_OMX_PortStateIdle) || + (exynosOutputPort->portState != EXYNOS_OMX_PortStateIdle)) { + break; + } + } else { + Exynos_OSAL_MutexUnlock(outputUseBuffer->bufferMutex); + } + + if (pExynosComponent->reInputData == OMX_FALSE) { + Exynos_OSAL_MutexLock(inputUseBuffer->bufferMutex); + if ((Exynos_Preprocessor_InputData(pOMXComponent) == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(exynosInputPort))) { + Exynos_OSAL_MutexUnlock(inputUseBuffer->bufferMutex); + ret = Exynos_InputBufferGetQueue(pExynosComponent); + break; + } + + Exynos_OSAL_MutexUnlock(inputUseBuffer->bufferMutex); + } + + Exynos_OSAL_MutexLock(inputUseBuffer->bufferMutex); + Exynos_OSAL_MutexLock(outputUseBuffer->bufferMutex); + if ((outputUseBuffer->dataValid == OMX_TRUE) && ((inputData->dataLen > 0) || (inputData->nFlags & OMX_BUFFERFLAG_EOS))) + ret = pAudioDec->exynos_codec_bufferProcess(pOMXComponent, inputData, outputData); + else { + ret = OMX_ErrorNone; + Exynos_OSAL_MutexUnlock(outputUseBuffer->bufferMutex); + Exynos_OSAL_MutexUnlock(inputUseBuffer->bufferMutex); + break; + } + Exynos_OSAL_MutexUnlock(outputUseBuffer->bufferMutex); + Exynos_OSAL_MutexUnlock(inputUseBuffer->bufferMutex); + + if (ret == (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet) + pExynosComponent->reInputData = OMX_TRUE; + else + pExynosComponent->reInputData = OMX_FALSE; + + Exynos_OSAL_MutexLock(outputUseBuffer->bufferMutex); + Exynos_Postprocess_OutputData(pOMXComponent); + Exynos_OSAL_MutexUnlock(outputUseBuffer->bufferMutex); + } + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetFlushBuffer(EXYNOS_OMX_BASEPORT *pExynosPort, EXYNOS_OMX_DATABUFFER **pDataBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + *pDataBuffer = &pExynosPort->dataBuffer; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FlushPort(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 portIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_DATABUFFER *flushPortBuffer = NULL; + OMX_BUFFERHEADERTYPE *bufferHeader = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + OMX_U32 flushNum = 0; + OMX_S32 semValue = 0; + + FunctionIn(); + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + while (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > 0) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message != NULL) { + bufferHeader = (OMX_BUFFERHEADERTYPE *)message->pCmdData; + bufferHeader->nFilledLen = 0; + + if (portIndex == OUTPUT_PORT_INDEX) { + Exynos_OMX_OutputBufferReturn(pOMXComponent, bufferHeader); + } else { + Exynos_OMX_InputBufferReturn(pOMXComponent, bufferHeader); + } + + Exynos_OSAL_Free(message); + message = NULL; + } + } + + Exynos_OMX_GetFlushBuffer(pExynosPort, &flushPortBuffer); + if (flushPortBuffer != NULL) { + if (flushPortBuffer->dataValid == OMX_TRUE) { + if (portIndex == INPUT_PORT_INDEX) + Exynos_InputBufferReturn(pOMXComponent); + else if (portIndex == OUTPUT_PORT_INDEX) + Exynos_OutputBufferReturn(pOMXComponent); + + /* reset outputData */ + Exynos_ResetCodecData(&(pExynosPort->processData)); + } + } + + while(1) { + OMX_S32 cnt = 0; + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[portIndex].bufferSemID, &cnt); + if (cnt <= 0) + break; + if (Exynos_OSAL_SemaphoreTryWait(pExynosComponent->pExynosPort[portIndex].bufferSemID) == OMX_ErrorUndefined) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "Cannot be happened"); + } + Exynos_OSAL_SetElemNum(&pExynosPort->bufferQ, 0); + + pExynosPort->processData.dataLen = 0; + pExynosPort->processData.nFlags = 0; + pExynosPort->processData.remainDataLen = 0; + pExynosPort->processData.timeStamp = 0; + pExynosPort->processData.usedDataLen = 0; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferFlush(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex, OMX_BOOL bEvent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_DATABUFFER *flushPortBuffer = NULL; + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_SignalSet(pExynosComponent->pauseEvent); + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + Exynos_OMX_GetFlushBuffer(pExynosPort, &flushPortBuffer); + + Exynos_OSAL_MutexLock(flushPortBuffer->bufferMutex); + ret = Exynos_OMX_FlushPort(pOMXComponent, nPortIndex); + Exynos_OSAL_MutexUnlock(flushPortBuffer->bufferMutex); + + if (bEvent == OMX_TRUE && ret == OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "bEVENT!!!!!!OMX_FLUSH_SEIREN"); + pAudioDec->exynos_codec_flushSeiren(pOMXComponent, nPortIndex); + } + + if (nPortIndex == INPUT_PORT_INDEX) { + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_TRUE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->reInputData = OMX_FALSE; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR ComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (ComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + switch (nParamIndex) { + case OMX_IndexParamAudioInit: + { + OMX_PORT_PARAM_TYPE *portParam = (OMX_PORT_PARAM_TYPE *)ComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(portParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + portParam->nPorts = pExynosComponent->portParam.nPorts; + portParam->nStartPortNumber = pExynosComponent->portParam.nStartPortNumber; + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamAudioPortFormat: + { + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormat = (OMX_AUDIO_PARAM_PORTFORMATTYPE *)ComponentParameterStructure; + OMX_U32 portIndex = portFormat->nPortIndex; + OMX_U32 index = portFormat->nIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = NULL; + OMX_U32 supportFormatNum = 0; /* supportFormatNum = N-1 */ + + ret = Exynos_OMX_Check_SizeVersion(portFormat, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((portIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + + if (portIndex == INPUT_PORT_INDEX) { + supportFormatNum = INPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1; + if (index > supportFormatNum) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + portDefinition = &pExynosPort->portDefinition; + + portFormat->eEncoding = portDefinition->format.audio.eEncoding; + } else if (portIndex == OUTPUT_PORT_INDEX) { + supportFormatNum = OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1; + if (index > supportFormatNum) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + portDefinition = &pExynosPort->portDefinition; + + portFormat->eEncoding = portDefinition->format.audio.eEncoding; + } + ret = OMX_ErrorNone; + } + break; + default: + { + ret = Exynos_OMX_GetParameter(hComponent, nParamIndex, ComponentParameterStructure); + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} +OMX_ERRORTYPE Exynos_OMX_AudioDecodeSetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR ComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (ComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + switch (nIndex) { + case OMX_IndexParamAudioPortFormat: + { + OMX_AUDIO_PARAM_PORTFORMATTYPE *portFormat = (OMX_AUDIO_PARAM_PORTFORMATTYPE *)ComponentParameterStructure; + OMX_U32 portIndex = portFormat->nPortIndex; + OMX_U32 index = portFormat->nIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = NULL; + OMX_U32 supportFormatNum = 0; /* supportFormatNum = N-1 */ + + ret = Exynos_OMX_Check_SizeVersion(portFormat, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((portIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + portDefinition = &pExynosPort->portDefinition; + + portDefinition->format.audio.eEncoding = portFormat->eEncoding; + ret = OMX_ErrorNone; + } + break; + default: + { + ret = Exynos_OMX_SetParameter(hComponent, nIndex, ComponentParameterStructure); + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = Exynos_OMX_GetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeSetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + case OMX_IndexConfigAudioMute: + { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX_IndexConfigAudioMute"); + ret = OMX_ErrorUnsupportedIndex; + } + break; + case OMX_IndexConfigAudioVolume: + { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX_IndexConfigAudioVolume"); + ret = OMX_ErrorUnsupportedIndex; + } + break; + default: + ret = Exynos_OMX_SetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if ((cParameterName == NULL) || (pIndexType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + ret = Exynos_OMX_GetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_BufferProcessThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pSECComponent = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + FunctionIn(); + + if (threadData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + pSECComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + Exynos_OMX_BufferProcess(pOMXComponent); + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferProcess_Create(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + FunctionIn(); + + pAudioDec->bExitBufferProcessThread = OMX_FALSE; + + ret = Exynos_OSAL_ThreadCreate(&pAudioDec->hBufferProcessThread, + Exynos_OMX_BufferProcessThread, + pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferProcess_Terminate(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + OMX_S32 countValue = 0; + unsigned int i = 0; + + FunctionIn(); + + pAudioDec->bExitBufferProcessThread = OMX_TRUE; + + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[i].bufferSemID, &countValue); + if (countValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[i].bufferSemID); + } + + Exynos_OSAL_SignalSet(pExynosComponent->pauseEvent); + Exynos_OSAL_ThreadTerminate(pAudioDec->hBufferProcessThread); + pAudioDec->hBufferProcessThread = NULL; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + goto EXIT; + } + + ret = Exynos_OMX_BaseComponent_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + goto EXIT; + } + + ret = Exynos_OMX_Port_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pAudioDec = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_AUDIODEC_COMPONENT)); + if (pAudioDec == NULL) { + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + + Exynos_OSAL_Memset(pAudioDec, 0, sizeof(EXYNOS_OMX_AUDIODEC_COMPONENT)); + pExynosComponent->hComponentHandle = (OMX_HANDLETYPE)pAudioDec; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = MAX_AUDIO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MAX_AUDIO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = DEFAULT_AUDIO_INPUT_BUFFER_SIZE; + pExynosPort->portDefinition.eDomain = OMX_PortDomainAudio; + + pExynosPort->portDefinition.format.audio.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/raw"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingUnused; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = MAX_AUDIO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MAX_AUDIO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.eDomain = OMX_PortDomainAudio; + + pExynosPort->portDefinition.format.audio.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/raw"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingUnused; + + + pOMXComponent->UseBuffer = &Exynos_OMX_UseBuffer; + pOMXComponent->AllocateBuffer = &Exynos_OMX_AllocateBuffer; + pOMXComponent->FreeBuffer = &Exynos_OMX_FreeBuffer; + pOMXComponent->ComponentTunnelRequest = &Exynos_OMX_ComponentTunnelRequest; + +#ifdef TUNNELING_SUPPORT + pExynosComponent->exynos_AllocateTunnelBuffer = &Exynos_OMX_AllocateTunnelBuffer; + pExynosComponent->exynos_FreeTunnelBuffer = &Exynos_OMX_FreeTunnelBuffer; +#endif + pExynosComponent->exynos_BufferProcessCreate = &Exynos_OMX_BufferProcess_Create; + pExynosComponent->exynos_BufferProcessTerminate = &Exynos_OMX_BufferProcess_Terminate; + pExynosComponent->exynos_BufferFlush = &Exynos_OMX_BufferFlush; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AudioDecodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = NULL; + int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + Exynos_OSAL_Free(pAudioDec); + pExynosComponent->hComponentHandle = pAudioDec = NULL; + + for(i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + Exynos_OSAL_Free(pExynosPort->portDefinition.format.audio.cMIMEType); + pExynosPort->portDefinition.format.audio.cMIMEType = NULL; + } + + ret = Exynos_OMX_Port_Destructor(pOMXComponent); + + ret = Exynos_OMX_BaseComponent_Destructor(hComponent); + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/audio/seiren_dec/Exynos_OMX_Adec.h b/openmax/component/audio/seiren_dec/Exynos_OMX_Adec.h new file mode 100644 index 0000000..d0d0bf5 --- /dev/null +++ b/openmax/component/audio/seiren_dec/Exynos_OMX_Adec.h @@ -0,0 +1,143 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Adec.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#ifndef EXYNOS_OMX_AUDIO_DECODE +#define EXYNOS_OMX_AUDIO_DECODE + +#include "OMX_Component.h" +#include "Exynos_OMX_Def.h" +#include "Exynos_OSAL_Queue.h" +#include "Exynos_OMX_ABaseport.h" +#include "Exynos_OMX_ABasecomponent.h" +#include "seiren_hw.h" + +#define MAX_AUDIO_INPUTBUFFER_NUM 2 +#define MAX_AUDIO_OUTPUTBUFFER_NUM 2 + +#define DEFAULT_AUDIO_INPUT_BUFFER_SIZE (16 * 1024) +#define DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE (32 * 1024) + +#define DEFAULT_AUDIO_SAMPLING_FREQ 44100 +#define DEFAULT_AUDIO_CHANNELS_NUM 2 +#define DEFAULT_AUDIO_BIT_PER_SAMPLE 16 + +#define INPUT_PORT_SUPPORTFORMAT_NUM_MAX 1 +#define OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX 1 + +#define AUDIO_DATA_PLANE 0 + +typedef struct _SRP_DEC_INPUT_BUFFER +{ + void *PhyAddr; // physical address + void *VirAddr; // virtual address + int bufferSize; // input buffer alloc size + int dataSize; // Data length +} SRP_DEC_INPUT_BUFFER; + +typedef struct _EXYNOS_OMX_AUDIODEC_COMPONENT +{ + OMX_HANDLETYPE hCodecHandle; + + OMX_BOOL bFirstFrame; + OMX_PTR pInputBuffer; + SRP_DEC_INPUT_BUFFER SRPDecInputBuffer[MAX_AUDIO_INPUTBUFFER_NUM]; + OMX_U32 indexInputBuffer; + + /* Buffer Process */ + OMX_BOOL bExitBufferProcessThread; + OMX_HANDLETYPE hBufferProcessThread; + + OMX_ERRORTYPE (*exynos_codec_bufferProcess) (OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData, EXYNOS_OMX_DATA *pOutputData); + OMX_ERRORTYPE (*exynos_codec_flushSeiren) (OMX_COMPONENTTYPE *pOMXComponent, SEIREN_PORTTYPE type); + + int (*exynos_checkInputFrame)(OMX_U8 *pInputStream, OMX_U32 buffSize, OMX_U32 flag, OMX_BOOL bPreviousFrameEOF, OMX_BOOL *pbEndOfFrame); +} EXYNOS_OMX_AUDIODEC_COMPONENT; + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer); +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes); +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr); +OMX_ERRORTYPE Exynos_OMX_AllocateTunnelBuffer( + EXYNOS_OMX_BASEPORT *pOMXBasePort, + OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_FreeTunnelBuffer( + EXYNOS_OMX_BASEPORT *pOMXBasePort, + OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_ComponentTunnelRequest( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 nPort, + OMX_IN OMX_HANDLETYPE hTunneledComp, + OMX_IN OMX_U32 nTunneledPort, + OMX_INOUT OMX_TUNNELSETUPTYPE *pTunnelSetup); +OMX_ERRORTYPE Exynos_OMX_BufferProcess(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR ComponentParameterStructure); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeSetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR ComponentParameterStructure); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeSetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeGetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_AudioDecodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent); +OMX_BOOL Exynos_Check_BufferProcess_State(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); + +#ifdef __cplusplus +} +#endif + +#endif /* EXYNOS_OMX_AUDIO_DECODE */ diff --git a/openmax/component/audio/seiren_dec/NOTICE b/openmax/component/audio/seiren_dec/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/audio/seiren_dec/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/audio/seiren_dec/aac/Android.mk b/openmax/component/audio/seiren_dec/aac/Android.mk new file mode 100644 index 0000000..0fde9ae --- /dev/null +++ b/openmax/component/audio/seiren_dec/aac/Android.mk @@ -0,0 +1,41 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Aacdec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.AAC.Decoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Adec libExynosOMX_OSAL libExynosOMX_ABasecomponent \ + libseirenhw +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/audio/seiren_dec \ + $(EXYNOS_AUDIO_CODEC)/include + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.c b/openmax/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.c new file mode 100644 index 0000000..7cc80a6 --- /dev/null +++ b/openmax/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.c @@ -0,0 +1,970 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Aacdec.c + * @brief + * @author Sungyeon Kim (sy85.kim@samsung.com) + * @version 1.0.0 + * @history + * 2012.12.22 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_ABasecomponent.h" +#include "Exynos_OMX_ABaseport.h" +#include "Exynos_OMX_Adec.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Aacdec.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_AAC_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +//#define Seiren_DUMP_TO_FILE +#ifdef Seiren_DUMP_TO_FILE +#include "stdio.h" + +FILE *inFile; +FILE *outFile; +#endif + +OMX_ERRORTYPE Exynos_Seiren_AacDec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nParamIndex) { + case OMX_IndexParamAudioAac: + { + OMX_AUDIO_PARAM_AACPROFILETYPE *pDstAacParam = (OMX_AUDIO_PARAM_AACPROFILETYPE *)pComponentParameterStructure; + OMX_AUDIO_PARAM_AACPROFILETYPE *pSrcAacParam = NULL; + EXYNOS_AAC_HANDLE *pAacDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstAacParam, sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstAacParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pAacDec = (EXYNOS_AAC_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pSrcAacParam = &pAacDec->aacParam; + + Exynos_OSAL_Memcpy(pDstAacParam, pSrcAacParam, sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE)); + } + break; + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pDstPcmParam = (OMX_AUDIO_PARAM_PCMMODETYPE *)pComponentParameterStructure; + OMX_AUDIO_PARAM_PCMMODETYPE *pSrcPcmParam = NULL; + EXYNOS_AAC_HANDLE *pAacDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstPcmParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pAacDec = (EXYNOS_AAC_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pSrcPcmParam = &pAacDec->pcmParam; + + Exynos_OSAL_Memcpy(pDstPcmParam, pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_S32 codecType; + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_AAC_DEC_ROLE); + } + break; + default: + ret = Exynos_OMX_AudioDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_AacDec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + case OMX_IndexParamAudioAac: + { + OMX_AUDIO_PARAM_AACPROFILETYPE *pDstAacParam = NULL; + OMX_AUDIO_PARAM_AACPROFILETYPE *pSrcAacParam = (OMX_AUDIO_PARAM_AACPROFILETYPE *)pComponentParameterStructure; + EXYNOS_AAC_HANDLE *pAacDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcAacParam, sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcAacParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pAacDec = (EXYNOS_AAC_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDstAacParam = &pAacDec->aacParam; + + Exynos_OSAL_Memcpy(pDstAacParam, pSrcAacParam, sizeof(OMX_AUDIO_PARAM_AACPROFILETYPE)); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nSize : %d \e[0m", pDstAacParam->nSize); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nPortIndex : %d \e[0m", pDstAacParam->nPortIndex); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nChannels : %d \e[0m", pDstAacParam->nChannels); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nSampleRate : %d \e[0m", pDstAacParam->nSampleRate); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nBitRate : %d \e[0m", pDstAacParam->nBitRate); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nAudioBandWidth : %d \e[0m", pDstAacParam->nAudioBandWidth); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nFrameLength : %d \e[0m", pDstAacParam->nFrameLength); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nAACtools : %d \e[0m", pDstAacParam->nAACtools); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nAACERtools : %d \e[0m", pDstAacParam->nAACERtools); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m eAACProfile : %d \e[0m", pDstAacParam->eAACProfile); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m eAACStreamFormat : %d \e[0m", pDstAacParam->eAACStreamFormat); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m eChannelMode : %d \e[0m", pDstAacParam->eChannelMode); + } + break; + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pDstPcmParam = NULL; + OMX_AUDIO_PARAM_PCMMODETYPE *pSrcPcmParam = (OMX_AUDIO_PARAM_PCMMODETYPE *)pComponentParameterStructure; + EXYNOS_AAC_HANDLE *pAacDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcPcmParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pAacDec = (EXYNOS_AAC_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDstPcmParam = &pAacDec->pcmParam; + + Exynos_OSAL_Memcpy(pDstPcmParam, pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_AAC_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingAAC; + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + default: + ret = Exynos_OMX_AudioDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_AacDec_GetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = Exynos_OMX_AudioDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_AacDec_SetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = Exynos_OMX_AudioDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_AacDec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if ((cParameterName == NULL) || (pIndexType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + ret = Exynos_OMX_AudioDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_AacDec_ComponentRoleEnum( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_U8 *cRole, + OMX_IN OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 codecType; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex != (MAX_COMPONENT_ROLE_NUM - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_AAC_DEC_ROLE); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_AacDec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_AAC_HANDLE *pAacDec = (EXYNOS_AAC_HANDLE *)pAudioDec->hCodecHandle; + + FunctionIn(); + + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pExynosComponent->bUseFlagEOF = OMX_TRUE; /* Aac extractor should parse into frame unit. */ + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pAacDec->hSeirenAacHandle.bConfiguredSeiren = OMX_FALSE; + pAacDec->hSeirenAacHandle.bSeirenSendEOS = OMX_FALSE; + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + +#ifdef Seiren_DUMP_TO_FILE + inFile = fopen("/data/InFile.aac", "w+"); + outFile = fopen("/data/OutFile.pcm", "w+"); +#endif + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_AacDec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + FunctionIn(); + +#ifdef Seiren_DUMP_TO_FILE + fclose(inFile); + fclose(outFile); +#endif + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Aac_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData, EXYNOS_OMX_DATA *pOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_AAC_HANDLE *pAacDec = (EXYNOS_AAC_HANDLE *)pAudioDec->hCodecHandle; + int returnCodec = 0; + unsigned long long isSeirenStopped = 0; + OMX_BOOL isSeirenIbufOverflow = OMX_FALSE; + + u32 fd = pAacDec->hSeirenAacHandle.hSeirenHandle; + audio_mem_info_t input_mem_pool = pAacDec->hSeirenAacHandle.input_mem_pool; + audio_mem_info_t output_mem_pool = pAacDec->hSeirenAacHandle.output_mem_pool; + unsigned long long sample_rate, channels; + int consumed_size = 0; + sample_rate = channels = 0; + + FunctionIn(); + +#ifdef Seiren_DUMP_TO_FILE + if (pExynosComponent->reInputData == OMX_FALSE) { + fwrite(pInputData->buffer.addr[AUDIO_DATA_PLANE], pInputData->dataLen, 1, inFile); + } +#endif + + /* Save timestamp and flags of input data */ + pOutputData->timeStamp = pInputData->timeStamp; + pOutputData->nFlags = pInputData->nFlags & (~OMX_BUFFERFLAG_EOS); + + /* Decoding aac frames by Seiren */ + if (pExynosComponent->getAllDelayBuffer == OMX_FALSE) { + input_mem_pool.data_size = pInputData->dataLen; + char* pt = input_mem_pool.virt_addr; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33m %02X %02X %02X %02X %02X %02X %lld \e[0m", *pt,*(pt+1),*(pt+2),*(pt+3),*(pt+4), *(pt+5), pInputData->timeStamp); + + if (pInputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + if (pAacDec->hSeirenAacHandle.bConfiguredSeiren == OMX_TRUE) + goto EXIT; + + ADec_ConfigSignal(fd); + unsigned char sample_rate_index = ((*(pt+1)) >> 7 & 0x01) | + ((*pt) << 1 & 0x0e); + unsigned char num_of_channel = ((*(pt+1)) >> 3 & 0x07); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "index %x ", sample_rate_index); + ADec_SetParams(fd, PCM_PARAM_SAMPLE_RATE, (unsigned long long)aac_sample_rates[sample_rate_index]); + ADec_SetParams(fd, PCM_PARAM_NUM_OF_CH, (unsigned long long)num_of_channel); + + /* AAC setup-data(or DSI) could be various length. But it only needs 2byte */ + input_mem_pool.data_size = 2; + ADec_SendStream(fd, &input_mem_pool, &consumed_size); + goto EXIT; + } + returnCodec = ADec_SendStream(fd, &input_mem_pool, &consumed_size); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "ProcessedSize : %d return : %d", consumed_size, returnCodec); + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "EOS!!"); + if (returnCodec >= 0) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) { + ADec_SendEOS(fd); + pAacDec->hSeirenAacHandle.bSeirenSendEOS = OMX_TRUE; + } + } else if (returnCodec < 0) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + if (pAacDec->hSeirenAacHandle.bConfiguredSeiren == OMX_FALSE) { + if ((pInputData->dataLen <= 0) && (pInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + pOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pAacDec->hSeirenAacHandle.bSeirenSendEOS = OMX_FALSE; + ret = OMX_ErrorNone; + goto EXIT; + } + + returnCodec = ADec_GetParams(fd, PCM_PARAM_SAMPLE_RATE, &sample_rate); + returnCodec = returnCodec | ADec_GetParams(fd, PCM_PARAM_NUM_OF_CH, &channels); + + if (returnCodec < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_ADec_GetParams failed: %d", returnCodec); + ret = OMX_ErrorHardware; + goto EXIT; + } + + if (!sample_rate || !channels) { + if (pAacDec->hSeirenAacHandle.bSeirenSendEOS == OMX_TRUE) { + pOutputData->dataLen = 0; + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + } else { + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + } + ret = OMX_ErrorNone; + goto EXIT;// + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "numChannels(%d), samplingRate(%d)", + channels, sample_rate); + + if (pAacDec->pcmParam.nChannels != channels || + pAacDec->pcmParam.nSamplingRate != sample_rate) { + /* Change channel count and sampling rate information */ + pAacDec->pcmParam.nChannels = channels; + pAacDec->pcmParam.nSamplingRate = sample_rate; + + /* Send Port Settings changed call back */ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + + pAacDec->hSeirenAacHandle.bConfiguredSeiren = OMX_TRUE; + + if (pAacDec->hSeirenAacHandle.bSeirenSendEOS == OMX_TRUE) { + pOutputData->dataLen = 0; + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + } else { + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + ret = OMX_ErrorNone; + } + goto EXIT; + } + + /* Get decoded data from Seiren */ + ADec_RecvPCM(fd, &output_mem_pool); + if (output_mem_pool.data_size > 0) { + pOutputData->dataLen = output_mem_pool.data_size; + Exynos_OSAL_Memcpy(pOutputData->buffer.addr[AUDIO_DATA_PLANE], + output_mem_pool.virt_addr, output_mem_pool.data_size); + } else { + pOutputData->dataLen = 0; + } + +#ifdef Seiren_DUMP_TO_FILE + if (pOutputData->dataLen > 0) + fwrite(pOutputData->buffer.addr[AUDIO_DATA_PLANE], pOutputData->dataLen, 1, outFile); +#endif + + /* Delay EOS signal until all the PCM is returned from the Seiren driver. */ + if (pAacDec->hSeirenAacHandle.bSeirenSendEOS == OMX_TRUE) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) { + returnCodec = ADec_GetParams(fd, ADEC_PARAM_GET_OUTPUT_STATUS, &isSeirenStopped); + if (returnCodec != 0) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Fail Seiren_STOP_EOS_STATE"); + if (isSeirenStopped == 1) { + pOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + pAacDec->hSeirenAacHandle.bSeirenSendEOS = OMX_FALSE; /* for repeating one song */ + ret = OMX_ErrorNone; + } else { + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + } + } else { /* Flush after EOS */ + pAacDec->hSeirenAacHandle.bSeirenSendEOS = OMX_FALSE; + } + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_AacDec_bufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData, EXYNOS_OMX_DATA *pOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || (!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pInputPort)) || (!CHECK_PORT_POPULATED(pOutputPort))) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent)) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + + goto EXIT; + } + + ret = Exynos_Seiren_Aac_Decode_Block(pOMXComponent, pInputData, pOutputData); + + if (ret != OMX_ErrorNone) { + if (ret == (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet) { + pOutputData->usedDataLen = 0; + pOutputData->remainDataLen = pOutputData->dataLen; + } else { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + pInputData->usedDataLen += pInputData->dataLen; + pInputData->remainDataLen = pInputData->dataLen - pInputData->usedDataLen; + pInputData->dataLen -= pInputData->usedDataLen; + pInputData->usedDataLen = 0; + + pOutputData->usedDataLen = 0; + pOutputData->remainDataLen = pOutputData->dataLen; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_AacDec_flushSeiren(OMX_COMPONENTTYPE *pOMXComponent, SEIREN_PORTTYPE type) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_AAC_HANDLE *pAacDec = (EXYNOS_AAC_HANDLE *)pAudioDec->hCodecHandle; + + int fd = pAacDec->hSeirenAacHandle.hSeirenHandle; + return ADec_Flush(fd, type); +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = NULL; + EXYNOS_AAC_HANDLE *pAacDec = NULL; + audio_mem_info_t input_mem_pool; + audio_mem_info_t output_mem_pool; + OMX_S32 fd; + + int i = 0; + + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: parameters are null, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_AAC_DEC, componentName) != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: componentName(%s) error, ret: %X", __FUNCTION__, componentName, ret); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_AudioDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_AudioDecodeComponentInit error, ret: %X", __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = HW_AUDIO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: componentName alloc error, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_1; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_AAC_DEC); + + pAacDec = Exynos_OSAL_Malloc(sizeof(EXYNOS_AAC_HANDLE)); + if (pAacDec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: EXYNOS_AAC_HANDLE alloc error, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_2; + } + Exynos_OSAL_Memset(pAacDec, 0, sizeof(EXYNOS_AAC_HANDLE)); + pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pAudioDec->hCodecHandle = (OMX_HANDLETYPE)pAacDec; + + /* Create and Init Seiren */ + pAacDec->hSeirenAacHandle.bSeirenLoaded = OMX_FALSE; + fd = ADec_Create(0, ADEC_AAC, NULL); + + if (fd < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_ADec_Create failed: %d", fd); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_3; + } + pAacDec->hSeirenAacHandle.hSeirenHandle = fd; /* Seiren's fd */ + pAacDec->hSeirenAacHandle.bSeirenLoaded = OMX_TRUE; + + /* Get input buffer info from Seiren */ + Exynos_OSAL_Memset(&pAacDec->hSeirenAacHandle.input_mem_pool, 0, sizeof(audio_mem_info_t)); + ADec_GetIMemPoolInfo(fd, &pAacDec->hSeirenAacHandle.input_mem_pool); + input_mem_pool = pAacDec->hSeirenAacHandle.input_mem_pool; + + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "eiren_Adec_GetIMemPoolInfo : %d", input_mem_pool.mem_size); + + if (input_mem_pool.virt_addr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_Adec_GetIMemPoolInfo failed: %d", fd); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_5; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->processData.allocSize = input_mem_pool.mem_size; + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = input_mem_pool.virt_addr; + + /* Get output buffer info from Seiren */ + Exynos_OSAL_Memset(&pAacDec->hSeirenAacHandle.output_mem_pool, 0, sizeof(audio_mem_info_t)); + ADec_GetOMemPoolInfo(fd, &pAacDec->hSeirenAacHandle.output_mem_pool); + output_mem_pool = pAacDec->hSeirenAacHandle.output_mem_pool; + if (output_mem_pool.virt_addr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_ADec_GetOMemPoolInfo failed: %d", fd); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_6; + } + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = input_mem_pool.block_count; + pExynosPort->portDefinition.nBufferCountMin = input_mem_pool.block_count; + pExynosPort->portDefinition.nBufferSize = input_mem_pool.mem_size; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.audio.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/aac"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingAAC; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = output_mem_pool.block_count; + pExynosPort->portDefinition.nBufferCountMin = output_mem_pool.block_count; + pExynosPort->portDefinition.nBufferSize = output_mem_pool.mem_size; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.audio.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/raw"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingPCM; + + /* Default values for Aac audio param */ + INIT_SET_SIZE_VERSION(&pAacDec->aacParam, OMX_AUDIO_PARAM_AACPROFILETYPE); + pAacDec->aacParam.nPortIndex = INPUT_PORT_INDEX; + pAacDec->aacParam.nChannels = DEFAULT_AUDIO_CHANNELS_NUM; + pAacDec->aacParam.nBitRate = 0; + pAacDec->aacParam.nSampleRate = DEFAULT_AUDIO_SAMPLING_FREQ; + pAacDec->aacParam.nAudioBandWidth = 0; + pAacDec->aacParam.eChannelMode = OMX_AUDIO_ChannelModeStereo; + pAacDec->aacParam.eAACProfile = OMX_AUDIO_AACObjectNull; + pAacDec->aacParam.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP2ADTS; + + /* Default values for PCM audio param */ + INIT_SET_SIZE_VERSION(&pAacDec->pcmParam, OMX_AUDIO_PARAM_PCMMODETYPE); + pAacDec->pcmParam.nPortIndex = OUTPUT_PORT_INDEX; + pAacDec->pcmParam.nChannels = DEFAULT_AUDIO_CHANNELS_NUM; + pAacDec->pcmParam.eNumData = OMX_NumericalDataSigned; + pAacDec->pcmParam.eEndian = OMX_EndianLittle; + pAacDec->pcmParam.bInterleaved = OMX_TRUE; + pAacDec->pcmParam.nBitPerSample = DEFAULT_AUDIO_BIT_PER_SAMPLE; + pAacDec->pcmParam.nSamplingRate = DEFAULT_AUDIO_SAMPLING_FREQ; + pAacDec->pcmParam.ePCMMode = OMX_AUDIO_PCMModeLinear; + pAacDec->pcmParam.eChannelMapping[0] = OMX_AUDIO_ChannelLF; + pAacDec->pcmParam.eChannelMapping[1] = OMX_AUDIO_ChannelRF; + + pOMXComponent->GetParameter = &Exynos_Seiren_AacDec_GetParameter; + pOMXComponent->SetParameter = &Exynos_Seiren_AacDec_SetParameter; + pOMXComponent->GetConfig = &Exynos_Seiren_AacDec_GetConfig; + pOMXComponent->SetConfig = &Exynos_Seiren_AacDec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_Seiren_AacDec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_Seiren_AacDec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + /* ToDo: Change the function name associated with a specific codec */ + pExynosComponent->exynos_codec_componentInit = &Exynos_Seiren_AacDec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_Seiren_AacDec_Terminate; + pAudioDec->exynos_codec_bufferProcess = &Exynos_Seiren_AacDec_bufferProcess; + pAudioDec->exynos_codec_flushSeiren = &Exynos_Seiren_AacDec_flushSeiren; + pAudioDec->exynos_checkInputFrame = NULL; + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + goto EXIT; /* This function is performed successfully. */ + +EXIT_ERROR_6: + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = NULL; + pExynosPort->processData.allocSize = 0; +EXIT_ERROR_5: +EXIT_ERROR_4: + ADec_Destroy(pAacDec->hSeirenAacHandle.hSeirenHandle); +EXIT_ERROR_3: + Exynos_OSAL_Free(pAacDec); + pAudioDec->hCodecHandle = NULL; +EXIT_ERROR_2: + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; +EXIT_ERROR_1: + Exynos_OMX_AudioDecodeComponentDeinit(pOMXComponent); +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_AAC_HANDLE *pAacDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_abnormalTermination(hComponent); + } + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pAacDec = (EXYNOS_AAC_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + if (pAacDec != NULL) { + if (pAacDec->hSeirenAacHandle.bSeirenLoaded == OMX_TRUE) { + ADec_Destroy(pAacDec->hSeirenAacHandle.hSeirenHandle); + } + Exynos_OSAL_Free(pAacDec); + ((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + } + + ret = Exynos_OMX_AudioDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.h b/openmax/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.h new file mode 100644 index 0000000..5e32a2a --- /dev/null +++ b/openmax/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.h @@ -0,0 +1,72 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Aacdec.h + * @brief + * @author Sungyeon Kim (sy85.kim@samsung.com) + * @version 1.0.0 + * @history + * 2012.12.22 : Create + */ + +#ifndef EXYNOS_OMX_AAC_DEC_COMPONENT +#define EXYNOS_OMX_AAC_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "seiren_hw.h" + +static const uint32_t aac_sample_rates[] = +{ + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000 +}; + +typedef struct _EXYNOS_Seiren_AAC_HANDLE +{ + OMX_U32 hSeirenHandle; + OMX_BOOL bConfiguredSeiren; + OMX_BOOL bSeirenLoaded; + OMX_BOOL bSeirenSendEOS; + OMX_S32 returnCodec; + audio_mem_info_t input_mem_pool; + audio_mem_info_t output_mem_pool; +} EXYNOS_Seiren_AAC_HANDLE; + +typedef struct _EXYNOS_AAC_HANDLE +{ + /* OMX Codec specific */ + OMX_AUDIO_PARAM_AACPROFILETYPE aacParam; + OMX_AUDIO_PARAM_PCMMODETYPE pcmParam; + + /* SEC Seiren Codec specific */ + EXYNOS_Seiren_AAC_HANDLE hSeirenAacHandle; +} EXYNOS_AAC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); + OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +#ifdef __cplusplus +}; +#endif + +#endif /* EXYNOS_OMX_AAC_DEC_COMPONENT */ diff --git a/openmax/component/audio/seiren_dec/aac/NOTICE b/openmax/component/audio/seiren_dec/aac/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/audio/seiren_dec/aac/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/audio/seiren_dec/aac/library_register.c b/openmax/component/audio/seiren_dec/aac/library_register.c new file mode 100644 index 0000000..cb7f3f5 --- /dev/null +++ b/openmax/component/audio/seiren_dec/aac/library_register.c @@ -0,0 +1,58 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_AAC_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - audio decoder AAC */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_AAC_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_AAC_DEC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + return MAX_COMPONENT_NUM; +} + diff --git a/openmax/component/audio/seiren_dec/aac/library_register.h b/openmax/component/audio/seiren_dec/aac/library_register.h new file mode 100644 index 0000000..75b0cc2 --- /dev/null +++ b/openmax/component/audio/seiren_dec/aac/library_register.h @@ -0,0 +1,54 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#ifndef EXYNOS_OMX_AAC_DEC_REG +#define EXYNOS_OMX_AAC_DEC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 1 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* AAC */ +#define EXYNOS_OMX_COMPONENT_AAC_DEC "OMX.Exynos.AAC.Decoder" +#define EXYNOS_OMX_COMPONENT_AAC_DEC_ROLE "audio_decoder.aac" + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif /* EXYNOS_OMX_AAC_DEC_REG */ + diff --git a/openmax/component/audio/seiren_dec/flac/Android.mk b/openmax/component/audio/seiren_dec/flac/Android.mk new file mode 100644 index 0000000..5083c4f --- /dev/null +++ b/openmax/component/audio/seiren_dec/flac/Android.mk @@ -0,0 +1,41 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Flacdec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.FLAC.Decoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Adec libExynosOMX_OSAL libExynosOMX_ABasecomponent \ + libseirenhw +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/audio/seiren_dec \ + $(EXYNOS_AUDIO_CODEC)/include + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.c b/openmax/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.c new file mode 100644 index 0000000..d51a97c --- /dev/null +++ b/openmax/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.c @@ -0,0 +1,946 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Flacdec.c + * @brief + * @author Sungyeon Kim (sy85.kim@samsung.com) + * @version 1.0.0 + * @history + * 2012.12.22 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_ABasecomponent.h" +#include "Exynos_OMX_ABaseport.h" +#include "Exynos_OMX_Adec.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Flacdec.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_FLAC_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +//#define Seiren_DUMP_TO_FILE +#ifdef Seiren_DUMP_TO_FILE +#include "stdio.h" + +FILE *inFile; +FILE *outFile; +#endif + +OMX_ERRORTYPE Exynos_Seiren_FlacDec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nParamIndex) { + case OMX_IndexParamAudioFlac: + { + OMX_AUDIO_PARAM_FLACTYPE *pDstFlacParam = (OMX_AUDIO_PARAM_FLACTYPE *)pComponentParameterStructure; + OMX_AUDIO_PARAM_FLACTYPE *pSrcFlacParam = NULL; + EXYNOS_FLAC_HANDLE *pFlacDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstFlacParam, sizeof(OMX_AUDIO_PARAM_FLACTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstFlacParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pFlacDec = (EXYNOS_FLAC_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pSrcFlacParam = &pFlacDec->flacParam; + + Exynos_OSAL_Memcpy(pDstFlacParam, pSrcFlacParam, sizeof(OMX_AUDIO_PARAM_FLACTYPE)); + } + break; + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pDstPcmParam = (OMX_AUDIO_PARAM_PCMMODETYPE *)pComponentParameterStructure; + OMX_AUDIO_PARAM_PCMMODETYPE *pSrcPcmParam = NULL; + EXYNOS_FLAC_HANDLE *pFlacDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstPcmParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pFlacDec = (EXYNOS_FLAC_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pSrcPcmParam = &pFlacDec->pcmParam; + + Exynos_OSAL_Memcpy(pDstPcmParam, pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_S32 codecType; + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_FLAC_DEC_ROLE); + } + break; + default: + ret = Exynos_OMX_AudioDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_FlacDec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + case OMX_IndexParamAudioFlac: + { + OMX_AUDIO_PARAM_FLACTYPE *pDstFlacParam = NULL; + OMX_AUDIO_PARAM_FLACTYPE *pSrcFlacParam = (OMX_AUDIO_PARAM_FLACTYPE *)pComponentParameterStructure; + EXYNOS_FLAC_HANDLE *pFlacDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcFlacParam, sizeof(OMX_AUDIO_PARAM_FLACTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcFlacParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pFlacDec = (EXYNOS_FLAC_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDstFlacParam = &pFlacDec->flacParam; + + Exynos_OSAL_Memcpy(pDstFlacParam, pSrcFlacParam, sizeof(OMX_AUDIO_PARAM_FLACTYPE)); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nSize : %d \e[0m", pDstFlacParam->nSize); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nPortIndex : %d \e[0m", pDstFlacParam->nPortIndex); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nChannels : %d \e[0m", pDstFlacParam->nChannels); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nSampleRate : %d \e[0m", pDstFlacParam->nSampleRate); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33;46m nCompressionLevel : %d \e[0m", pDstFlacParam->nCompressionLevel); + } + break; + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pDstPcmParam = NULL; + OMX_AUDIO_PARAM_PCMMODETYPE *pSrcPcmParam = (OMX_AUDIO_PARAM_PCMMODETYPE *)pComponentParameterStructure; + EXYNOS_FLAC_HANDLE *pFlacDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcPcmParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pFlacDec = (EXYNOS_FLAC_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDstPcmParam = &pFlacDec->pcmParam; + + Exynos_OSAL_Memcpy(pDstPcmParam, pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_FLAC_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingFLAC; + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + default: + ret = Exynos_OMX_AudioDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_FlacDec_GetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = Exynos_OMX_AudioDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_FlacDec_SetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = Exynos_OMX_AudioDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_FlacDec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if ((cParameterName == NULL) || (pIndexType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + ret = Exynos_OMX_AudioDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_FlacDec_ComponentRoleEnum( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_U8 *cRole, + OMX_IN OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 codecType; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex != (MAX_COMPONENT_ROLE_NUM - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_FLAC_DEC_ROLE); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_FlacDec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_FLAC_HANDLE *pFlacDec = (EXYNOS_FLAC_HANDLE *)pAudioDec->hCodecHandle; + + FunctionIn(); + + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pExynosComponent->bUseFlagEOF = OMX_TRUE; /* Flac extractor should parse into frame unit. */ + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pFlacDec->hSeirenFlacHandle.bConfiguredSeiren = OMX_FALSE; + pFlacDec->hSeirenFlacHandle.bSeirenSendEOS = OMX_FALSE; + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + +#ifdef Seiren_DUMP_TO_FILE + inFile = fopen("/data/InFile.flac", "w+"); + outFile = fopen("/data/OutFile.pcm", "w+"); +#endif + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_FlacDec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + FunctionIn(); + +#ifdef Seiren_DUMP_TO_FILE + fclose(inFile); + fclose(outFile); +#endif + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Flac_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData, EXYNOS_OMX_DATA *pOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_FLAC_HANDLE *pFlacDec = (EXYNOS_FLAC_HANDLE *)pAudioDec->hCodecHandle; + int returnCodec = 0; + unsigned long long isSeirenStopped = 0; + OMX_BOOL isSeirenIbufOverflow = OMX_FALSE; + unsigned char* pt; + + u32 fd = pFlacDec->hSeirenFlacHandle.hSeirenHandle; + audio_mem_info_t input_mem_pool = pFlacDec->hSeirenFlacHandle.input_mem_pool; + audio_mem_info_t output_mem_pool = pFlacDec->hSeirenFlacHandle.output_mem_pool; + unsigned long long sample_rate, channels; + int consumed_size = 0; + sample_rate = channels = 0; + + FunctionIn(); + +#ifdef Seiren_DUMP_TO_FILE + if (pExynosComponent->reInputData == OMX_FALSE) { + fwrite(pInputData->buffer.addr[AUDIO_DATA_PLANE], pInputData->dataLen, 1, inFile); + } +#endif + + /* Save timestamp and flags of input data */ + pOutputData->timeStamp = pInputData->timeStamp; + pOutputData->nFlags = pInputData->nFlags & (~OMX_BUFFERFLAG_EOS); + + /* Decoding flac frames by Seiren */ + if (pExynosComponent->getAllDelayBuffer == OMX_FALSE) { + input_mem_pool.data_size = pInputData->dataLen; + pt = (unsigned char*)input_mem_pool.virt_addr; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33m %02X %02X %02X %02X %02X %02X %lld \e[0m", *pt,*(pt+1),*(pt+2),*(pt+3),*(pt+4), *(pt+5), pInputData->timeStamp); + + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) { + ADec_SendEOS(fd); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "EOS!!"); + } + if (pInputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG) + ADec_ConfigSignal(fd); + + returnCodec = ADec_SendStream(fd, &input_mem_pool, &consumed_size); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "ProcessedSize : %d return : %d", consumed_size, returnCodec); + if (returnCodec >= 0) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) { + pFlacDec->hSeirenFlacHandle.bSeirenSendEOS = OMX_TRUE; + } + } else if (returnCodec < 0) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + if (pFlacDec->hSeirenFlacHandle.bConfiguredSeiren == OMX_FALSE) { + if ((pInputData->dataLen <= 0) && (pInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + pOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pFlacDec->hSeirenFlacHandle.bSeirenSendEOS = OMX_FALSE; + ret = OMX_ErrorNone; + goto EXIT; + } + + returnCodec = ADec_GetParams(fd, PCM_PARAM_SAMPLE_RATE, &sample_rate); + returnCodec = returnCodec | ADec_GetParams(fd, PCM_PARAM_NUM_OF_CH, &channels); + + if (returnCodec < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_ADec_GetParams failed: %d", returnCodec); + ret = OMX_ErrorHardware; + goto EXIT; + } + + if (!sample_rate || !channels) { + if (pFlacDec->hSeirenFlacHandle.bSeirenSendEOS == OMX_TRUE) { + pOutputData->dataLen = 0; + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + } else { + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + } + ret = OMX_ErrorNone; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "numChannels(%d), samplingRate(%d)", + channels, sample_rate); + + if (pFlacDec->pcmParam.nChannels != channels || + pFlacDec->pcmParam.nSamplingRate != sample_rate) { + /* Change channel count and sampling rate information */ + pFlacDec->pcmParam.nChannels = channels; + pFlacDec->pcmParam.nSamplingRate = sample_rate; + + /* Send Port Settings changed call back */ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + + pFlacDec->hSeirenFlacHandle.bConfiguredSeiren = OMX_TRUE; + + if (pFlacDec->hSeirenFlacHandle.bSeirenSendEOS == OMX_TRUE) { + pOutputData->dataLen = 0; + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + } else { + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + ret = OMX_ErrorNone; + } + goto EXIT; + } + + /* Get decoded data from Seiren */ + ADec_RecvPCM(fd, &output_mem_pool); + if (output_mem_pool.data_size > 0) { + pOutputData->dataLen = output_mem_pool.data_size; + Exynos_OSAL_Memcpy(pOutputData->buffer.addr[AUDIO_DATA_PLANE], + output_mem_pool.virt_addr, output_mem_pool.data_size); + } else { + pOutputData->dataLen = 0; + } + +#ifdef Seiren_DUMP_TO_FILE + if (pOutputData->dataLen > 0) + fwrite(pOutputData->buffer.addr[AUDIO_DATA_PLANE], pOutputData->dataLen, 1, outFile); +#endif + + /* Delay EOS signal until all the PCM is returned from the Seiren driver. */ + if (pFlacDec->hSeirenFlacHandle.bSeirenSendEOS == OMX_TRUE) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) { + returnCodec = ADec_GetParams(fd, ADEC_PARAM_GET_OUTPUT_STATUS, &isSeirenStopped); + if (returnCodec != 0) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Fail Seiren_STOP_EOS_STATE"); + if (isSeirenStopped == 1) { + pOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + pFlacDec->hSeirenFlacHandle.bSeirenSendEOS = OMX_FALSE; /* for repeating one song */ + ret = OMX_ErrorNone; + } else { + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + } + } else { /* Flush after EOS */ + pFlacDec->hSeirenFlacHandle.bSeirenSendEOS = OMX_FALSE; + } + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_FlacDec_bufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData, EXYNOS_OMX_DATA *pOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || (!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pInputPort)) || (!CHECK_PORT_POPULATED(pOutputPort))) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent)) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + + goto EXIT; + } + + ret = Exynos_Seiren_Flac_Decode_Block(pOMXComponent, pInputData, pOutputData); + + if (ret != OMX_ErrorNone) { + if (ret == (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet) { + pOutputData->usedDataLen = 0; + pOutputData->remainDataLen = pOutputData->dataLen; + } else { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + pInputData->usedDataLen += pInputData->dataLen; + pInputData->remainDataLen = pInputData->dataLen - pInputData->usedDataLen; + pInputData->dataLen -= pInputData->usedDataLen; + pInputData->usedDataLen = 0; + + pOutputData->usedDataLen = 0; + pOutputData->remainDataLen = pOutputData->dataLen; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_FlacDec_flushSeiren(OMX_COMPONENTTYPE *pOMXComponent, SEIREN_PORTTYPE type) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_FLAC_HANDLE *pFlacDec = (EXYNOS_FLAC_HANDLE *)pAudioDec->hCodecHandle; + + if (type == 1) + return 0; + int fd = pFlacDec->hSeirenFlacHandle.hSeirenHandle; + return ADec_Flush(fd, type); +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = NULL; + EXYNOS_FLAC_HANDLE *pFlacDec = NULL; + audio_mem_info_t input_mem_pool; + audio_mem_info_t output_mem_pool; + OMX_S32 fd; + + int i = 0; + + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: parameters are null, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_FLAC_DEC, componentName) != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: componentName(%s) error, ret: %X", __FUNCTION__, componentName, ret); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_AudioDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_AudioDecodeComponentInit error, ret: %X", __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = HW_AUDIO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: componentName alloc error, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_1; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_FLAC_DEC); + + pFlacDec = Exynos_OSAL_Malloc(sizeof(EXYNOS_FLAC_HANDLE)); + if (pFlacDec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: EXYNOS_FLAC_HANDLE alloc error, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_2; + } + Exynos_OSAL_Memset(pFlacDec, 0, sizeof(EXYNOS_FLAC_HANDLE)); + pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pAudioDec->hCodecHandle = (OMX_HANDLETYPE)pFlacDec; + + /* Create and Init Seiren */ + pFlacDec->hSeirenFlacHandle.bSeirenLoaded = OMX_FALSE; + fd = ADec_Create(0, ADEC_FLAC, NULL); + + if (fd < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_ADec_Create failed: %d", fd); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_3; + } + pFlacDec->hSeirenFlacHandle.hSeirenHandle = fd; /* Seiren's fd */ + pFlacDec->hSeirenFlacHandle.bSeirenLoaded = OMX_TRUE; + + /* Get input buffer info from Seiren */ + Exynos_OSAL_Memset(&pFlacDec->hSeirenFlacHandle.input_mem_pool, 0, sizeof(audio_mem_info_t)); + ADec_GetIMemPoolInfo(fd, &pFlacDec->hSeirenFlacHandle.input_mem_pool); + input_mem_pool = pFlacDec->hSeirenFlacHandle.input_mem_pool; + + if (input_mem_pool.virt_addr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_Adec_GetIMemPoolInfo failed: %d", fd); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_5; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->processData.allocSize = input_mem_pool.mem_size; + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = input_mem_pool.virt_addr; + + /* Get output buffer info from Seiren */ + Exynos_OSAL_Memset(&pFlacDec->hSeirenFlacHandle.output_mem_pool, 0, sizeof(audio_mem_info_t)); + ADec_GetOMemPoolInfo(fd, &pFlacDec->hSeirenFlacHandle.output_mem_pool); + output_mem_pool = pFlacDec->hSeirenFlacHandle.output_mem_pool; + if (output_mem_pool.virt_addr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_ADec_GetOMemPoolInfo failed: %d", fd); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_6; + } + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = input_mem_pool.block_count; + pExynosPort->portDefinition.nBufferCountMin = input_mem_pool.block_count; + pExynosPort->portDefinition.nBufferSize = input_mem_pool.mem_size; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.audio.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/flac"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingFLAC; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = output_mem_pool.block_count; + pExynosPort->portDefinition.nBufferCountMin = output_mem_pool.block_count; + pExynosPort->portDefinition.nBufferSize = output_mem_pool.mem_size; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.audio.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/raw"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingPCM; + + /* Default values for Flac audio param */ + INIT_SET_SIZE_VERSION(&pFlacDec->flacParam, OMX_AUDIO_PARAM_FLACTYPE); + pFlacDec->flacParam.nPortIndex = INPUT_PORT_INDEX; + pFlacDec->flacParam.nChannels = DEFAULT_AUDIO_CHANNELS_NUM; + pFlacDec->flacParam.nSampleRate = DEFAULT_AUDIO_SAMPLING_FREQ; + + /* Default values for PCM audio param */ + INIT_SET_SIZE_VERSION(&pFlacDec->pcmParam, OMX_AUDIO_PARAM_PCMMODETYPE); + pFlacDec->pcmParam.nPortIndex = OUTPUT_PORT_INDEX; + pFlacDec->pcmParam.nChannels = DEFAULT_AUDIO_CHANNELS_NUM; + pFlacDec->pcmParam.eNumData = OMX_NumericalDataSigned; + pFlacDec->pcmParam.eEndian = OMX_EndianLittle; + pFlacDec->pcmParam.bInterleaved = OMX_TRUE; + pFlacDec->pcmParam.nBitPerSample = DEFAULT_AUDIO_BIT_PER_SAMPLE; + pFlacDec->pcmParam.nSamplingRate = DEFAULT_AUDIO_SAMPLING_FREQ; + pFlacDec->pcmParam.ePCMMode = OMX_AUDIO_PCMModeLinear; + pFlacDec->pcmParam.eChannelMapping[0] = OMX_AUDIO_ChannelLF; + pFlacDec->pcmParam.eChannelMapping[1] = OMX_AUDIO_ChannelRF; + + pOMXComponent->GetParameter = &Exynos_Seiren_FlacDec_GetParameter; + pOMXComponent->SetParameter = &Exynos_Seiren_FlacDec_SetParameter; + pOMXComponent->GetConfig = &Exynos_Seiren_FlacDec_GetConfig; + pOMXComponent->SetConfig = &Exynos_Seiren_FlacDec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_Seiren_FlacDec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_Seiren_FlacDec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + /* ToDo: Change the function name associated with a specific codec */ + pExynosComponent->exynos_codec_componentInit = &Exynos_Seiren_FlacDec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_Seiren_FlacDec_Terminate; + pAudioDec->exynos_codec_bufferProcess = &Exynos_Seiren_FlacDec_bufferProcess; + pAudioDec->exynos_codec_flushSeiren = &Exynos_Seiren_FlacDec_flushSeiren; + pAudioDec->exynos_checkInputFrame = NULL; + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + goto EXIT; /* This function is performed successfully. */ + +EXIT_ERROR_6: + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = NULL; + pExynosPort->processData.allocSize = 0; +EXIT_ERROR_5: +EXIT_ERROR_4: + ADec_Destroy(pFlacDec->hSeirenFlacHandle.hSeirenHandle); +EXIT_ERROR_3: + Exynos_OSAL_Free(pFlacDec); + pAudioDec->hCodecHandle = NULL; +EXIT_ERROR_2: + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; +EXIT_ERROR_1: + Exynos_OMX_AudioDecodeComponentDeinit(pOMXComponent); +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_FLAC_HANDLE *pFlacDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_abnormalTermination(hComponent); + } + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pFlacDec = (EXYNOS_FLAC_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + if (pFlacDec != NULL) { + if (pFlacDec->hSeirenFlacHandle.bSeirenLoaded == OMX_TRUE) { + ADec_Destroy(pFlacDec->hSeirenFlacHandle.hSeirenHandle); + } + Exynos_OSAL_Free(pFlacDec); + ((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + } + + ret = Exynos_OMX_AudioDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.h b/openmax/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.h new file mode 100644 index 0000000..7f88847 --- /dev/null +++ b/openmax/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.h @@ -0,0 +1,77 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Flacdec.h + * @brief + * @author Sungyeon Kim (sy85.kim@samsung.com) + * @version 1.0.0 + * @history + * 2012.12.22 : Create + */ + +#ifndef EXYNOS_OMX_FLAC_DEC_COMPONENT +#define EXYNOS_OMX_FLAC_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "seiren_hw.h" + +static const uint32_t flac_sample_rates[] = +{ + 0, 88200, 176400, 192000, 8000, 16000, 22050, 24000, + 32000, 44100, 48000, 96000, 0, 0, 0, 0 +}; +static const uint32_t flac_channels[] = +{ + 1, 2, 3, 4, 5, 6, 7, 8, + 2, 2, 2, 0, 0, 0, 0, 0 +}; + +typedef struct _EXYNOS_Seiren_FLAC_HANDLE +{ + OMX_U32 hSeirenHandle; + OMX_BOOL bConfiguredSeiren; + OMX_BOOL bSeirenLoaded; + OMX_BOOL bSeirenSendEOS; + OMX_S32 returnCodec; + audio_mem_info_t input_mem_pool; + audio_mem_info_t output_mem_pool; +} EXYNOS_Seiren_FLAC_HANDLE; + +typedef struct _EXYNOS_FLAC_HANDLE +{ + /* OMX Codec specific */ + OMX_AUDIO_PARAM_FLACTYPE flacParam; + OMX_AUDIO_PARAM_PCMMODETYPE pcmParam; + + /* SEC Seiren Codec specific */ + EXYNOS_Seiren_FLAC_HANDLE hSeirenFlacHandle; +} EXYNOS_FLAC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); + OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +#ifdef __cplusplus +}; +#endif + +#endif /* EXYNOS_OMX_FLAC_DEC_COMPONENT */ diff --git a/openmax/component/audio/seiren_dec/flac/NOTICE b/openmax/component/audio/seiren_dec/flac/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/audio/seiren_dec/flac/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/audio/seiren_dec/flac/library_register.c b/openmax/component/audio/seiren_dec/flac/library_register.c new file mode 100644 index 0000000..e242810 --- /dev/null +++ b/openmax/component/audio/seiren_dec/flac/library_register.c @@ -0,0 +1,58 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_FLAC_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - audio decoder FLAC */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_FLAC_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_FLAC_DEC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + return MAX_COMPONENT_NUM; +} + diff --git a/openmax/component/audio/seiren_dec/flac/library_register.h b/openmax/component/audio/seiren_dec/flac/library_register.h new file mode 100644 index 0000000..f9d4e5b --- /dev/null +++ b/openmax/component/audio/seiren_dec/flac/library_register.h @@ -0,0 +1,54 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#ifndef EXYNOS_OMX_FLAC_DEC_REG +#define EXYNOS_OMX_FLAC_DEC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 1 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* FLAC */ +#define EXYNOS_OMX_COMPONENT_FLAC_DEC "OMX.Exynos.FLAC.Decoder" +#define EXYNOS_OMX_COMPONENT_FLAC_DEC_ROLE "audio_decoder.flac" + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif /* EXYNOS_OMX_FLAC_DEC_REG */ + diff --git a/openmax/component/audio/seiren_dec/mp3/Android.mk b/openmax/component/audio/seiren_dec/mp3/Android.mk new file mode 100644 index 0000000..ae82ac2 --- /dev/null +++ b/openmax/component/audio/seiren_dec/mp3/Android.mk @@ -0,0 +1,41 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Mp3dec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.MP3.Decoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Adec libExynosOMX_OSAL libExynosOMX_ABasecomponent \ + libseirenhw +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/audio/seiren_dec \ + $(EXYNOS_AUDIO_CODEC)/include + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.c b/openmax/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.c new file mode 100644 index 0000000..df82339 --- /dev/null +++ b/openmax/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.c @@ -0,0 +1,955 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Mp3dec.c + * @brief + * @author Sungyeon Kim (sy85.kim@samsung.com) + * @version 1.0.0 + * @history + * 2012.12.22 : Create + */ + +#include +#include +#include +/ +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_ABasecomponent.h" +#include "Exynos_OMX_ABaseport.h" +#include "Exynos_OMX_Adec.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Mp3dec.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_MP3_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +//#define Seiren_DUMP_TO_FILE +#ifdef Seiren_DUMP_TO_FILE +#include "stdio.h" + +FILE *inFile; +FILE *outFile; +#endif + +OMX_ERRORTYPE Exynos_Seiren_Mp3Dec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nParamIndex) { + case OMX_IndexParamAudioMp3: + { + OMX_AUDIO_PARAM_MP3TYPE *pDstMp3Param = (OMX_AUDIO_PARAM_MP3TYPE *)pComponentParameterStructure; + OMX_AUDIO_PARAM_MP3TYPE *pSrcMp3Param = NULL; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstMp3Param, sizeof(OMX_AUDIO_PARAM_MP3TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstMp3Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMp3Dec = (EXYNOS_MP3_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pSrcMp3Param = &pMp3Dec->mp3Param; + + Exynos_OSAL_Memcpy(pDstMp3Param, pSrcMp3Param, sizeof(OMX_AUDIO_PARAM_MP3TYPE)); + } + break; + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pDstPcmParam = (OMX_AUDIO_PARAM_PCMMODETYPE *)pComponentParameterStructure; + OMX_AUDIO_PARAM_PCMMODETYPE *pSrcPcmParam = NULL; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstPcmParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMp3Dec = (EXYNOS_MP3_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pSrcPcmParam = &pMp3Dec->pcmParam; + + Exynos_OSAL_Memcpy(pDstPcmParam, pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_S32 codecType; + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_MP3_DEC_ROLE); + } + break; + default: + ret = Exynos_OMX_AudioDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Mp3Dec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + case OMX_IndexParamAudioMp3: + { + OMX_AUDIO_PARAM_MP3TYPE *pDstMp3Param = NULL; + OMX_AUDIO_PARAM_MP3TYPE *pSrcMp3Param = (OMX_AUDIO_PARAM_MP3TYPE *)pComponentParameterStructure; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcMp3Param, sizeof(OMX_AUDIO_PARAM_MP3TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcMp3Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMp3Dec = (EXYNOS_MP3_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDstMp3Param = &pMp3Dec->mp3Param; + + Exynos_OSAL_Memcpy(pDstMp3Param, pSrcMp3Param, sizeof(OMX_AUDIO_PARAM_MP3TYPE)); + } + break; + case OMX_IndexParamAudioPcm: + { + OMX_AUDIO_PARAM_PCMMODETYPE *pDstPcmParam = NULL; + OMX_AUDIO_PARAM_PCMMODETYPE *pSrcPcmParam = (OMX_AUDIO_PARAM_PCMMODETYPE *)pComponentParameterStructure; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcPcmParam->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMp3Dec = (EXYNOS_MP3_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDstPcmParam = &pMp3Dec->pcmParam; + + Exynos_OSAL_Memcpy(pDstPcmParam, pSrcPcmParam, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strncmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_MP3_DEC_ROLE, 16)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingMP3; + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + default: + ret = Exynos_OMX_AudioDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Mp3Dec_GetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = Exynos_OMX_AudioDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Mp3Dec_SetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentConfigStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nIndex) { + default: + ret = Exynos_OMX_AudioDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Mp3Dec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if ((cParameterName == NULL) || (pIndexType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + ret = Exynos_OMX_AudioDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Mp3Dec_ComponentRoleEnum( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_U8 *cRole, + OMX_IN OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 codecType; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex != (MAX_COMPONENT_ROLE_NUM - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_MP3_DEC_ROLE); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Mp3Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MP3_HANDLE *pMp3Dec = (EXYNOS_MP3_HANDLE *)pAudioDec->hCodecHandle; + + FunctionIn(); + + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pExynosComponent->bUseFlagEOF = OMX_TRUE; /* Mp3 extractor should parse into frame unit. */ + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pMp3Dec->hSeirenMp3Handle.bConfiguredSeiren = OMX_FALSE; + pMp3Dec->hSeirenMp3Handle.bSeirenSendEOS = OMX_FALSE; + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + +#ifdef Seiren_DUMP_TO_FILE + inFile = fopen("/data/InFile.mp3", "w+"); + outFile = fopen("/data/OutFile.pcm", "w+"); +#endif + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Mp3Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + FunctionIn(); + +#ifdef Seiren_DUMP_TO_FILE + fclose(inFile); + fclose(outFile); +#endif + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Mp3_Decode_Block(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData, EXYNOS_OMX_DATA *pOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MP3_HANDLE *pMp3Dec = (EXYNOS_MP3_HANDLE *)pAudioDec->hCodecHandle; + int returnCodec = 0; + unsigned long long isSeirenStopped = 0; + OMX_BOOL isSeirenIbufOverflow = OMX_FALSE; + + u32 fd = pMp3Dec->hSeirenMp3Handle.hSeirenHandle; + audio_mem_info_t input_mem_pool = pMp3Dec->hSeirenMp3Handle.input_mem_pool; + audio_mem_info_t output_mem_pool = pMp3Dec->hSeirenMp3Handle.output_mem_pool; + unsigned long long sample_rate, channels; + int consumed_size = 0; + unsigned char* pt = NULL; + sample_rate = channels = 0; + + FunctionIn(); + +#ifdef Seiren_DUMP_TO_FILE + if (pExynosComponent->reInputData == OMX_FALSE) { + fwrite(pInputData->buffer.addr[AUDIO_DATA_PLANE], pInputData->dataLen, 1, inFile); + } +#endif + + /* Save timestamp and flags of input data */ + pOutputData->timeStamp = pInputData->timeStamp; + pOutputData->nFlags = pInputData->nFlags & (~OMX_BUFFERFLAG_EOS); + + /* Decoding mp3 frames by Seiren */ + if (pExynosComponent->getAllDelayBuffer == OMX_FALSE) { + input_mem_pool.data_size = pInputData->dataLen; + pt = (unsigned char*)input_mem_pool.virt_addr; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "\e[1;33m %02X %02X %02X %02X %02X %02X %lld \e[0m", *pt,*(pt+1),*(pt+2),*(pt+3),*(pt+4), *(pt+5), pInputData->timeStamp); + returnCodec = ADec_SendStream(fd, &input_mem_pool, &consumed_size); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "ProcessedSize : %d return : %d", consumed_size, returnCodec); + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "EOS!!"); + if (returnCodec >= 0) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) { + ADec_SendEOS(fd); + pMp3Dec->hSeirenMp3Handle.bSeirenSendEOS = OMX_TRUE; + } + } else if (returnCodec < 0) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + if (pMp3Dec->hSeirenMp3Handle.bConfiguredSeiren == OMX_FALSE) { + if ((pInputData->dataLen <= 0) && (pInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + pOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pMp3Dec->hSeirenMp3Handle.bSeirenSendEOS = OMX_FALSE; + ret = OMX_ErrorNone; + goto EXIT; + } + + returnCodec = ADec_GetParams(fd, PCM_PARAM_SAMPLE_RATE, &sample_rate); + returnCodec = returnCodec | ADec_GetParams(fd, PCM_PARAM_NUM_OF_CH, &channels); + + if (returnCodec < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_ADec_GetParams failed: %d", returnCodec); + ret = OMX_ErrorHardware; + goto EXIT; + } + + if (!sample_rate || !channels) { + if (pMp3Dec->hSeirenMp3Handle.bSeirenSendEOS == OMX_TRUE) { + pOutputData->dataLen = 0; + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + } else { + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + } + ret = OMX_ErrorNone; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "numChannels(%d), samplingRate(%d)", + channels, sample_rate); + + if (pMp3Dec->pcmParam.nChannels != channels || + pMp3Dec->pcmParam.nSamplingRate != sample_rate) { + /* Change channel count and sampling rate information */ + pMp3Dec->pcmParam.nChannels = channels; + pMp3Dec->pcmParam.nSamplingRate = sample_rate; + + /* Send Port Settings changed call back */ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + + pMp3Dec->hSeirenMp3Handle.bConfiguredSeiren = OMX_TRUE; + + if (pMp3Dec->hSeirenMp3Handle.bSeirenSendEOS == OMX_TRUE) { + pOutputData->dataLen = 0; + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + } else { + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + ret = OMX_ErrorNone; + } + goto EXIT; + } + + /* Get decoded data from Seiren */ + ADec_RecvPCM(fd, &output_mem_pool); + + pt = (unsigned char*)output_mem_pool.virt_addr; + /* Trim first samples for MP3 gapless CTS test */ + if (pAudioDec->bFirstFrame) { + pAudioDec->bFirstFrame = OMX_FALSE; + /* Need to check Gapless playback or not */ + const int gapless_frames = 529; + const int gapless_bytes = gapless_frames * pMp3Dec->pcmParam.nChannels * sizeof(OMX_S16); + if (output_mem_pool.data_size >= gapless_bytes) { + pt += gapless_bytes; + output_mem_pool.data_size -= gapless_bytes; + } + } + + if (output_mem_pool.data_size > 0) { + pOutputData->dataLen = output_mem_pool.data_size; + Exynos_OSAL_Memcpy(pOutputData->buffer.addr[AUDIO_DATA_PLANE], + pt, output_mem_pool.data_size); + } else { + pOutputData->dataLen = 0; + } + +#ifdef Seiren_DUMP_TO_FILE + if (pOutputData->dataLen > 0) + fwrite(pOutputData->buffer.addr[AUDIO_DATA_PLANE], pOutputData->dataLen, 1, outFile); +#endif + + /* Delay EOS signal until all the PCM is returned from the Seiren driver. */ + if (pMp3Dec->hSeirenMp3Handle.bSeirenSendEOS == OMX_TRUE) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) { + returnCodec = ADec_GetParams(fd, ADEC_PARAM_GET_OUTPUT_STATUS, &isSeirenStopped); + if (returnCodec != 0) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Fail Seiren_STOP_EOS_STATE"); + if (isSeirenStopped == 1) { + pOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + pMp3Dec->hSeirenMp3Handle.bSeirenSendEOS = OMX_FALSE; /* for repeating one song */ + ret = OMX_ErrorNone; + } else { + pExynosComponent->getAllDelayBuffer = OMX_TRUE; + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + } + } else { /* Flush after EOS */ + pMp3Dec->hSeirenMp3Handle.bSeirenSendEOS = OMX_FALSE; + } + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Mp3Dec_bufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData, EXYNOS_OMX_DATA *pOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || (!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pInputPort)) || (!CHECK_PORT_POPULATED(pOutputPort))) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent)) { + if (pInputData->nFlags & OMX_BUFFERFLAG_EOS) + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + else + ret = OMX_ErrorNone; + + goto EXIT; + } + + ret = Exynos_Seiren_Mp3_Decode_Block(pOMXComponent, pInputData, pOutputData); + + if (ret != OMX_ErrorNone) { + if (ret == (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet) { + pOutputData->usedDataLen = 0; + pOutputData->remainDataLen = pOutputData->dataLen; + } else { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + pInputData->usedDataLen += pInputData->dataLen; + pInputData->remainDataLen = pInputData->dataLen - pInputData->usedDataLen; + pInputData->dataLen -= pInputData->usedDataLen; + pInputData->usedDataLen = 0; + + pOutputData->usedDataLen = 0; + pOutputData->remainDataLen = pOutputData->dataLen; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Seiren_Mp3Dec_flushSeiren(OMX_COMPONENTTYPE *pOMXComponent, SEIREN_PORTTYPE type) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MP3_HANDLE *pMp3Dec = (EXYNOS_MP3_HANDLE *)pAudioDec->hCodecHandle; + + int fd = pMp3Dec->hSeirenMp3Handle.hSeirenHandle; + return ADec_Flush(fd, type); +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_AUDIODEC_COMPONENT *pAudioDec = NULL; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + audio_mem_info_t input_mem_pool; + audio_mem_info_t output_mem_pool; + OMX_S32 fd; + OMX_S32 codec_type = CODEC_TYPE_MAX; + + int i = 0; + + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: parameters are null, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MP3_DEC, componentName) == 0) { + codec_type = CODEC_TYPE_MP3; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MP1_DEC, componentName) == 0) { + codec_type = CODEC_TYPE_MP1; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MP2_DEC, componentName) == 0) { + codec_type = CODEC_TYPE_MP2; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: componentName(%s) error, ret: %X", __FUNCTION__, componentName, ret); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_AudioDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_AudioDecodeComponentInit error, ret: %X", __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = HW_AUDIO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: componentName alloc error, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_1; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_MP3_DEC); + + pMp3Dec = Exynos_OSAL_Malloc(sizeof(EXYNOS_MP3_HANDLE)); + if (pMp3Dec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: EXYNOS_MP3_HANDLE alloc error, ret: %X", __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto EXIT_ERROR_2; + } + Exynos_OSAL_Memset(pMp3Dec, 0, sizeof(EXYNOS_MP3_HANDLE)); + pAudioDec = (EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pAudioDec->hCodecHandle = (OMX_HANDLETYPE)pMp3Dec; + pAudioDec->bFirstFrame = OMX_TRUE; + + /* Create and Init Seiren */ + pMp3Dec->hSeirenMp3Handle.bSeirenLoaded = OMX_FALSE; + fd = ADec_Create(0, ADEC_MP3, NULL); + + if (fd < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_ADec_Create failed: %d", fd); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_3; + } + pMp3Dec->hSeirenMp3Handle.hSeirenHandle = fd; /* Seiren's fd */ + pMp3Dec->hSeirenMp3Handle.bSeirenLoaded = OMX_TRUE; + + /* Get input buffer info from Seiren */ + Exynos_OSAL_Memset(&pMp3Dec->hSeirenMp3Handle.input_mem_pool, 0, sizeof(audio_mem_info_t)); + ADec_GetIMemPoolInfo(fd, &pMp3Dec->hSeirenMp3Handle.input_mem_pool); + input_mem_pool = pMp3Dec->hSeirenMp3Handle.input_mem_pool; + + if (input_mem_pool.virt_addr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_Adec_GetIMemPoolInfo failed: %d", fd); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_5; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->processData.allocSize = input_mem_pool.mem_size; + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = input_mem_pool.virt_addr; + + /* Get output buffer info from Seiren */ + Exynos_OSAL_Memset(&pMp3Dec->hSeirenMp3Handle.output_mem_pool, 0, sizeof(audio_mem_info_t)); + ADec_GetOMemPoolInfo(fd, &pMp3Dec->hSeirenMp3Handle.output_mem_pool); + output_mem_pool = pMp3Dec->hSeirenMp3Handle.output_mem_pool; + if (output_mem_pool.virt_addr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Seiren_ADec_GetOMemPoolInfo failed: %d", fd); + ret = OMX_ErrorHardware; + goto EXIT_ERROR_6; + } + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = input_mem_pool.block_count; + pExynosPort->portDefinition.nBufferCountMin = input_mem_pool.block_count; + pExynosPort->portDefinition.nBufferSize = input_mem_pool.mem_size; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.audio.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + if (codec_type == CODEC_TYPE_MP3) + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/mpeg"); + else if (codec_type == CODEC_TYPE_MP1) + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/mpeg-L1"); + else + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/mpeg-L2"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingMP3; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.nBufferCountActual = output_mem_pool.block_count; + pExynosPort->portDefinition.nBufferCountMin = output_mem_pool.block_count; + pExynosPort->portDefinition.nBufferSize = output_mem_pool.mem_size; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.audio.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.audio.cMIMEType, "audio/raw"); + pExynosPort->portDefinition.format.audio.pNativeRender = 0; + pExynosPort->portDefinition.format.audio.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.audio.eEncoding = OMX_AUDIO_CodingPCM; + + /* Default values for Mp3 audio param */ + INIT_SET_SIZE_VERSION(&pMp3Dec->mp3Param, OMX_AUDIO_PARAM_MP3TYPE); + pMp3Dec->mp3Param.nPortIndex = INPUT_PORT_INDEX; + pMp3Dec->mp3Param.nChannels = DEFAULT_AUDIO_CHANNELS_NUM; + pMp3Dec->mp3Param.nBitRate = 0; + pMp3Dec->mp3Param.nSampleRate = DEFAULT_AUDIO_SAMPLING_FREQ; + pMp3Dec->mp3Param.nAudioBandWidth = 0; + pMp3Dec->mp3Param.eChannelMode = OMX_AUDIO_ChannelModeStereo; + pMp3Dec->mp3Param.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3; + + /* Default values for PCM audio param */ + INIT_SET_SIZE_VERSION(&pMp3Dec->pcmParam, OMX_AUDIO_PARAM_PCMMODETYPE); + pMp3Dec->pcmParam.nPortIndex = OUTPUT_PORT_INDEX; + pMp3Dec->pcmParam.nChannels = DEFAULT_AUDIO_CHANNELS_NUM; + pMp3Dec->pcmParam.eNumData = OMX_NumericalDataSigned; + pMp3Dec->pcmParam.eEndian = OMX_EndianLittle; + pMp3Dec->pcmParam.bInterleaved = OMX_TRUE; + pMp3Dec->pcmParam.nBitPerSample = DEFAULT_AUDIO_BIT_PER_SAMPLE; + pMp3Dec->pcmParam.nSamplingRate = DEFAULT_AUDIO_SAMPLING_FREQ; + pMp3Dec->pcmParam.ePCMMode = OMX_AUDIO_PCMModeLinear; + pMp3Dec->pcmParam.eChannelMapping[0] = OMX_AUDIO_ChannelLF; + pMp3Dec->pcmParam.eChannelMapping[1] = OMX_AUDIO_ChannelRF; + + pOMXComponent->GetParameter = &Exynos_Seiren_Mp3Dec_GetParameter; + pOMXComponent->SetParameter = &Exynos_Seiren_Mp3Dec_SetParameter; + pOMXComponent->GetConfig = &Exynos_Seiren_Mp3Dec_GetConfig; + pOMXComponent->SetConfig = &Exynos_Seiren_Mp3Dec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_Seiren_Mp3Dec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_Seiren_Mp3Dec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + /* ToDo: Change the function name associated with a specific codec */ + pExynosComponent->exynos_codec_componentInit = &Exynos_Seiren_Mp3Dec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_Seiren_Mp3Dec_Terminate; + pAudioDec->exynos_codec_bufferProcess = &Exynos_Seiren_Mp3Dec_bufferProcess; + pAudioDec->exynos_codec_flushSeiren = &Exynos_Seiren_Mp3Dec_flushSeiren; + pAudioDec->exynos_checkInputFrame = NULL; + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + goto EXIT; /* This function is performed successfully. */ + +EXIT_ERROR_6: + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->processData.buffer.addr[AUDIO_DATA_PLANE] = NULL; + pExynosPort->processData.allocSize = 0; +EXIT_ERROR_5: +EXIT_ERROR_4: + ADec_Destroy(pMp3Dec->hSeirenMp3Handle.hSeirenHandle); +EXIT_ERROR_3: + Exynos_OSAL_Free(pMp3Dec); + pAudioDec->hCodecHandle = NULL; +EXIT_ERROR_2: + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; +EXIT_ERROR_1: + Exynos_OMX_AudioDecodeComponentDeinit(pOMXComponent); +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_MP3_HANDLE *pMp3Dec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pMp3Dec = (EXYNOS_MP3_HANDLE *)((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + if (pMp3Dec != NULL) { + if (pMp3Dec->hSeirenMp3Handle.bSeirenLoaded == OMX_TRUE) { + ADec_Destroy(pMp3Dec->hSeirenMp3Handle.hSeirenHandle); + } + Exynos_OSAL_Free(pMp3Dec); + ((EXYNOS_OMX_AUDIODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + } + + ret = Exynos_OMX_AudioDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.h b/openmax/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.h new file mode 100644 index 0000000..84f7e10 --- /dev/null +++ b/openmax/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.h @@ -0,0 +1,74 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Mp3dec.h + * @brief + * @author Sungyeon Kim (sy85.kim@samsung.com) + * @version 1.0.0 + * @history + * 2012.12.22 : Create + */ + +#ifndef EXYNOS_OMX_MP3_DEC_COMPONENT +#define EXYNOS_OMX_MP3_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "seiren_hw.h" + +typedef enum _CODEC_TYPE +{ + CODEC_TYPE_MP1, + CODEC_TYPE_MP2, + CODEC_TYPE_MP3, + CODEC_TYPE_MAX +} CODEC_TYPE; + +typedef struct _EXYNOS_Seiren_MP3_HANDLE +{ + OMX_U32 hSeirenHandle; + OMX_BOOL bConfiguredSeiren; + OMX_BOOL bSeirenLoaded; + OMX_BOOL bSeirenSendEOS; + OMX_S32 returnCodec; + audio_mem_info_t input_mem_pool; + audio_mem_info_t output_mem_pool; +} EXYNOS_Seiren_MP3_HANDLE; + +typedef struct _EXYNOS_MP3_HANDLE +{ + /* OMX Codec specific */ + OMX_AUDIO_PARAM_MP3TYPE mp3Param; + OMX_AUDIO_PARAM_PCMMODETYPE pcmParam; + + /* SEC Seiren Codec specific */ + EXYNOS_Seiren_MP3_HANDLE hSeirenMp3Handle; +} EXYNOS_MP3_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); + OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +#ifdef __cplusplus +}; +#endif + +#endif /* EXYNOS_OMX_MP3_DEC_COMPONENT */ diff --git a/openmax/component/audio/seiren_dec/mp3/NOTICE b/openmax/component/audio/seiren_dec/mp3/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/audio/seiren_dec/mp3/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/audio/seiren_dec/mp3/library_register.c b/openmax/component/audio/seiren_dec/mp3/library_register.c new file mode 100644 index 0000000..fe44c0b --- /dev/null +++ b/openmax/component/audio/seiren_dec/mp3/library_register.c @@ -0,0 +1,67 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_MP3_DEC" +#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - audio decoder MP3 */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_MP3_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_MP3_DEC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 2 - audio decoder MP3 Layer 1 */ + Exynos_OSAL_Strcpy(ppExynosComponent[1]->componentName, EXYNOS_OMX_COMPONENT_MP1_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[1]->roles[0], EXYNOS_OMX_COMPONENT_MP1_DEC_ROLE); + ppExynosComponent[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 3 - audio decoder MP3 Layer 2 */ + Exynos_OSAL_Strcpy(ppExynosComponent[2]->componentName, EXYNOS_OMX_COMPONENT_MP2_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[2]->roles[0], EXYNOS_OMX_COMPONENT_MP2_DEC_ROLE); + ppExynosComponent[2]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; +EXIT: + FunctionOut(); + return MAX_COMPONENT_NUM; +} + diff --git a/openmax/component/audio/seiren_dec/mp3/library_register.h b/openmax/component/audio/seiren_dec/mp3/library_register.h new file mode 100644 index 0000000..a750690 --- /dev/null +++ b/openmax/component/audio/seiren_dec/mp3/library_register.h @@ -0,0 +1,60 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 1.1.0 + * @history + * 2012.02.28 : Create + */ + +#ifndef EXYNOS_OMX_MP3_DEC_REG +#define EXYNOS_OMX_MP3_DEC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 3 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* MP3 */ +#define EXYNOS_OMX_COMPONENT_MP3_DEC "OMX.Exynos.MP3.Decoder" +#define EXYNOS_OMX_COMPONENT_MP3_DEC_ROLE "audio_decoder.mp3" + +#define EXYNOS_OMX_COMPONENT_MP1_DEC "OMX.Exynos.MP1.Decoder" +#define EXYNOS_OMX_COMPONENT_MP1_DEC_ROLE "audio_decoder.mp1" + +#define EXYNOS_OMX_COMPONENT_MP2_DEC "OMX.Exynos.MP2.Decoder" +#define EXYNOS_OMX_COMPONENT_MP2_DEC_ROLE "audio_decoder.mp2" + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif /* EXYNOS_OMX_MP3_DEC_REG */ + diff --git a/openmax/component/common/Android.mk b/openmax/component/common/Android.mk new file mode 100644 index 0000000..ecb7d72 --- /dev/null +++ b/openmax/component/common/Android.mk @@ -0,0 +1,97 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Basecomponent.c \ + Exynos_OMX_Baseport.c + +LOCAL_MODULE := libExynosOMX_Basecomponent +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +LOCAL_STATIC_LIBRARIES := libExynosOMX_OSAL +LOCAL_SHARED_LIBRARIES := libcutils libutils + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_VIDEO_CODEC)/include + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(EXYNOS_OMX_SUPPORT_EGL_IMAGE), true) +LOCAL_CFLAGS += -DEGL_IMAGE_SUPPORT +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label -Wno-unused-function + +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Resourcemanager.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libExynosOMX_Resourcemanager +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +LOCAL_STATIC_LIBRARIES := libExynosOMX_OSAL +LOCAL_SHARED_LIBRARIES := libcutils libutils liblog + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(EXYNOS_OMX_SUPPORT_TUNNELING), true) +LOCAL_CFLAGS += -DTUNNELING_SUPPORT +endif + +ifneq ($(BOARD_NOT_SUPPORT_DCPP), true) +LOCAL_CFLAGS += -DUSE_SECURE_WITH_NONSECURE +endif + +ifeq ($(BOARD_USE_SINGLE_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +ifdef BOARD_USE_MAX_COMPONENT_NUM +LOCAL_CFLAGS += -DMAX_COMPONENT_NUM=$(BOARD_USE_MAX_COMPONENT_NUM) +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label -Wno-unused-function + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/common/Exynos_OMX_Basecomponent.c b/openmax/component/common/Exynos_OMX_Basecomponent.c new file mode 100644 index 0000000..839f387 --- /dev/null +++ b/openmax/component/common/Exynos_OMX_Basecomponent.c @@ -0,0 +1,2557 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Basecomponent.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.5.0 + * @history + * 2012.02.20 : Create + * 2017.08.03 : Change event handling + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Event.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Resourcemanager.h" +#include "Exynos_OMX_Macros.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_BASE_COMP" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +static OMX_ERRORTYPE Exynos_CheckStateSet(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam); +static OMX_ERRORTYPE Exynos_CheckPortFlush(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam); +static OMX_ERRORTYPE Exynos_CheckPortDisable(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam); +static OMX_ERRORTYPE Exynos_CheckPortEnable(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam); +static OMX_ERRORTYPE Exynos_CheckMarkBuffer(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam); +static OMX_ERRORTYPE Exynos_OMX_CommandQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_COMMANDTYPE Cmd, OMX_U32 nParam, OMX_PTR pCmdData); + +/* Change CHECK_SIZE_VERSION Macro */ +OMX_ERRORTYPE Exynos_OMX_Check_SizeVersion(OMX_PTR header, OMX_U32 size) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_VERSIONTYPE *version = NULL; + + if (header == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + version = (OMX_VERSIONTYPE*)((char*)header + sizeof(OMX_U32)); + if (*((OMX_U32*)header) != size) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_FUNC_TRACE, "[%s] nVersionMajor:%d, nVersionMinor:%d", __FUNCTION__, version->s.nVersionMajor, version->s.nVersionMinor); + + if ((version->s.nVersionMajor != VERSIONMAJOR_NUMBER) || + (version->s.nVersionMinor > VERSIONMINOR_NUMBER)) { + ret = OMX_ErrorVersionMismatch; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + return ret; +} + + +/* OMX Interface */ +OMX_ERRORTYPE Exynos_OMX_GetComponentVersion( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STRING pComponentName, + OMX_OUT OMX_VERSIONTYPE *pComponentVersion, + OMX_OUT OMX_VERSIONTYPE *pSpecVersion, + OMX_OUT OMX_UUIDTYPE *pComponentUUID) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + unsigned long compUUID[3]; + + FunctionIn(); + + /* check parameters */ + if (hComponent == NULL || + pComponentName == NULL || pComponentVersion == NULL || + pSpecVersion == NULL || pComponentUUID == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Strcpy(pComponentName, pExynosComponent->componentName); + Exynos_OSAL_Memcpy(pComponentVersion, &(pExynosComponent->componentVersion), sizeof(OMX_VERSIONTYPE)); + Exynos_OSAL_Memcpy(pSpecVersion, &(pExynosComponent->specVersion), sizeof(OMX_VERSIONTYPE)); + + /* Fill UUID with handle address, PID and UID. + * This should guarantee uiniqness */ + compUUID[0] = (unsigned long)pOMXComponent; + compUUID[1] = (unsigned long)getpid(); + compUUID[2] = (unsigned long)getuid(); + Exynos_OSAL_Memcpy(*pComponentUUID, compUUID, 3 * sizeof(*compUUID)); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SendCommand( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_COMMANDTYPE Cmd, + OMX_IN OMX_U32 nParam, + OMX_IN OMX_PTR pCmdData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (Cmd) { + case OMX_CommandStateSet : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_CommandStateSet(%s)", + pExynosComponent, __FUNCTION__, stateString(nParam)); + ret = Exynos_CheckStateSet(pExynosComponent, nParam); + break; + case OMX_CommandFlush : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_CommandFlush(port:0x%x)", + pExynosComponent, __FUNCTION__, nParam); + ret = Exynos_CheckPortFlush(pExynosComponent, nParam); + break; + case OMX_CommandPortDisable : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_CommandPortDisable(port:0x%x)", + pExynosComponent, __FUNCTION__, nParam); + ret = Exynos_CheckPortDisable(pExynosComponent, nParam); + break; + case OMX_CommandPortEnable : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_CommandPortEnable(port:0x%x)", + pExynosComponent, __FUNCTION__, nParam); + ret = Exynos_CheckPortEnable(pExynosComponent, nParam); + break; + case OMX_CommandMarkBuffer : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_CommandMarkBuffer(0x%x)", + pExynosComponent, __FUNCTION__, nParam); + + ret = Exynos_CheckMarkBuffer(pExynosComponent, nParam); + break; + default: + ret = OMX_ErrorBadParameter; + break; + } + + if (ret == OMX_ErrorNone) { + ret = Exynos_OMX_CommandQueue(pExynosComponent, Cmd, nParam, pCmdData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Exynos_OMX_CommandQueue()", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + /* wait for msg handler's ack except for MarkBuffer */ + if (Cmd != OMX_CommandMarkBuffer) + Exynos_OSAL_SemaphoreWait(pExynosComponent->hSemaMsgProgress); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetState( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STATETYPE *pState) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pState == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + *pState = pExynosComponent->currentState; + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SetCallbacks( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_CALLBACKTYPE* pCallbacks, + OMX_IN OMX_PTR pAppData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pCallbacks == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->currentState != OMX_StateLoaded) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosComponent->pCallbacks = pCallbacks; + pExynosComponent->callbackData = pAppData; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +#ifdef EGL_IMAGE_SUPPORT +OMX_ERRORTYPE Exynos_OMX_UseEGLImage( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN void *eglImage) +{ + return OMX_ErrorNotImplemented; +} +#endif + +static OMX_ERRORTYPE Exynos_CheckStateSet( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorUndefined; + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if (pExynosComponent->currentState == (OMX_STATETYPE)nParam) { + ret = OMX_ErrorSameState; + goto EXIT; + } + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch ((OMX_STATETYPE)nParam) { + case OMX_StateInvalid: + { + ret = OMX_ErrorNone; + } + break; + case OMX_StateLoaded: + { + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateTransition; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_StateWaitForResources: + { + if (pExynosComponent->currentState != OMX_StateLoaded) { + ret = OMX_ErrorIncorrectStateTransition; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_StateIdle: + { + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorIncorrectStateTransition; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_StateExecuting: + { + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StatePause)) { + ret = OMX_ErrorIncorrectStateTransition; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_StatePause: + { + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StateExecuting)) { + ret = OMX_ErrorIncorrectStateTransition; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + break; + default: + ret = OMX_ErrorBadParameter; + break; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE Exynos_CheckPortFlush( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorUndefined; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 nPortIndex = nParam; + + OMX_U32 i = 0; + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((nPortIndex != (OMX_U32)ALL_PORT_INDEX) && + (nPortIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + if ((nPortIndex != (OMX_U32)ALL_PORT_INDEX) && + (nPortIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == (OMX_U32)ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorIncorrectStateOperation; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE Exynos_CheckPortDisable( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorUndefined; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 nPortIndex = nParam; + + OMX_U32 i = 0; + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((nPortIndex != (OMX_U32)ALL_PORT_INDEX) && + (nPortIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == (OMX_U32)ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + ret = OMX_ErrorNone; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE Exynos_CheckPortEnable( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorUndefined; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 nPortIndex = nParam; + + OMX_U32 i = 0; + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((nPortIndex != (OMX_U32)ALL_PORT_INDEX) && + (nPortIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == (OMX_U32)ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + ret = OMX_ErrorNone; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE Exynos_CheckMarkBuffer( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorUndefined; + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if (nParam >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorIncorrectStateOperation; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE Exynos_SetStateSet( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + OMX_U32 i = 0; + + FunctionIn(); + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + switch ((OMX_STATETYPE)nParam) { + case OMX_StateIdle: + { + /* Loaded to Idle */ + if (pExynosComponent->currentState == OMX_StateLoaded) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateLoadedToIdle; + + for(i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateEnabling; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateLoaded to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + /* Executing to Idle */ + if (pExynosComponent->currentState == OMX_StateExecuting) { + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + pExynosComponent->transientState = EXYNOS_OMX_TransStateExecutingToIdle; + + pExynosPort = &(pExynosComponent->pExynosPort[INPUT_PORT_INDEX]); + if ((pExynosPort->portDefinition.bEnabled == OMX_FALSE) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + pExynosPort->exceptionFlag = INVALID_STATE; + } + + pExynosPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + if ((pExynosPort->portDefinition.bEnabled == OMX_FALSE) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + pExynosPort->exceptionFlag = INVALID_STATE; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateExecuting to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + /* Pause to Idle */ + if (pExynosComponent->currentState == OMX_StatePause) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StatePause to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_StateExecuting: + { + /* Idle to Executing */ + if (pExynosComponent->currentState == OMX_StateIdle) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateIdleToExecuting; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateExecuting", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + /* Pause to Executing */ + if (pExynosComponent->currentState == OMX_StatePause) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StatePause to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = OMX_ErrorBadParameter; + } + break; + case OMX_StateLoaded: + { + /* Idle to Loaded */ + if (pExynosComponent->currentState == OMX_StateIdle) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateIdleToLoaded; + + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateDisabling; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateLoaded", pExynosComponent, __FUNCTION__); + } + } + break; + case OMX_StateInvalid: + { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateInvalid; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, stateString(pExynosComponent->currentState)); + } + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s to %s", pExynosComponent, __FUNCTION__, + stateString(pExynosComponent->currentState), stateString(nParam)); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_SetPortFlush( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 nPortIndex = nParam; + + OMX_U32 i; + + FunctionIn(); + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + if ((nPortIndex != (OMX_U32)ALL_PORT_INDEX) && + (nPortIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == (OMX_U32)ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateFlushing; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateFlushing; + } + } else { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_SetPortDisable( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 nPortIndex = nParam; + + OMX_U32 i = 0; + + FunctionIn(); + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((nPortIndex != (OMX_U32)ALL_PORT_INDEX) && + (nPortIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == (OMX_U32)ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateDisabling; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateDisabling; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_SetPortEnable( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 nPortIndex = nParam; + + OMX_U32 i; + + FunctionIn(); + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((nPortIndex != (OMX_U32)ALL_PORT_INDEX) && + (nPortIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == (OMX_U32)ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; + +} + +static OMX_ERRORTYPE Exynos_SetMarkBuffer( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if (nParam >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorIncorrectStateOperation; + } + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_ComponentStateSet( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 destState) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_STATETYPE currentState = OMX_StateLoaded; + + int i; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + currentState = pExynosComponent->currentState; + + if (pExynosComponent->currentState == (OMX_STATETYPE)destState) { + ret = OMX_ErrorSameState; + goto EXIT; + } + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] current:(%s) dest:(%s)", pExynosComponent, __FUNCTION__, + stateString(currentState), stateString(destState)); + switch ((OMX_STATETYPE)destState) { + case OMX_StateInvalid: + { + switch (currentState) { + case OMX_StateWaitForResources: + Exynos_OMX_Out_WaitForResource(pOMXComponent); + case OMX_StateIdle: + case OMX_StateExecuting: + case OMX_StatePause: + case OMX_StateLoaded: + pExynosComponent->currentState = OMX_StateInvalid; + + ret = pExynosComponent->exynos_BufferProcessTerminate(pOMXComponent); + + for (i = 0; i < ALL_PORT_NUM; i++) { + /* terminate mutex in way */ + if (pExynosComponent->pExynosPort[i].portWayType == WAY1_PORT) { + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].way.port1WayDataBuffer.dataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].way.port1WayDataBuffer.dataBuffer.bufferMutex = NULL; + } else if (pExynosComponent->pExynosPort[i].portWayType == WAY2_PORT) { + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.inputDataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.inputDataBuffer.bufferMutex = NULL; + + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.outputDataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.outputDataBuffer.bufferMutex = NULL; + } + + /* terminate mutex for port */ + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].hPortMutex); + pExynosComponent->pExynosPort[i].hPortMutex = NULL; + } + + /* terminate signal about pause */ + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pExynosPort[i].pauseEvent); + pExynosComponent->pExynosPort[i].pauseEvent = NULL; + } + + /* terminate sema for buffer handling on port */ + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SemaphoreTerminate(pExynosComponent->pExynosPort[i].bufferSemID); + pExynosComponent->pExynosPort[i].bufferSemID = NULL; + } + + //if (currentState != OMX_StateLoaded) + pExynosComponent->exynos_codec_componentTerminate(pOMXComponent); + + ret = OMX_ErrorInvalidState; + + if (pExynosComponent->abendState == OMX_TRUE) + goto NO_EVENT_EXIT; + + break; + default: + ret = OMX_ErrorInvalidState; + break; + } + } + break; + case OMX_StateLoaded: + { + switch (currentState) { + case OMX_StateIdle: + for(i = 0; i < (int)pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateDisabling; + + ret = pExynosComponent->exynos_BufferProcessTerminate(pOMXComponent); + + for (i = 0; i < ALL_PORT_NUM; i++) { + /* terminate mutex in way */ + if (pExynosComponent->pExynosPort[i].portWayType == WAY1_PORT) { + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].way.port1WayDataBuffer.dataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].way.port1WayDataBuffer.dataBuffer.bufferMutex = NULL; + } else if (pExynosComponent->pExynosPort[i].portWayType == WAY2_PORT) { + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.inputDataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.inputDataBuffer.bufferMutex = NULL; + + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.outputDataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.outputDataBuffer.bufferMutex = NULL; + } + + /* terminate mutex for port */ + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].hPortMutex); + pExynosComponent->pExynosPort[i].hPortMutex = NULL; + } + + /* terminate signal about pause */ + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pExynosPort[i].pauseEvent); + pExynosComponent->pExynosPort[i].pauseEvent = NULL; + } + + /* terminate sema for buffer handling on port */ + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SemaphoreTerminate(pExynosComponent->pExynosPort[i].bufferSemID); + pExynosComponent->pExynosPort[i].bufferSemID = NULL; + } + + pExynosComponent->exynos_codec_componentTerminate(pOMXComponent); + +#ifdef TUNNELING_SUPPORT + for (i = 0; i < (pExynosComponent->portParam.nPorts); i++) { + pExynosPort = &(pExynosComponent->pExynosPort[i]); + if (CHECK_PORT_TUNNELED(pExynosPort) && + CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + while (Exynos_OSAL_GetElemNum(&(pExynosPort->bufferQ)) > 0) { + EXYNOS_OMX_MESSAGE *pMessage = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (pMessage != NULL) + Exynos_OSAL_Free(pMessage); + } + + ret = pExynosComponent->exynos_FreeTunnelBuffer(pExynosPort, i); + if (OMX_ErrorNone != ret) + goto EXIT; + } + } +#endif + + /* if all buffers are freed, send an event */ + if ((pExynosComponent->pExynosPort[INPUT_PORT_INDEX].assignedBufferNum <= 0) && + (pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].assignedBufferNum <= 0)) { + Exynos_OMX_SendEventCommand(pExynosComponent, EVENT_CMD_STATE_TO_LOAD_STATE, NULL); + } + + goto NO_EVENT_EXIT; + case OMX_StateWaitForResources: + ret = Exynos_OMX_Out_WaitForResource(pOMXComponent); + + pExynosComponent->currentState = OMX_StateLoaded; + break; + case OMX_StateExecuting: + case OMX_StatePause: + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + } + break; + case OMX_StateIdle: + { + switch (currentState) { + case OMX_StateLoaded: + for (i = 0; i < (int)pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &(pExynosComponent->pExynosPort[i]); + + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + +#ifdef TUNNELING_SUPPORT + if (CHECK_PORT_TUNNELED(pExynosPort) && + CHECK_PORT_BUFFER_SUPPLIER(pExynosPort) && + CHECK_PORT_ENABLED(pExynosPort)) { + ret = pExynosComponent->exynos_AllocateTunnelBuffer(pExynosPort, i); + if (ret!=OMX_ErrorNone) + goto EXIT; + } +#endif + } + + Exynos_OSAL_Get_Log_Property(); // For debuging, Function called when GetHandle function is success + + ret = pExynosComponent->exynos_codec_componentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to exynos_codec_componentInit() (0x%x)", pExynosComponent, __FUNCTION__, ret); +#ifdef TUNNELING_SUPPORT + /* + * if (CHECK_PORT_TUNNELED == OMX_TRUE) thenTunnel Buffer Free + */ +#endif + goto EXIT; + } + + /* create sema for buffer handling on port */ + for (i = 0; i < ALL_PORT_NUM; i++) { + ret = Exynos_OSAL_SemaphoreCreate(&pExynosComponent->pExynosPort[i].bufferSemID); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SemaphoreCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto FAIL_TO_IDLE; + } + } + + /* create signal about pause */ + for (i = 0; i < ALL_PORT_NUM; i++) { + ret = Exynos_OSAL_SignalCreate(&pExynosComponent->pExynosPort[i].pauseEvent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Exynos_OSAL_SignalCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto FAIL_TO_IDLE; + } + } + + for (i = 0; i < ALL_PORT_NUM; i++) { + /* create mutex in way */ + if (pExynosComponent->pExynosPort[i].portWayType == WAY1_PORT) { + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->pExynosPort[i].way.port1WayDataBuffer.dataBuffer.bufferMutex); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Exynos_OSAL_MutexCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto FAIL_TO_IDLE; + } + } else if (pExynosComponent->pExynosPort[i].portWayType == WAY2_PORT) { + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.inputDataBuffer.bufferMutex); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Exynos_OSAL_MutexCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto FAIL_TO_IDLE; + } + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.outputDataBuffer.bufferMutex); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Exynos_OSAL_MutexCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto FAIL_TO_IDLE; + } + } + + /* create mutex for port */ + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->pExynosPort[i].hPortMutex); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Exynos_OSAL_MutexCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto FAIL_TO_IDLE; + } + } + + ret = pExynosComponent->exynos_BufferProcessCreate(pOMXComponent); + if (ret != OMX_ErrorNone) { +FAIL_TO_IDLE: +#ifdef TUNNELING_SUPPORT + /* + * if (CHECK_PORT_TUNNELED == OMX_TRUE) thenTunnel Buffer Free + */ +#endif + for (i = 0; i < ALL_PORT_NUM; i++) { + /* terminate mutex in way */ + if (pExynosComponent->pExynosPort[i].portWayType == WAY1_PORT) { + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].way.port1WayDataBuffer.dataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].way.port1WayDataBuffer.dataBuffer.bufferMutex = NULL; + } else if (pExynosComponent->pExynosPort[i].portWayType == WAY2_PORT) { + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.inputDataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.inputDataBuffer.bufferMutex = NULL; + + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.outputDataBuffer.bufferMutex); + pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.outputDataBuffer.bufferMutex = NULL; + } + + /* terminate mutex for port */ + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].hPortMutex); + pExynosComponent->pExynosPort[i].hPortMutex = NULL; + } + + /* terminate signal about pause */ + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pExynosPort[i].pauseEvent); + pExynosComponent->pExynosPort[i].pauseEvent = NULL; + } + + /* terminate sema for buffer handling on port */ + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SemaphoreTerminate(pExynosComponent->pExynosPort[i].bufferSemID); + pExynosComponent->pExynosPort[i].bufferSemID = NULL; + } + + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* if all buffers are allocated, send an event */ + if (CHECK_PORT_POPULATED(&(pExynosComponent->pExynosPort[INPUT_PORT_INDEX])) && + CHECK_PORT_POPULATED(&(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]))) { + Exynos_OMX_SendEventCommand(pExynosComponent, EVENT_CMD_STATE_TO_IDLE_STATE, NULL); + } + + goto NO_EVENT_EXIT; + break; + case OMX_StateExecuting: + Exynos_SetPortFlush(pExynosComponent, ALL_PORT_INDEX); + + ret = Exynos_OMX_BufferFlushProcess(pOMXComponent, ALL_PORT_INDEX, OMX_FALSE); + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateIdle; + break; + case OMX_StatePause: + Exynos_SetPortFlush(pExynosComponent, ALL_PORT_INDEX); + + ret = Exynos_OMX_BufferFlushProcess(pOMXComponent, ALL_PORT_INDEX, OMX_FALSE); + + pExynosComponent->currentState = OMX_StateIdle; + break; + case OMX_StateWaitForResources: + pExynosComponent->currentState = OMX_StateIdle; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + } + break; + case OMX_StateExecuting: + { + int j; + + switch (currentState) { + case OMX_StateLoaded: + ret = OMX_ErrorIncorrectStateTransition; + break; + case OMX_StateIdle: +#ifdef TUNNELING_SUPPORT + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + if (CHECK_PORT_TUNNELED(pExynosPort) && + CHECK_PORT_BUFFER_SUPPLIER(pExynosPort) && + CHECK_PORT_ENABLED(pExynosPort)) { + for (j = 0; j < pExynosPort->tunnelBufferNum; j++) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[i].bufferSemID); + } + } +#endif + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateExecuting; + + /* set signal about pause */ + for (i = 0; i < ALL_PORT_NUM; i++) + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[i].pauseEvent); + break; + case OMX_StatePause: +#ifdef TUNNELING_SUPPORT + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + if (CHECK_PORT_TUNNELED(pExynosPort) && + CHECK_PORT_BUFFER_SUPPLIER(pExynosPort) && + CHECK_PORT_ENABLED(pExynosPort)) { + OMX_S32 semaValue = 0, cnt = 0; + + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[i].bufferSemID, &semaValue); + if (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > semaValue) { + cnt = Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) - semaValue; + for (j = 0; j < cnt; j++) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[i].bufferSemID); + } + } + } +#endif + pExynosComponent->currentState = OMX_StateExecuting; + + /* set signal about pause */ + for (i = 0; i < ALL_PORT_NUM; i++) + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[i].pauseEvent); + break; + case OMX_StateWaitForResources: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + } + break; + case OMX_StatePause: + { + switch (currentState) { + case OMX_StateLoaded: + ret = OMX_ErrorIncorrectStateTransition; + break; + case OMX_StateIdle: + pExynosComponent->currentState = OMX_StatePause; + break; + case OMX_StateExecuting: + pExynosComponent->currentState = OMX_StatePause; + break; + case OMX_StateWaitForResources: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + } + break; + case OMX_StateWaitForResources: + { + switch (currentState) { + case OMX_StateLoaded: + ret = Exynos_OMX_In_WaitForResource(pOMXComponent); + pExynosComponent->currentState = OMX_StateWaitForResources; + break; + case OMX_StateIdle: + case OMX_StateExecuting: + case OMX_StatePause: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + } + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + if (pExynosComponent->pCallbacks != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(%s)", + pExynosComponent, __FUNCTION__, stateString(destState)); + + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, OMX_CommandStateSet, + destState, NULL); + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Exynos_OMX_ComponentStateSet(%s) (0x%x)", + pExynosComponent, __FUNCTION__, stateString(destState), ret); + if ((pExynosComponent != NULL) && + (pExynosComponent->pCallbacks != NULL)) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +NO_EVENT_EXIT: /* postpone to send event */ + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_EventHandler( + OMX_COMPONENTTYPE *pOMXComponent, + EVENT_COMMAD_TYPE cmd) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + int i = 0; + + if ((pOMXComponent == NULL) || + (pOMXComponent->pComponentPrivate == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + switch (cmd) { + case EVENT_CMD_STATE_TO_LOAD_STATE: /* Idle to Loaded */ + { + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (pExynosComponent->currentState == OMX_StateLoaded) { + /* event was already handled */ + break; + } + + if ((pExynosComponent->currentState != OMX_StateIdle) || + (pExynosComponent->transientState != EXYNOS_OMX_TransStateIdleToLoaded)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid state(state:0x%x, transient:0x%x)", + pExynosComponent, __FUNCTION__, + pExynosComponent->currentState, pExynosComponent->transientState); + break; + } + + for (i = 0; i < (int)pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &(pExynosComponent->pExynosPort[i]); + + if (CHECK_PORT_ENABLED(pExynosPort)) { + while (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > 0) { + EXYNOS_OMX_MESSAGE *pMsg = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (pMsg != NULL) + Exynos_OSAL_Free(pMsg); + } + } + + pExynosPort->portState = EXYNOS_OMX_PortStateLoaded; + } + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateLoaded; + + if (pExynosComponent->pCallbacks != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(OMX_StateLoaded)", pExynosComponent, __FUNCTION__); + + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandStateSet, + OMX_StateLoaded, + NULL); + } + } + break; + case EVENT_CMD_STATE_TO_IDLE_STATE: /* Loaded to Idle */ + { + if (pExynosComponent->currentState == OMX_StateIdle) { + /* event was already handled */ + break; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) || + (pExynosComponent->transientState != EXYNOS_OMX_TransStateLoadedToIdle)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid state(state:0x%x, transient:0x%x)", + pExynosComponent, __FUNCTION__, + pExynosComponent->currentState, pExynosComponent->transientState); + break; + } + + for (i = 0; i < (int)pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateIdle; + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateIdle; + + if (pExynosComponent->pCallbacks != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(OMX_StateIdle)", pExynosComponent, __FUNCTION__); + + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandStateSet, + OMX_StateIdle, + NULL); + } + } + break; + case EVENT_CMD_DISABLE_INPUT_PORT: /* PortDisable(INPUT_PORT) */ + { + if (!CHECK_PORT_ENABLED((&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]))) { + /* event was already handled */ + break; + } + + Exynos_OMX_DisablePort(pOMXComponent, INPUT_PORT_INDEX); + + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portState = EXYNOS_OMX_PortStateLoaded; + + if (pExynosComponent->pCallbacks != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(Disable/input port)", pExynosComponent, __FUNCTION__); + + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortDisable, INPUT_PORT_INDEX, NULL); + } + } + break; + case EVENT_CMD_DISABLE_OUTPUT_PORT: + { + if (!CHECK_PORT_ENABLED((&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]))) { + /* event was already handled */ + break; + } + + Exynos_OMX_DisablePort(pOMXComponent, OUTPUT_PORT_INDEX); + + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portState = EXYNOS_OMX_PortStateLoaded; + + if (pExynosComponent->pCallbacks != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(Disable/output port)", pExynosComponent, __FUNCTION__); + + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortDisable, OUTPUT_PORT_INDEX, NULL); + } + } + break; + case EVENT_CMD_ENABLE_INPUT_PORT: /* PortEnable(INPUT_PORT) */ + { + if (CHECK_PORT_ENABLED((&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]))) { + /* event was already handled */ + break; + } + + Exynos_OMX_EnablePort(pOMXComponent, INPUT_PORT_INDEX); + + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portState = EXYNOS_OMX_PortStateIdle; + + if (pExynosComponent->pCallbacks != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(Enable/input port)", pExynosComponent, __FUNCTION__); + + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortEnable, INPUT_PORT_INDEX, NULL); + } + } + break; + case EVENT_CMD_ENABLE_OUTPUT_PORT: /* PortEnable(OUTPUT_PORT) */ + { + if (CHECK_PORT_ENABLED((&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]))) { + /* event was already handled */ + break; + } + + Exynos_OMX_EnablePort(pOMXComponent, OUTPUT_PORT_INDEX); + + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portState = EXYNOS_OMX_PortStateIdle; + + if (pExynosComponent->pCallbacks != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(Enable/output port)", pExynosComponent, __FUNCTION__); + + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortEnable, OUTPUT_PORT_INDEX, NULL); + } + } + break; + default: + ret = OMX_ErrorBadParameter; + break; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_MessageHandlerThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (threadData == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + while (pExynosComponent->bExitMessageHandlerThread == OMX_FALSE) { + EXYNOS_OMX_MESSAGE *pMessage = NULL; + + Exynos_OSAL_SemaphoreWait(pExynosComponent->hSemaMsgWait); + + pMessage = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosComponent->messageQ); + if (pMessage != NULL) { + switch ((int)pMessage->type) { + case OMX_CommandStateSet: + { + Exynos_SetStateSet(pExynosComponent, pMessage->param); + + if (pMessage->param != OMX_StateInvalid) + Exynos_OSAL_SemaphorePost(pExynosComponent->hSemaMsgProgress); + + ret = Exynos_OMX_ComponentStateSet(pOMXComponent, pMessage->param); + + if (pMessage->param == OMX_StateInvalid) + Exynos_OSAL_SemaphorePost(pExynosComponent->hSemaMsgProgress); + } + break; + case OMX_CommandFlush: + { + Exynos_SetPortFlush(pExynosComponent, pMessage->param); + + Exynos_OSAL_SemaphorePost(pExynosComponent->hSemaMsgProgress); + + ret = Exynos_OMX_BufferFlushProcess(pOMXComponent, pMessage->param, OMX_TRUE); + } + break; + case OMX_CommandPortDisable: + { + Exynos_SetPortDisable(pExynosComponent, pMessage->param); + + Exynos_OSAL_SemaphorePost(pExynosComponent->hSemaMsgProgress); + + ret = Exynos_OMX_PortDisableProcess(pOMXComponent, pMessage->param); + } + break; + case OMX_CommandPortEnable: + { + Exynos_SetPortEnable(pExynosComponent, pMessage->param); + + Exynos_OSAL_SemaphorePost(pExynosComponent->hSemaMsgProgress); + + ret = Exynos_OMX_PortEnableProcess(pOMXComponent, pMessage->param); + } + break; + case OMX_CommandMarkBuffer: + { + OMX_U32 nPortIndex = pMessage->param; + + if ((pMessage->pCmdData != NULL) && + ((nPortIndex == INPUT_PORT_INDEX) || + (nPortIndex == OUTPUT_PORT_INDEX))) { + OMX_MARKTYPE *pMarkType = (OMX_MARKTYPE *)(pMessage->pCmdData); + + pExynosComponent->pExynosPort[nPortIndex].markType.hMarkTargetComponent = pMarkType->hMarkTargetComponent; + pExynosComponent->pExynosPort[nPortIndex].markType.pMarkData = pMarkType->pMarkData; + } + } + break; + case Exynos_OMX_CommandSendEvent: + { + Exynos_OMX_EventHandler(pOMXComponent, (EVENT_COMMAD_TYPE)pMessage->param); + } + break; + case EXYNOS_OMX_CommandComponentDeInit: + { + pExynosComponent->bExitMessageHandlerThread = OMX_TRUE; + } + break; + default: + break; + } + + Exynos_OSAL_Free(pMessage); + pMessage = NULL; + } + } + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_CommandQueue( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COMMANDTYPE Cmd, + OMX_U32 nParam, + OMX_PTR pCmdData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_MESSAGE *command = NULL; + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + command = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_MESSAGE)); + if (command == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Exynos_OSAL_Malloc()", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + command->type = (OMX_U32)Cmd; + command->param = nParam; + command->pCmdData = pCmdData; + + ret = Exynos_OSAL_Queue(&pExynosComponent->messageQ, (void *)command); + if (ret != 0) { + Exynos_OSAL_Free(command); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + ret = Exynos_OSAL_SemaphorePost(pExynosComponent->hSemaMsgWait); + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pParams) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pParams == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch ((int)nParamIndex) { + case OMX_IndexParamAudioInit: + case OMX_IndexParamVideoInit: + case OMX_IndexParamImageInit: + case OMX_IndexParamOtherInit: + { + OMX_PORT_PARAM_TYPE *pPortParam = (OMX_PORT_PARAM_TYPE *)pParams; + + ret = Exynos_OMX_Check_SizeVersion(pPortParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pPortParam->nPorts = 0; + pPortParam->nStartPortNumber = 0; + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *pDstPortDef = (OMX_PARAM_PORTDEFINITIONTYPE *)pParams; + OMX_U32 nPortIndex = pDstPortDef->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pDstPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + Exynos_OSAL_Memcpy(((char *)pDstPortDef) + nOffset, + ((char *)&pExynosPort->portDefinition) + nOffset, + pDstPortDef->nSize - nOffset); + } + break; + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *pPriority = (OMX_PRIORITYMGMTTYPE *)pParams; + + ret = Exynos_OMX_Check_SizeVersion(pPriority, sizeof(OMX_PRIORITYMGMTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pPriority->nGroupID = pExynosComponent->compPriority.nGroupID; + pPriority->nGroupPriority = pExynosComponent->compPriority.nGroupPriority; + } + break; + + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *pSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pParams; + OMX_U32 nPortIndex = pSupplierType->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if ((pExynosComponent->currentState == OMX_StateLoaded) || + (pExynosComponent->currentState == OMX_StateWaitForResources)) { + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pSupplierType, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (pExynosPort->portDefinition.eDir == OMX_DirInput) { + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + pSupplierType->eBufferSupplier = OMX_BufferSupplyInput; + } else if (CHECK_PORT_TUNNELED(pExynosPort)) { + pSupplierType->eBufferSupplier = OMX_BufferSupplyOutput; + } else { + pSupplierType->eBufferSupplier = OMX_BufferSupplyUnspecified; + } + } else { + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + pSupplierType->eBufferSupplier = OMX_BufferSupplyOutput; + } else if (CHECK_PORT_TUNNELED(pExynosPort)) { + pSupplierType->eBufferSupplier = OMX_BufferSupplyInput; + } else { + pSupplierType->eBufferSupplier = OMX_BufferSupplyUnspecified; + } + } + } + else + { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + break; + case OMX_IndexExynosParamImageCrop: + { + EXYNOS_OMX_VIDEO_PARAM_IMAGE_CROP *pImageCrop = (EXYNOS_OMX_VIDEO_PARAM_IMAGE_CROP *)pParams; + + ret = Exynos_OMX_Check_SizeVersion(pImageCrop, sizeof(EXYNOS_OMX_VIDEO_PARAM_IMAGE_CROP)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pImageCrop->bEnabled = pExynosComponent->bUseImgCrop; + + ret = OMX_ErrorNone; + } + break; + + default: + { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + + ret = OMX_ErrorNone; + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_IN OMX_PTR pParams) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pParams == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch ((int)nParamIndex) { + case OMX_IndexParamAudioInit: + case OMX_IndexParamVideoInit: + case OMX_IndexParamImageInit: + case OMX_IndexParamOtherInit: + { + OMX_PORT_PARAM_TYPE *pPortParam = (OMX_PORT_PARAM_TYPE *)pParams; + + ret = Exynos_OMX_Check_SizeVersion(pPortParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + /* ret = OMX_ErrorUndefined; */ + /* Exynos_OSAL_Memcpy(&pExynosComponent->portParam, pPortParam, sizeof(OMX_PORT_PARAM_TYPE)); */ + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *pSrcPortDef = (OMX_PARAM_PORTDEFINITIONTYPE *)pParams; + OMX_U32 nPortIndex = pSrcPortDef->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pSrcPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + if (pSrcPortDef->nBufferCountActual < pExynosPort->portDefinition.nBufferCountMin) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Memcpy(((char *)&pExynosPort->portDefinition) + nOffset, + ((char *)pSrcPortDef) + nOffset, + pSrcPortDef->nSize - nOffset); + } + break; + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *pPriority = (OMX_PRIORITYMGMTTYPE *)pParams; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPriority, sizeof(OMX_PRIORITYMGMTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosComponent->compPriority.nGroupID = pPriority->nGroupID; + pExynosComponent->compPriority.nGroupPriority = pPriority->nGroupPriority; + } + break; + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *pSupplierType = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pParams; + OMX_U32 nPortIndex = pSupplierType->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pSupplierType, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + if (pSupplierType->eBufferSupplier == OMX_BufferSupplyUnspecified) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) == 0) { + ret = OMX_ErrorNone; /*OMX_ErrorNone ?????*/ + goto EXIT; + } + + if (pExynosPort->portDefinition.eDir == OMX_DirInput) { + if (pSupplierType->eBufferSupplier == OMX_BufferSupplyInput) { + /* + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorNone; + } + */ + pExynosPort->tunnelFlags |= EXYNOS_TUNNEL_IS_SUPPLIER; + pSupplierType->nPortIndex = pExynosPort->tunneledPort; + + ret = OMX_SetParameter(pExynosPort->tunneledComponent, OMX_IndexParamCompBufferSupplier, pSupplierType); + + goto EXIT; + } else if (pSupplierType->eBufferSupplier == OMX_BufferSupplyOutput) { + ret = OMX_ErrorNone; + + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + pExynosPort->tunnelFlags &= ~EXYNOS_TUNNEL_IS_SUPPLIER; + pSupplierType->nPortIndex = pExynosPort->tunneledPort; + + ret = OMX_SetParameter(pExynosPort->tunneledComponent, OMX_IndexParamCompBufferSupplier, pSupplierType); + } + + goto EXIT; + } + } else if (pExynosPort->portDefinition.eDir == OMX_DirOutput) { + if (pSupplierType->eBufferSupplier == OMX_BufferSupplyInput) { + ret = OMX_ErrorNone; + + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + pExynosPort->tunnelFlags &= ~EXYNOS_TUNNEL_IS_SUPPLIER; + ret = OMX_ErrorNone; + } + + goto EXIT; + } else if (pSupplierType->eBufferSupplier == OMX_BufferSupplyOutput) { + /* + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorNone; + } + */ + + pExynosPort->tunnelFlags |= EXYNOS_TUNNEL_IS_SUPPLIER; + ret = OMX_ErrorNone; + + goto EXIT; + } + } + } + break; + default: + { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + + ret = OMX_ErrorNone; + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nConfigIndex, + OMX_INOUT OMX_PTR pConfigs) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pConfigs == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nConfigIndex) { + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nConfigIndex, + OMX_IN OMX_PTR pConfigs) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pConfigs == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (nConfigIndex) { + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_IMAGE_CROP) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamImageCrop; + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = OMX_ErrorBadParameter; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_PTR Exynos_OMX_MakeDynamicConfig( + OMX_INDEXTYPE nConfigIndex, + OMX_PTR pConfigs) +{ + OMX_PTR ret = NULL; + OMX_S32 nConfigSize = 0; + + switch ((int)nConfigIndex) { + case OMX_IndexConfigVideoIntraPeriod: + { + nConfigSize = sizeof(OMX_U32); + + ret = Exynos_OSAL_Malloc(sizeof(OMX_U32) + nConfigSize); + } + break; + case OMX_IndexConfigVideoRoiInfo: + { + EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *pRoiInfo = (EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *)pConfigs; + OMX_S32 nRoiMBInfoSize = 0; + + nConfigSize = *(OMX_U32 *)pConfigs; + + if (pRoiInfo->bUseRoiInfo == OMX_TRUE) + nRoiMBInfoSize = pRoiInfo->nRoiMBInfoSize; + + ret = Exynos_OSAL_Malloc(sizeof(OMX_U32) + nConfigSize + nRoiMBInfoSize); + + if (ret != NULL) + Exynos_OSAL_Memcpy((OMX_PTR)((OMX_U8 *)ret + sizeof(OMX_U32) + nConfigSize), pRoiInfo->pRoiMBInfo, nRoiMBInfoSize); + } + break; + default: + nConfigSize = *(OMX_U32 *)pConfigs; + + ret = Exynos_OSAL_Malloc(sizeof(OMX_U32) + nConfigSize); + break; + } + + if (ret != NULL) { + *((OMX_S32 *)ret) = (OMX_S32)nConfigIndex; + Exynos_OSAL_Memcpy((OMX_PTR)((OMX_U8 *)ret + sizeof(OMX_U32)), pConfigs, nConfigSize); + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SendEventCommand( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + EVENT_COMMAD_TYPE Cmd, + OMX_PTR pCmdData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] current state is OMX_StateInvalid", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + ret = Exynos_OMX_CommandQueue(pExynosComponent, (OMX_COMMANDTYPE)Exynos_OMX_CommandSendEvent, Cmd, pCmdData); + +EXIT: + FunctionOut(); + + return ret; +} + +void Exynos_OMX_Component_AbnormalTermination(OMX_HANDLETYPE hComponent) +{ + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + if (pOMXComponent->pComponentPrivate == NULL) + goto EXIT; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + /* clear a msg command piled on queue */ + while(Exynos_OSAL_GetElemNum(&pExynosComponent->messageQ) > 0) + Exynos_OSAL_Free(Exynos_OSAL_Dequeue(&pExynosComponent->messageQ)); + + pExynosComponent->abendState = OMX_TRUE; + + /* change to invalid state */ + Exynos_OMX_SendCommand(hComponent, OMX_CommandStateSet, OMX_StateInvalid, NULL); + +EXIT: + FunctionOut(); + + return; +} + +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Constructor( + OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] lib version is %s", __FUNCTION__, IS_64BIT_OS? "64bit":"32bit"); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x)", __FUNCTION__, ret); + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BASECOMPONENT)); + if (pExynosComponent == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Malloc (0x%x)", __FUNCTION__, ret); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent, 0, sizeof(EXYNOS_OMX_BASECOMPONENT)); + pOMXComponent->pComponentPrivate = (OMX_PTR)pExynosComponent; + + ret = Exynos_OSAL_SemaphoreCreate(&pExynosComponent->hSemaMsgWait); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SemaphoreCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + ret = Exynos_OSAL_SemaphoreCreate(&pExynosComponent->hSemaMsgProgress); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SemaphoreCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->compMutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to MutexCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->compEventMutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to MutexCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pExynosComponent->bExitMessageHandlerThread = OMX_FALSE; + Exynos_OSAL_QueueCreate(&pExynosComponent->messageQ, MAX_QUEUE_ELEMENTS); + ret = Exynos_OSAL_ThreadCreate(&pExynosComponent->hMessageHandler, Exynos_OMX_MessageHandlerThread, pOMXComponent); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ThreadCreate (0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + Exynos_OSAL_QueueCreate(&pExynosComponent->dynamicConfigQ, MAX_QUEUE_ELEMENTS); + + Exynos_OSAL_QueueCreate(&pExynosComponent->HDR10plusConfigQ, MAX_QUEUE_ELEMENTS); + + pOMXComponent->GetComponentVersion = &Exynos_OMX_GetComponentVersion; + pOMXComponent->SendCommand = &Exynos_OMX_SendCommand; + pOMXComponent->GetState = &Exynos_OMX_GetState; + pOMXComponent->SetCallbacks = &Exynos_OMX_SetCallbacks; + +#ifdef EGL_IMAGE_SUPPORT + pOMXComponent->UseEGLImage = &Exynos_OMX_UseEGLImage; +#endif + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Destructor( + OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 semaValue = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + while(Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + Exynos_OSAL_Free(Exynos_OSAL_Dequeue(&pExynosComponent->dynamicConfigQ)); + } + Exynos_OSAL_QueueTerminate(&pExynosComponent->dynamicConfigQ); + + while(Exynos_OSAL_GetElemNum(&pExynosComponent->HDR10plusConfigQ) > 0) { + Exynos_OSAL_Free(Exynos_OSAL_Dequeue(&pExynosComponent->HDR10plusConfigQ)); + } + Exynos_OSAL_QueueTerminate(&pExynosComponent->HDR10plusConfigQ); + + Exynos_OMX_CommandQueue(pExynosComponent, (OMX_COMMANDTYPE)EXYNOS_OMX_CommandComponentDeInit, 0, NULL); + Exynos_OSAL_SleepMillisec(0); + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->hSemaMsgWait, &semaValue); + if (semaValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->hSemaMsgWait); + Exynos_OSAL_SemaphorePost(pExynosComponent->hSemaMsgWait); + + Exynos_OSAL_ThreadTerminate(pExynosComponent->hMessageHandler); + pExynosComponent->hMessageHandler = NULL; + + Exynos_OSAL_MutexTerminate(pExynosComponent->compEventMutex); + pExynosComponent->compMutex = NULL; + + Exynos_OSAL_MutexTerminate(pExynosComponent->compMutex); + pExynosComponent->compMutex = NULL; + + Exynos_OSAL_SemaphoreTerminate(pExynosComponent->hSemaMsgProgress); + pExynosComponent->hSemaMsgProgress = NULL; + + Exynos_OSAL_SemaphoreTerminate(pExynosComponent->hSemaMsgWait); + pExynosComponent->hSemaMsgWait = NULL; + Exynos_OSAL_QueueTerminate(&pExynosComponent->messageQ); + + Exynos_OSAL_Free(pExynosComponent); + pExynosComponent = NULL; + + ret = OMX_ErrorNone; +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/common/Exynos_OMX_Basecomponent.h b/openmax/component/common/Exynos_OMX_Basecomponent.h new file mode 100644 index 0000000..dfd5f83 --- /dev/null +++ b/openmax/component/common/Exynos_OMX_Basecomponent.h @@ -0,0 +1,166 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Basecomponent.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.5.0 + * @history + * 2012.02.20 : Create +* 2017.08.03 : Change event handling + */ + +#ifndef EXYNOS_OMX_BASECOMP +#define EXYNOS_OMX_BASECOMP + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OSAL_Queue.h" +#include "Exynos_OMX_Baseport.h" + + +typedef struct _EXYNOS_OMX_MESSAGE +{ + OMX_U32 type; + OMX_U32 param; + OMX_PTR pCmdData; +} EXYNOS_OMX_MESSAGE; + +/* for Check TimeStamp after Seek */ +typedef struct _EXYNOS_OMX_TIMESTAMP +{ + OMX_BOOL needSetStartTimeStamp; + OMX_BOOL needCheckStartTimeStamp; + OMX_TICKS startTimeStamp; + OMX_U32 nStartFlags; +} EXYNOS_OMX_TIMESTAMP; + +typedef struct _EXYNOS_OMX_BASECOMPONENT +{ + OMX_STRING componentName; + OMX_VERSIONTYPE componentVersion; + OMX_VERSIONTYPE specVersion; + + OMX_STATETYPE currentState; + EXYNOS_OMX_TRANS_STATETYPE transientState; + OMX_BOOL abendState; + + EXYNOS_CODEC_TYPE codecType; + EXYNOS_OMX_PRIORITYMGMTTYPE compPriority; + OMX_MARKTYPE propagateMarkType; + OMX_HANDLETYPE compMutex; + OMX_HANDLETYPE compEventMutex; + + OMX_HANDLETYPE hComponentHandle; + + /* Message Handler */ + OMX_BOOL bExitMessageHandlerThread; + OMX_HANDLETYPE hMessageHandler; + OMX_HANDLETYPE hSemaMsgWait; + OMX_HANDLETYPE hSemaMsgProgress; + EXYNOS_QUEUE messageQ; + EXYNOS_QUEUE dynamicConfigQ; + + /* Port */ + OMX_PORT_PARAM_TYPE portParam; + EXYNOS_OMX_BASEPORT *pExynosPort; + + /* Callback function */ + OMX_CALLBACKTYPE *pCallbacks; + OMX_PTR callbackData; + + /* Save Timestamp */ + OMX_BOOL bTimestampSlotUsed[MAX_TIMESTAMP]; + OMX_TICKS timeStamp[MAX_TIMESTAMP]; + EXYNOS_OMX_TIMESTAMP checkTimeStamp; + + /* Save Flags */ + OMX_U32 nFlags[MAX_FLAGS]; + + OMX_BOOL getAllDelayBuffer; + OMX_BOOL reInputData; + OMX_BOOL bUseImgCrop; + + /* HDR10+ */ + EXYNOS_QUEUE HDR10plusConfigQ; + EXYNOS_OMX_VIDEO_HDR10PLUS_INFO HDR10plusList[MAX_BUFFER_REF]; + + OMX_BOOL bUseFlagEOF; + OMX_BOOL bSaveFlagEOS; /* bSaveFlagEOS is OMX_TRUE, if EOS flag is incoming. */ + OMX_BOOL bBehaviorEOS; /* bBehaviorEOS is OMX_TRUE, if EOS flag with Data are incoming. */ + + OMX_PTR vendorExts[MAX_VENDOR_EXT_NUM]; + + OMX_ERRORTYPE (*exynos_codec_componentInit)(OMX_COMPONENTTYPE *pOMXComponent); + OMX_ERRORTYPE (*exynos_codec_componentTerminate)(OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef TUNNELING_SUPPORT + OMX_ERRORTYPE (*exynos_AllocateTunnelBuffer)(EXYNOS_OMX_BASEPORT *pOMXBasePort, OMX_U32 nPortIndex); + OMX_ERRORTYPE (*exynos_FreeTunnelBuffer)(EXYNOS_OMX_BASEPORT *pOMXBasePort, OMX_U32 nPortIndex); +#endif + + OMX_ERRORTYPE (*exynos_BufferProcessCreate)(OMX_HANDLETYPE pOMXComponent); + OMX_ERRORTYPE (*exynos_BufferProcessTerminate)(OMX_HANDLETYPE pOMXComponent); + OMX_ERRORTYPE (*exynos_BufferFlush)(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex, OMX_BOOL bEvent); +} EXYNOS_OMX_BASECOMPONENT; + +OMX_ERRORTYPE Exynos_OMX_GetParameter( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nParamIndex, + OMX_PTR pParams); + +OMX_ERRORTYPE Exynos_OMX_SetParameter( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nParamIndex, + OMX_PTR pParams); + +OMX_ERRORTYPE Exynos_OMX_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nConfigIndex, + OMX_PTR pConfigs); + +OMX_ERRORTYPE Exynos_OMX_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nConfigIndex, + OMX_PTR pConfigs); + +OMX_ERRORTYPE Exynos_OMX_GetExtensionIndex( + OMX_HANDLETYPE hComponent, + OMX_STRING cParameterName, + OMX_INDEXTYPE *pIndexType); + +OMX_PTR Exynos_OMX_MakeDynamicConfig(OMX_INDEXTYPE nConfigIndex, OMX_PTR pConfigs); +OMX_ERRORTYPE Exynos_OMX_SendEventCommand(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, EVENT_COMMAD_TYPE Cmd, OMX_PTR pCmdData); +void Exynos_OMX_Component_AbnormalTermination(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Constructor(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Destructor(OMX_HANDLETYPE hComponent); + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OMX_Check_SizeVersion(OMX_PTR header, OMX_U32 size); + + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/common/Exynos_OMX_Baseport.c b/openmax/component/common/Exynos_OMX_Baseport.c new file mode 100644 index 0000000..4d8b7f1 --- /dev/null +++ b/openmax/component/common/Exynos_OMX_Baseport.c @@ -0,0 +1,1255 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Baseport.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.5.0 + * @history + * 2012.02.20 : Create + * 2017.08.03 : Change event handling + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_Memory.h" + +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Basecomponent.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_BASE_PORT" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +#ifdef PERFORMANCE_DEBUG +#include "Exynos_OSAL_ETC.h" +#endif + +#include "Exynos_OSAL_Platform.h" + + +OMX_ERRORTYPE Exynos_OMX_InputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE* bufferHeader) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 i = 0; + OMX_BOOL bBufferFind = OMX_FALSE; + + Exynos_OSAL_MutexLock(pExynosPort->hPortMutex); + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (bufferHeader == pExynosPort->extendBufferHeader[i].OMXBufferHeader) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_TRUE) { + pExynosPort->extendBufferHeader[i].bBufferInOMX = OMX_FALSE; + bBufferFind = OMX_TRUE; + break; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Trying to return the input buffer without ownership!!", pExynosComponent, __FUNCTION__); + } + } + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_CountDecrease(pExynosPort->hBufferCount, bufferHeader, INPUT_PORT_INDEX); +#endif + + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + + if ((bBufferFind == OMX_TRUE) && + (bufferHeader != NULL) && + (bufferHeader->pBuffer != NULL) && + (pExynosComponent->pCallbacks != NULL)) { + pExynosComponent->pCallbacks->EmptyBufferDone(pOMXComponent, + pExynosComponent->callbackData, + bufferHeader); + + if (bufferHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] bufferHeader(CSD): %p", pExynosComponent, __FUNCTION__, bufferHeader); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader: %p", pExynosComponent, __FUNCTION__, bufferHeader); + } + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_OutputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE* bufferHeader) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 i = 0; + OMX_BOOL bBufferFind = OMX_FALSE; + Exynos_OSAL_MutexLock(pExynosPort->hPortMutex); + for (i = 0; i < MAX_BUFFER_NUM; i++) { + if (bufferHeader == pExynosPort->extendBufferHeader[i].OMXBufferHeader) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_TRUE) { + bBufferFind = OMX_TRUE; + pExynosPort->extendBufferHeader[i].bBufferInOMX = OMX_FALSE; + break; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Trying to return the output buffer without ownership!!", pExynosComponent, __FUNCTION__); + } + } + } + +#ifdef PERFORMANCE_DEBUG + { + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + BUFFER_TIME inputBufferInfo, outBufferInfo; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "################################################################################"); + Exynos_OSAL_GetCountInfoUseTimestamp(pExynosInputPort->hBufferCount, bufferHeader->nTimeStamp, &inputBufferInfo); + Exynos_OSAL_GetCountInfoUseTimestamp(pExynosOutputPort->hBufferCount, bufferHeader->nTimeStamp, &outBufferInfo); + Exynos_OSAL_PrintCountInfo(inputBufferInfo, outBufferInfo); + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "################################################################################"); + } + + Exynos_OSAL_CountDecrease(pExynosPort->hBufferCount, bufferHeader, OUTPUT_PORT_INDEX); +#endif + + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + + if ((bBufferFind == OMX_TRUE) && + (bufferHeader != NULL) && + (bufferHeader->pBuffer != NULL) && + (pExynosComponent->pCallbacks != NULL)) { + pExynosComponent->pCallbacks->FillBufferDone(pOMXComponent, + pExynosComponent->callbackData, + bufferHeader); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader: %p", pExynosComponent, __FUNCTION__, bufferHeader); + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferFlushProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex, + OMX_BOOL bEvent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i, cnt; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + cnt = (nPortIndex == ALL_PORT_INDEX)? ALL_PORT_NUM:1; + for (i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + pExynosPort = &(pExynosComponent->pExynosPort[nIndex]); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Flush %s Port", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + ret = pExynosComponent->exynos_BufferFlush(pOMXComponent, nIndex, bEvent); + if (ret == OMX_ErrorNone) { + pExynosPort->portState = EXYNOS_OMX_PortStateIdle; + + if ((bEvent == OMX_TRUE) && + (pExynosComponent->pCallbacks != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(Flush/%s port)", + pExynosComponent, __FUNCTION__, (nIndex == INPUT_PORT_INDEX)? "input":"output"); + + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandFlush, nIndex, NULL); + } + } + } + +EXIT: + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + + if ((pExynosComponent != NULL) && + (pExynosComponent->pCallbacks != NULL)) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_DisablePort( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + pExynosPort->portDefinition.bEnabled = OMX_FALSE; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_PortDisableProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i, cnt; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + cnt = (nPortIndex == ALL_PORT_INDEX)? ALL_PORT_NUM:1; + for (i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + pExynosPort = &(pExynosComponent->pExynosPort[nIndex]); + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + /* do port flush */ + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Before disabling %s port, do flush", + pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + + pExynosPort->portState = EXYNOS_OMX_PortStateFlushingForDisable; + + ret = pExynosComponent->exynos_BufferFlush(pOMXComponent, nIndex, OMX_FALSE); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port is flushed", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + if (ret != OMX_ErrorNone) + goto EXIT; + + pExynosPort->portState = EXYNOS_OMX_PortStateDisabling; + } + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Disable %s Port", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + + if (CHECK_PORT_ENABLED(pExynosPort)) { + if (pExynosComponent->currentState != OMX_StateLoaded) { + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + while (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > 0) { + EXYNOS_OMX_MESSAGE *pMessage = (EXYNOS_OMX_MESSAGE*)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (pMessage != NULL) + Exynos_OSAL_Free(pMessage); + } + } + + if (pExynosPort->exceptionFlag == NEED_PORT_DISABLE) + pExynosPort->exceptionFlag = GENERAL_STATE; + } + + if (pExynosPort->assignedBufferNum <= 0) { + Exynos_OMX_SendEventCommand(pExynosComponent, + ((nIndex == INPUT_PORT_INDEX)? EVENT_CMD_DISABLE_INPUT_PORT:EVENT_CMD_DISABLE_OUTPUT_PORT), + NULL); + } + } + } + +EXIT: + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + + if ((pExynosComponent != NULL) && + (pExynosComponent->pCallbacks != NULL)) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_EnablePort( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + OMX_U32 i = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + pExynosPort->exceptionFlag = GENERAL_STATE; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + + if (pExynosPort->portWayType == WAY2_PORT) { + for (i = 0; i < ALL_WAY_NUM; i++) { + if (pExynosPort->semWaitPortEnable[i] != NULL) + Exynos_OSAL_SemaphorePost(pExynosPort->semWaitPortEnable[i]); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_PortEnableProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i, cnt; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + cnt = (nPortIndex == ALL_PORT_INDEX)? ALL_PORT_NUM:1; + for (i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + pExynosPort = &(pExynosComponent->pExynosPort[nIndex]); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Enable %s Port", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + + if (CHECK_PORT_POPULATED(pExynosPort)) { + Exynos_OMX_SendEventCommand(pExynosComponent, + ((nIndex == INPUT_PORT_INDEX)? EVENT_CMD_ENABLE_INPUT_PORT:EVENT_CMD_ENABLE_OUTPUT_PORT), + NULL); + } + } + +EXIT: + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + + if ((pExynosComponent != NULL) && + (pExynosComponent->pCallbacks != NULL)) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_EmptyThisBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + OMX_U32 i = 0; + OMX_BOOL bFindBuffer = OMX_FALSE; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pBuffer->nInputPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StateExecuting) && + (pExynosComponent->currentState != OMX_StatePause)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + if ((!CHECK_PORT_ENABLED(pExynosPort)) || + (CHECK_PORT_BEING_FLUSHED(pExynosPort) && + (!CHECK_PORT_TUNNELED(pExynosPort) || !CHECK_PORT_BUFFER_SUPPLIER(pExynosPort))) || + ((pExynosComponent->transientState == EXYNOS_OMX_TransStateExecutingToIdle) && + (CHECK_PORT_TUNNELED(pExynosPort) && !CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] enabled(%d), state(%x), tunneld(%d), supplier(%d)", pExynosComponent, __FUNCTION__, + CHECK_PORT_ENABLED(pExynosPort), pExynosPort->portState, + CHECK_PORT_TUNNELED(pExynosPort), CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + Exynos_OSAL_MutexLock(pExynosPort->hPortMutex); + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pBuffer == pExynosPort->extendBufferHeader[i].OMXBufferHeader) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_FALSE) { + pExynosPort->extendBufferHeader[i].bBufferInOMX = OMX_TRUE; + bFindBuffer = OMX_TRUE; + break; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] input buffer(%p) was already entered!", pExynosComponent, __FUNCTION__, pBuffer); + } + } + } + + if (bFindBuffer == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] EmptyThisBuffer is failed : %p", pExynosComponent, __FUNCTION__, pBuffer); + ret = OMX_ErrorBadParameter; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_CountIncrease(pExynosPort->hBufferCount, pBuffer, INPUT_PORT_INDEX); +#endif + + message = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_MESSAGE)); + if (message == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + message->type = EXYNOS_OMX_CommandEmptyBuffer; + message->param = (OMX_U32) i; + message->pCmdData = (OMX_PTR)pBuffer; + + ret = Exynos_OSAL_Queue(&pExynosPort->bufferQ, (void *)message); + if (ret != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Buffer queue failed", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + ret = Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + + if (pBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] bufferHeader(CSD):%p, nAllocLen:%d, nFilledLen:%d, nOffset:%d, nFlags:%x", + pExynosComponent, __FUNCTION__, + pBuffer, pBuffer->nAllocLen, pBuffer->nFilledLen, pBuffer->nOffset, pBuffer->nFlags); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader:%p, nAllocLen:%d, nFilledLen:%d, nOffset:%d, nFlags:%x", + pExynosComponent, __FUNCTION__, + pBuffer, pBuffer->nAllocLen, pBuffer->nFilledLen, pBuffer->nOffset, pBuffer->nFlags); + } + + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FillThisBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + OMX_U32 i = 0; + OMX_BOOL bFindBuffer = OMX_FALSE; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pBuffer->nOutputPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StateExecuting) && + (pExynosComponent->currentState != OMX_StatePause)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + if ((!CHECK_PORT_ENABLED(pExynosPort)) || + ((CHECK_PORT_BEING_FLUSHED(pExynosPort)) && + (!CHECK_PORT_TUNNELED(pExynosPort) || !CHECK_PORT_BUFFER_SUPPLIER(pExynosPort))) || + ((pExynosComponent->transientState == EXYNOS_OMX_TransStateExecutingToIdle) && + (CHECK_PORT_TUNNELED(pExynosPort) && !CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] enabled(%d), state(%x), tunneld(%d), supplier(%d)", pExynosComponent, __FUNCTION__, + CHECK_PORT_ENABLED(pExynosPort), pExynosPort->portState, + CHECK_PORT_TUNNELED(pExynosPort), CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + Exynos_OSAL_MutexLock(pExynosPort->hPortMutex); + for (i = 0; i < MAX_BUFFER_NUM; i++) { + if (pBuffer == pExynosPort->extendBufferHeader[i].OMXBufferHeader) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_FALSE) { + pExynosPort->extendBufferHeader[i].bBufferInOMX = OMX_TRUE; + bFindBuffer = OMX_TRUE; + break; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] output buffer(%p) was already entered!", pExynosComponent, __FUNCTION__, pBuffer); + } + } + } + + if (bFindBuffer == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] FillThisBuffer is failed : %p", pExynosComponent, __FUNCTION__, pBuffer); + ret = OMX_ErrorBadParameter; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_CountIncrease(pExynosPort->hBufferCount, pBuffer, OUTPUT_PORT_INDEX); +#endif + + message = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_MESSAGE)); + if (message == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + message->type = EXYNOS_OMX_CommandFillBuffer; + message->param = (OMX_U32) i; + message->pCmdData = (OMX_PTR)pBuffer; + + ret = Exynos_OSAL_Queue(&pExynosPort->bufferQ, (void *)message); + if (ret != 0) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + + ret = Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader:%p", pExynosComponent, __FUNCTION__, pBuffer); + + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FillThisBufferAgain( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + OMX_U32 i = 0; + OMX_BOOL bFindBuffer = OMX_FALSE; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pBuffer->nOutputPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StateExecuting) && + (pExynosComponent->currentState != OMX_StatePause)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + if ((!CHECK_PORT_ENABLED(pExynosPort)) || +#if 0 + (CHECK_PORT_BEING_FLUSHED(pExynosPort) && + (!CHECK_PORT_TUNNELED(pExynosPort) || !CHECK_PORT_BUFFER_SUPPLIER(pExynosPort))) || +#endif + ((pExynosComponent->transientState == EXYNOS_OMX_TransStateExecutingToIdle) && + (CHECK_PORT_TUNNELED(pExynosPort) && !CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] enabled(%d), state(%x), tunneld(%d), supplier(%d)", pExynosComponent, __FUNCTION__, + CHECK_PORT_ENABLED(pExynosPort), pExynosPort->portState, + CHECK_PORT_TUNNELED(pExynosPort), CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + Exynos_OSAL_MutexLock(pExynosPort->hPortMutex); + for (i = 0; i < MAX_BUFFER_NUM; i++) { + if (pBuffer == pExynosPort->extendBufferHeader[i].OMXBufferHeader) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_TRUE) { + bFindBuffer = OMX_TRUE; + break; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] output buffer(%p) is firstly entered!", pExynosComponent, __FUNCTION__, pBuffer); + } + } + } + + if (bFindBuffer == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] FillThisBufferAgain is failed : %p", pExynosComponent, __FUNCTION__, pBuffer); + ret = OMX_ErrorBadParameter; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + + message = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_MESSAGE)); + if (message == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + message->type = EXYNOS_OMX_CommandFillBuffer; + message->param = (OMX_U32) i; + message->pCmdData = (OMX_PTR)pBuffer; + + ret = Exynos_OSAL_Queue(&pExynosPort->bufferQ, (void *)message); + if (ret != 0) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + goto EXIT; + } + + ret = Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader:%p", pExynosComponent, __FUNCTION__, pBuffer); + + Exynos_OSAL_MutexUnlock(pExynosPort->hPortMutex); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Port_Constructor(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_BASEPORT *pExynosInputPort = NULL; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = NULL; + int i = 0, j = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x) Line:%d", __FUNCTION__, ret, __LINE__); + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x) Line:%d", __FUNCTION__, ret, __LINE__); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + INIT_SET_SIZE_VERSION(&pExynosComponent->portParam, OMX_PORT_PARAM_TYPE); + pExynosComponent->portParam.nPorts = ALL_PORT_NUM; + pExynosComponent->portParam.nStartPortNumber = INPUT_PORT_INDEX; + + pExynosPort = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BASEPORT) * ALL_PORT_NUM); + if (pExynosPort == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort, 0, sizeof(EXYNOS_OMX_BASEPORT) * ALL_PORT_NUM); + pExynosComponent->pExynosPort = pExynosPort; + + /* Input Port */ + pExynosInputPort = &pExynosPort[INPUT_PORT_INDEX]; + + Exynos_OSAL_QueueCreate(&pExynosInputPort->bufferQ, MAX_QUEUE_ELEMENTS); + + Exynos_OSAL_QueueCreate(&pExynosInputPort->HdrDynamicInfoQ, MAX_QUEUE_ELEMENTS); + + pExynosInputPort->extendBufferHeader = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + if (pExynosInputPort->extendBufferHeader == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosInputPort->extendBufferHeader, 0, sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + + pExynosInputPort->bufferStateAllocate = Exynos_OSAL_Malloc(sizeof(OMX_U32) * MAX_BUFFER_NUM); + if (pExynosInputPort->bufferStateAllocate == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosInputPort->bufferStateAllocate, 0, sizeof(OMX_U32) * MAX_BUFFER_NUM); + + pExynosInputPort->bufferSemID = NULL; + pExynosInputPort->assignedBufferNum = 0; + pExynosInputPort->portState = EXYNOS_OMX_PortStateLoaded; + pExynosInputPort->tunneledComponent = NULL; + pExynosInputPort->tunneledPort = 0; + pExynosInputPort->tunnelBufferNum = 0; + pExynosInputPort->bufferSupplier = OMX_BufferSupplyUnspecified; + pExynosInputPort->tunnelFlags = 0; + pExynosInputPort->supportFormat = NULL; + pExynosInputPort->bNeedContigMem = OMX_FALSE; + pExynosInputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + + for (i = 0; i < ALL_WAY_NUM; i++) { + ret = Exynos_OSAL_SemaphoreCreate(&(pExynosInputPort->semWaitPortEnable[i])); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SemaphoreCreate (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + } + + INIT_SET_SIZE_VERSION(&pExynosInputPort->portDefinition, OMX_PARAM_PORTDEFINITIONTYPE); + pExynosInputPort->portDefinition.nPortIndex = INPUT_PORT_INDEX; + pExynosInputPort->portDefinition.eDir = OMX_DirInput; + pExynosInputPort->portDefinition.nBufferCountActual = 0; + pExynosInputPort->portDefinition.nBufferCountMin = 0; + pExynosInputPort->portDefinition.nBufferSize = 0; + pExynosInputPort->portDefinition.bEnabled = OMX_FALSE; + pExynosInputPort->portDefinition.bPopulated = OMX_FALSE; + pExynosInputPort->portDefinition.eDomain = OMX_PortDomainMax; + pExynosInputPort->portDefinition.bBuffersContiguous = OMX_FALSE; + pExynosInputPort->portDefinition.nBufferAlignment = 0; + pExynosInputPort->markType.hMarkTargetComponent = NULL; + pExynosInputPort->markType.pMarkData = NULL; + pExynosInputPort->exceptionFlag = GENERAL_STATE; + pExynosInputPort->bForceUseNonCompFormat = OMX_FALSE; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_CountCreate(&pExynosInputPort->hBufferCount); +#endif + + /* Output Port */ + pExynosOutputPort = &pExynosPort[OUTPUT_PORT_INDEX]; + + Exynos_OSAL_QueueCreate(&pExynosOutputPort->bufferQ, MAX_QUEUE_ELEMENTS); /* For in case of "Output Buffer Share", MAX ELEMENTS(DPB + EDPB) */ + + Exynos_OSAL_QueueCreate(&pExynosOutputPort->HdrDynamicInfoQ, MAX_QUEUE_ELEMENTS); + + pExynosOutputPort->extendBufferHeader = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + if (pExynosOutputPort->extendBufferHeader == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosOutputPort->extendBufferHeader, 0, sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + + pExynosOutputPort->bufferStateAllocate = Exynos_OSAL_Malloc(sizeof(OMX_U32) * MAX_BUFFER_NUM); + if (pExynosOutputPort->bufferStateAllocate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosOutputPort->bufferStateAllocate, 0, sizeof(OMX_U32) * MAX_BUFFER_NUM); + + pExynosOutputPort->bufferSemID = NULL; + pExynosOutputPort->assignedBufferNum = 0; + pExynosOutputPort->portState = EXYNOS_OMX_PortStateLoaded; + pExynosOutputPort->tunneledComponent = NULL; + pExynosOutputPort->tunneledPort = 0; + pExynosOutputPort->tunnelBufferNum = 0; + pExynosOutputPort->bufferSupplier = OMX_BufferSupplyUnspecified; + pExynosOutputPort->tunnelFlags = 0; + pExynosOutputPort->supportFormat = NULL; + pExynosOutputPort->bNeedContigMem = OMX_FALSE; + pExynosOutputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + + for (i = 0; i < ALL_WAY_NUM; i++) { + ret = Exynos_OSAL_SemaphoreCreate(&(pExynosOutputPort->semWaitPortEnable[i])); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SemaphoreCreate (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + } + + INIT_SET_SIZE_VERSION(&pExynosOutputPort->portDefinition, OMX_PARAM_PORTDEFINITIONTYPE); + pExynosOutputPort->portDefinition.nPortIndex = OUTPUT_PORT_INDEX; + pExynosOutputPort->portDefinition.eDir = OMX_DirOutput; + pExynosOutputPort->portDefinition.nBufferCountActual = 0; + pExynosOutputPort->portDefinition.nBufferCountMin = 0; + pExynosOutputPort->portDefinition.nBufferSize = 0; + pExynosOutputPort->portDefinition.bEnabled = OMX_FALSE; + pExynosOutputPort->portDefinition.bPopulated = OMX_FALSE; + pExynosOutputPort->portDefinition.eDomain = OMX_PortDomainMax; + pExynosOutputPort->portDefinition.bBuffersContiguous = OMX_FALSE; + pExynosOutputPort->portDefinition.nBufferAlignment = 0; + pExynosOutputPort->markType.hMarkTargetComponent = NULL; + pExynosOutputPort->markType.pMarkData = NULL; + pExynosOutputPort->exceptionFlag = GENERAL_STATE; + pExynosOutputPort->bForceUseNonCompFormat = OMX_FALSE; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_CountCreate(&pExynosOutputPort->hBufferCount); +#endif + + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.startTimeStamp = 0; + pExynosComponent->checkTimeStamp.nStartFlags = 0x0; + + pOMXComponent->EmptyThisBuffer = &Exynos_OMX_EmptyThisBuffer; + pOMXComponent->FillThisBuffer = &Exynos_OMX_FillThisBuffer; + + ret = OMX_ErrorNone; + +EXIT: + if ((ret != OMX_ErrorNone) && + (pExynosComponent != NULL) && + (pExynosComponent->pExynosPort != NULL)) { + for (i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_CountTerminate(&pExynosPort->hBufferCount); +#endif + for (j = 0; j < ALL_WAY_NUM; j++) { + Exynos_OSAL_SemaphoreTerminate(pExynosPort->semWaitPortEnable[j]); + pExynosPort->semWaitPortEnable[j] = NULL; + } + + Exynos_OSAL_Free(pExynosPort->bufferStateAllocate); + pExynosPort->bufferStateAllocate = NULL; + Exynos_OSAL_Free(pExynosPort->extendBufferHeader); + pExynosPort->extendBufferHeader = NULL; + + Exynos_OSAL_QueueTerminate(&pExynosPort->bufferQ); + } + + Exynos_OSAL_Free(pExynosComponent->pExynosPort); + pExynosComponent->pExynosPort = NULL; + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Port_Destructor(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + int i = 0, j = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + for (i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_CountTerminate(&pExynosPort->hBufferCount); +#endif + + for (j = 0; j < ALL_WAY_NUM; j++) { + Exynos_OSAL_SemaphoreTerminate(pExynosPort->semWaitPortEnable[j]); + pExynosPort->semWaitPortEnable[j] = NULL; + } + + Exynos_OSAL_Free(pExynosPort->bufferStateAllocate); + pExynosPort->bufferStateAllocate = NULL; + Exynos_OSAL_Free(pExynosPort->extendBufferHeader); + pExynosPort->extendBufferHeader = NULL; + + Exynos_OSAL_QueueTerminate(&pExynosPort->bufferQ); + Exynos_OSAL_QueueTerminate(&pExynosPort->HdrDynamicInfoQ); + } + + Exynos_OSAL_Free(pExynosComponent->pExynosPort); + pExynosComponent->pExynosPort = NULL; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_ResetDataBuffer(EXYNOS_OMX_DATABUFFER *pDataBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pDataBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDataBuffer->dataValid = OMX_FALSE; + pDataBuffer->dataLen = 0; + pDataBuffer->remainDataLen = 0; + pDataBuffer->usedDataLen = 0; + pDataBuffer->bufferHeader = NULL; + pDataBuffer->nFlags = 0; + pDataBuffer->timeStamp = 0; + pDataBuffer->pPrivate = NULL; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_ResetCodecData(EXYNOS_OMX_DATA *pData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + /* caution: nPlanes in buffer structure might be used all times */ + Exynos_OSAL_Memset(&(pData->buffer.fd), 0, sizeof(pData->buffer.fd)); + Exynos_OSAL_Memset(&(pData->buffer.addr), 0, sizeof(pData->buffer.addr)); + + pData->dataLen = 0; + pData->usedDataLen = 0; + pData->remainDataLen = 0; + pData->nFlags = 0; + pData->timeStamp = 0; + pData->pPrivate = NULL; + pData->bufferHeader = NULL; + +EXIT: + return ret; +} + +int Exynos_GetPlaneFromPort(EXYNOS_OMX_BASEPORT *pPort) +{ + int ret = 0; + + if (pPort == NULL) + goto EXIT; + + ret = pPort->processData.buffer.nPlanes; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_SetPlaneToPort(EXYNOS_OMX_BASEPORT *pPort, int nPlaneNum) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pPort == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pPort->processData.buffer.nPlanes = nPlaneNum; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_ResetImgCropInfo( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + OMX_S32 maxPortNum = 0; + int i, j; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + maxPortNum = (OMX_S32)pExynosComponent->portParam.nPorts; + + if ((nPortIndex < 0) || + (nPortIndex > maxPortNum)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == maxPortNum) { + for (i = 0; i < maxPortNum; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + for (j = 0; j < IMG_CROP_PORT_MAX; j++) { + pExynosPort->cropRectangle[j].nTop = 0; + pExynosPort->cropRectangle[j].nLeft = 0; + pExynosPort->cropRectangle[j].nWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->cropRectangle[j].nHeight = DEFAULT_FRAME_HEIGHT; + } + + pExynosPort->bUseImgCrop[IMG_CROP_INPUT_PORT] = OMX_FALSE; + pExynosPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] = OMX_FALSE; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + for (j = 0; j < IMG_CROP_PORT_MAX; j++) { + pExynosPort->cropRectangle[j].nTop = 0; + pExynosPort->cropRectangle[j].nLeft = 0; + pExynosPort->cropRectangle[j].nWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->cropRectangle[j].nHeight = DEFAULT_FRAME_HEIGHT; + } + + pExynosPort->bUseImgCrop[IMG_CROP_INPUT_PORT] = OMX_FALSE; + pExynosPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] = OMX_FALSE; + } + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/common/Exynos_OMX_Baseport.h b/openmax/component/common/Exynos_OMX_Baseport.h new file mode 100644 index 0000000..3a0197d --- /dev/null +++ b/openmax/component/common/Exynos_OMX_Baseport.h @@ -0,0 +1,242 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Baseport.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.5.0 + * @history + * 2012.02.20 : Create + * 2017.08.03 : Change event handling + */ + +#ifndef EXYNOS_OMX_BASE_PORT +#define EXYNOS_OMX_BASE_PORT + +#include "OMX_Component.h" +#include "Exynos_OMX_Def.h" +#include "Exynos_OSAL_Queue.h" +#include "Exynos_OMX_Def.h" + +#ifdef PERFORMANCE_DEBUG +#include +#endif + +#define BUFFER_STATE_ALLOCATED (1 << 0) +#define BUFFER_STATE_ASSIGNED (1 << 1) +#define HEADER_STATE_ALLOCATED (1 << 2) +#define BUFFER_STATE_FREE 0 + +#define DEFAULT_FRAME_WIDTH 176 +#define DEFAULT_FRAME_HEIGHT 144 + +#define MAX_BUFFER_NUM 40 + +#define INPUT_PORT_INDEX 0 +#define OUTPUT_PORT_INDEX 1 +#define ALL_PORT_INDEX -1 +#define ALL_PORT_NUM 2 + +#define INPUT_WAY_INDEX 0 +#define OUTPUT_WAY_INDEX 1 +#define ALL_WAY_NUM 2 + +typedef struct _EXYNOS_OMX_BUFFERHEADERTYPE +{ + OMX_BUFFERHEADERTYPE *OMXBufferHeader; + OMX_BOOL bBufferInOMX; + OMX_HANDLETYPE ANBHandle; + void *pYUVBuf[MAX_BUFFER_PLANE]; + unsigned long buf_fd[MAX_BUFFER_PLANE]; +} EXYNOS_OMX_BUFFERHEADERTYPE; + +typedef struct _EXYNOS_OMX_DATABUFFER +{ + OMX_HANDLETYPE bufferMutex; + OMX_BUFFERHEADERTYPE* bufferHeader; + OMX_BOOL dataValid; + OMX_U32 allocSize; + OMX_U32 dataLen; + OMX_U32 usedDataLen; + OMX_U32 remainDataLen; + OMX_U32 nFlags; + OMX_TICKS timeStamp; + OMX_PTR pPrivate; +} EXYNOS_OMX_DATABUFFER; + +typedef void* CODEC_EXTRA_BUFFERINFO; + +typedef struct _EXYNOS_OMX_MULTIPLANE_BUFFER +{ + OMX_U32 nPlanes; + unsigned long fd[MAX_BUFFER_PLANE]; + OMX_PTR addr[MAX_BUFFER_PLANE]; + OMX_COLOR_FORMATTYPE eColorFormat; +} EXYNOS_OMX_MULTIPLANE_BUFFER; + +typedef struct _EXYNOS_OMX_DATA +{ + EXYNOS_OMX_MULTIPLANE_BUFFER buffer; + OMX_U32 allocSize; + OMX_U32 dataLen; + OMX_U32 usedDataLen; + OMX_U32 remainDataLen; + OMX_U32 nFlags; + OMX_TICKS timeStamp; + OMX_PTR pPrivate; + CODEC_EXTRA_BUFFERINFO extInfo; + + /* For Share Buffer */ + OMX_BUFFERHEADERTYPE *bufferHeader; +} EXYNOS_OMX_DATA; + +typedef struct _EXYNOS_OMX_WAY1_PORT_DATABUFFER +{ + EXYNOS_OMX_DATABUFFER dataBuffer; +} EXYNOS_OMX_PORT_1WAY_DATABUFFER; + +typedef struct _EXYNOS_OMX_WAY2_PORT_DATABUFFER +{ + EXYNOS_OMX_DATABUFFER inputDataBuffer; + EXYNOS_OMX_DATABUFFER outputDataBuffer; +} EXYNOS_OMX_PORT_2WAY_DATABUFFER; + +typedef enum _EXYNOS_OMX_PORT_WAY_TYPE +{ + WAY1_PORT = 0x00, + WAY2_PORT, +} EXYNOS_OMX_PORT_WAY_TYPE; + +typedef enum _EXYNOS_OMX_EXCEPTION_STATE +{ + GENERAL_STATE = 0x00, + NEED_PORT_FLUSH, + NEED_PORT_DISABLE, + INVALID_STATE, +} EXYNOS_OMX_EXCEPTION_STATE; + +typedef enum _EXYNOS_OMX_PLANE +{ + ONE_PLANE = 0x01, + TWO_PLANE = 0x02, + THREE_PLANE = 0x03, +/* + ANB_START_PLANE = 0x10, + ANB_ONE_PLANE = 0x11, + ANB_TWO_PLANE = 0x12, + ANB_THREE_PLANE = 0x13, +*/ +} EXYNOS_OMX_PLANE; + +typedef struct _EXYNOS_OMX_BASEPORT +{ + EXYNOS_OMX_BUFFERHEADERTYPE *extendBufferHeader; + OMX_U32 *bufferStateAllocate; + OMX_PARAM_PORTDEFINITIONTYPE portDefinition; + OMX_HANDLETYPE bufferSemID; + EXYNOS_QUEUE bufferQ; + EXYNOS_QUEUE HdrDynamicInfoQ; + OMX_S32 assignedBufferNum; + EXYNOS_OMX_PORT_STATETYPE portState; + OMX_HANDLETYPE semWaitPortEnable[ALL_WAY_NUM]; + + OMX_MARKTYPE markType; + + OMX_BOOL bUseImgCrop[IMG_CROP_PORT_MAX]; + OMX_CONFIG_RECTTYPE cropRectangle[IMG_CROP_PORT_MAX]; + + /* Tunnel Info */ + OMX_HANDLETYPE tunneledComponent; + OMX_U32 tunneledPort; + OMX_U32 tunnelBufferNum; + OMX_BUFFERSUPPLIERTYPE bufferSupplier; + OMX_U32 tunnelFlags; + + OMX_COLOR_FORMATTYPE *supportFormat; + EXYNOS_METADATA_TYPE eMetaDataType; + OMX_BOOL bNeedContigMem; /* contiguous memory : WFD(HDCP) */ + PLANE_TYPE ePlaneType; + + EXYNOS_OMX_BUFFERPROCESS_TYPE bufferProcessType; + EXYNOS_OMX_PORT_WAY_TYPE portWayType; + OMX_HANDLETYPE codecSemID; + EXYNOS_QUEUE codecBufferQ; + + OMX_HANDLETYPE pauseEvent; + + /* Buffer */ + union { + EXYNOS_OMX_PORT_1WAY_DATABUFFER port1WayDataBuffer; + EXYNOS_OMX_PORT_2WAY_DATABUFFER port2WayDataBuffer; + } way; + + /* Data */ + EXYNOS_OMX_DATA processData; + + EXYNOS_OMX_VIDEO_HDRSTATICINFO HDRStaticInfo; + EXYNOS_OMX_VIDEO_COLORASPECTS ColorAspects; + + OMX_HANDLETYPE hPortMutex; + EXYNOS_OMX_EXCEPTION_STATE exceptionFlag; + + OMX_TICKS latestTimeStamp; + + /* Protecting S/W Encoder uses SBWC by ConsumerUsage */ + OMX_BOOL bForceUseNonCompFormat; + +#ifdef PERFORMANCE_DEBUG + /* For performance debug */ + OMX_HANDLETYPE hBufferCount; +#endif +} EXYNOS_OMX_BASEPORT; + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OMX_InputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE *bufferHeader); +OMX_ERRORTYPE Exynos_OMX_OutputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE *bufferHeader); + +OMX_ERRORTYPE Exynos_OMX_BufferFlushProcess(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex, OMX_BOOL bEvent); + +OMX_ERRORTYPE Exynos_OMX_DisablePort(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_PortDisableProcess(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_EnablePort(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_PortEnableProcess(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex); + +OMX_ERRORTYPE Exynos_OMX_FillThisBufferAgain(OMX_HANDLETYPE hComponent, OMX_BUFFERHEADERTYPE *pBuffer); + +OMX_ERRORTYPE Exynos_OMX_Port_Constructor(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_Port_Destructor(OMX_HANDLETYPE hComponent); + +OMX_ERRORTYPE Exynos_ResetDataBuffer(EXYNOS_OMX_DATABUFFER *pDataBuffer); +OMX_ERRORTYPE Exynos_ResetCodecData(EXYNOS_OMX_DATA *pData); + +int Exynos_GetPlaneFromPort(EXYNOS_OMX_BASEPORT *pPort); +OMX_ERRORTYPE Exynos_SetPlaneToPort(EXYNOS_OMX_BASEPORT *pPort, int nPlaneNum); + +OMX_ERRORTYPE Exynos_ResetImgCropInfo(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex); + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/openmax/component/common/Exynos_OMX_Resourcemanager.c b/openmax/component/common/Exynos_OMX_Resourcemanager.c new file mode 100644 index 0000000..78491fe --- /dev/null +++ b/openmax/component/common/Exynos_OMX_Resourcemanager.c @@ -0,0 +1,584 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Resourcemanager.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Def.h" +#include "Exynos_OMX_Resourcemanager.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_Mutex.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_RM" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +#define MAX_RESOURCE_VIDEO_DEC RESOURCE_VIDEO_DEC +#define MAX_RESOURCE_VIDEO_ENC RESOURCE_VIDEO_ENC +#define MAX_RESOURCE_AUDIO_DEC RESOURCE_AUDIO_DEC +#define MAX_RESOURCE_VIDEO_SECURE 2 +/* Add new resource block */ + +typedef enum _EXYNOS_OMX_RESOURCE +{ + VIDEO_DEC, + VIDEO_ENC, + AUDIO_DEC, + VIDEO_SECURE, + /* Add new resource block */ + RESOURCE_MAX +} EXYNOS_OMX_RESOURCE; + +typedef struct _EXYNOS_OMX_RM_COMPONENT_LIST +{ + OMX_COMPONENTTYPE *pOMXStandComp; + OMX_U32 groupPriority; + struct _EXYNOS_OMX_RM_COMPONENT_LIST *pNext; +} EXYNOS_OMX_RM_COMPONENT_LIST; + +/* Max allowable scheduler component instance */ +static EXYNOS_OMX_RM_COMPONENT_LIST *gpRMList[RESOURCE_MAX]; +static EXYNOS_OMX_RM_COMPONENT_LIST *gpRMWaitList[RESOURCE_MAX]; +static OMX_HANDLETYPE ghVideoRMComponentListMutex = NULL; + +EXYNOS_OMX_RM_COMPONENT_LIST *getRMList( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + EXYNOS_OMX_RM_COMPONENT_LIST *pRMList[], + int *pMaxResource) +{ + EXYNOS_OMX_RM_COMPONENT_LIST *ret = NULL; + + if (pExynosComponent == NULL) + goto EXIT; + + switch (pExynosComponent->codecType) { + case HW_VIDEO_DEC_CODEC: + ret = pRMList[VIDEO_DEC]; + if (pMaxResource != NULL) + *pMaxResource = MAX_RESOURCE_VIDEO_DEC; + break; + case HW_VIDEO_ENC_CODEC: + ret = pRMList[VIDEO_ENC]; + if (pMaxResource != NULL) + *pMaxResource = MAX_RESOURCE_VIDEO_ENC; + break; + case HW_VIDEO_DEC_SECURE_CODEC: + case HW_VIDEO_ENC_SECURE_CODEC: + ret = pRMList[VIDEO_SECURE]; + if (pMaxResource != NULL) { + *pMaxResource = MAX_RESOURCE_VIDEO_SECURE; +#ifdef USE_SINGLE_DRM + *pMaxResource = 1; +#endif + } + break; + case HW_AUDIO_DEC_CODEC: + ret = pRMList[AUDIO_DEC]; + if (pMaxResource != NULL) + *pMaxResource = MAX_RESOURCE_AUDIO_DEC; + break; + /* Add new resource block */ + default: + ret = NULL; + if (pMaxResource != NULL) + *pMaxResource = 0; + break; + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE setRMList( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + EXYNOS_OMX_RM_COMPONENT_LIST *pRMList[], + EXYNOS_OMX_RM_COMPONENT_LIST *pRMComponentList) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + switch (pExynosComponent->codecType) { + case HW_VIDEO_DEC_CODEC: + pRMList[VIDEO_DEC] = pRMComponentList; + break; + case HW_VIDEO_ENC_CODEC: + pRMList[VIDEO_ENC] = pRMComponentList; + break; + case HW_VIDEO_DEC_SECURE_CODEC: + case HW_VIDEO_ENC_SECURE_CODEC: + pRMList[VIDEO_SECURE] = pRMComponentList; + break; + case HW_AUDIO_DEC_CODEC: + pRMList[AUDIO_DEC] = pRMComponentList; + break; + /* Add new resource block */ + default: + ret = OMX_ErrorUndefined; + break; + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE addElementList( + EXYNOS_OMX_RM_COMPONENT_LIST **ppList, + OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_RM_COMPONENT_LIST *pTempComp = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (*ppList != NULL) { + pTempComp = *ppList; + while (pTempComp->pNext != NULL) { + pTempComp = pTempComp->pNext; + } + + pTempComp->pNext = (EXYNOS_OMX_RM_COMPONENT_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_RM_COMPONENT_LIST)); + if (pTempComp->pNext == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ((EXYNOS_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->pNext = NULL; + ((EXYNOS_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->pOMXStandComp = pOMXComponent; + ((EXYNOS_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->groupPriority = pExynosComponent->compPriority.nGroupPriority; + goto EXIT; + } else { + *ppList = (EXYNOS_OMX_RM_COMPONENT_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_RM_COMPONENT_LIST)); + if (*ppList == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pTempComp = *ppList; + pTempComp->pNext = NULL; + pTempComp->pOMXStandComp = pOMXComponent; + pTempComp->groupPriority = pExynosComponent->compPriority.nGroupPriority; + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE removeElementList( + EXYNOS_OMX_RM_COMPONENT_LIST **ppList, + OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_RM_COMPONENT_LIST *pCurrComp = NULL; + EXYNOS_OMX_RM_COMPONENT_LIST *pPrevComp = NULL; + OMX_BOOL bDetectComp = OMX_FALSE; + + if (*ppList == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pCurrComp = *ppList; + while (pCurrComp != NULL) { + if (pCurrComp->pOMXStandComp == pOMXComponent) { + if (*ppList == pCurrComp) { + *ppList = pCurrComp->pNext; + Exynos_OSAL_Free(pCurrComp); + pCurrComp = NULL; + } else { + if (pPrevComp != NULL) + pPrevComp->pNext = pCurrComp->pNext; + + Exynos_OSAL_Free(pCurrComp); + pCurrComp = NULL; + } + + bDetectComp = OMX_TRUE; + break; + } else { + pPrevComp = pCurrComp; + pCurrComp = pCurrComp->pNext; + } + } + + if (bDetectComp == OMX_FALSE) + ret = OMX_ErrorComponentNotFound; + else + ret = OMX_ErrorNone; + +EXIT: + return ret; +} + +int searchLowPriority( + EXYNOS_OMX_RM_COMPONENT_LIST *pRMComponentList, + OMX_U32 inComp_priority, + EXYNOS_OMX_RM_COMPONENT_LIST **outLowComp) +{ + int ret = 0; + EXYNOS_OMX_RM_COMPONENT_LIST *pTempComp = NULL; + EXYNOS_OMX_RM_COMPONENT_LIST *pCandidateComp = NULL; + + if (pRMComponentList == NULL) { + ret = -1; + goto EXIT; + } + + pTempComp = pRMComponentList; + *outLowComp = 0; + + while (pTempComp != NULL) { + if (pTempComp->groupPriority > inComp_priority) { + if (pCandidateComp != NULL) { + if (pCandidateComp->groupPriority < pTempComp->groupPriority) + pCandidateComp = pTempComp; + } else { + pCandidateComp = pTempComp; + } + } + + pTempComp = pTempComp->pNext; + } + + *outLowComp = pCandidateComp; + if (pCandidateComp == NULL) + ret = 0; + else + ret = 1; + +EXIT: + return ret; +} + +OMX_ERRORTYPE removeComponent(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateIdle) { + (*(pExynosComponent->pCallbacks->EventHandler))(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + OMX_ErrorResourcesLost, + 0, + NULL); + ret = OMX_SendCommand(pOMXComponent, OMX_CommandStateSet, OMX_StateLoaded, NULL); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + /* Todo */ + } + + ret = OMX_ErrorNone; + +EXIT: + return ret; +} + + +OMX_ERRORTYPE Exynos_OMX_ResourceManager_Init() +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + ret = Exynos_OSAL_MutexCreate(&ghVideoRMComponentListMutex); + + if (ret == OMX_ErrorNone) { + Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex); + Exynos_OSAL_Memset(gpRMList, 0, (sizeof(EXYNOS_OMX_RM_COMPONENT_LIST*) * RESOURCE_MAX)); + Exynos_OSAL_Memset(gpRMWaitList, 0, (sizeof(EXYNOS_OMX_RM_COMPONENT_LIST*) * RESOURCE_MAX)); + Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex); + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ResourceManager_Deinit() +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_RM_COMPONENT_LIST *pCurrComponent = NULL; + EXYNOS_OMX_RM_COMPONENT_LIST *pNextComponent = NULL; + int i = 0; + + FunctionIn(); + + Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex); + + for (i = 0; i < RESOURCE_MAX; i++) { + if (gpRMList[i]) { + pCurrComponent = gpRMList[i]; + while (pCurrComponent != NULL) { + pNextComponent = pCurrComponent->pNext; + Exynos_OSAL_Free(pCurrComponent); + pCurrComponent = pNextComponent; + } + gpRMList[i] = NULL; + } + + if (gpRMWaitList[i]) { + pCurrComponent = gpRMWaitList[i]; + while (pCurrComponent != NULL) { + pNextComponent = pCurrComponent->pNext; + Exynos_OSAL_Free(pCurrComponent); + pCurrComponent = pNextComponent; + } + gpRMWaitList[i] = NULL; + } + } + + Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex); + + Exynos_OSAL_MutexTerminate(ghVideoRMComponentListMutex); + ghVideoRMComponentListMutex = NULL; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Get_Resource(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_RM_COMPONENT_LIST *pRMComponentList = NULL; + EXYNOS_OMX_RM_COMPONENT_LIST *pComponentTemp = NULL; + EXYNOS_OMX_RM_COMPONENT_LIST *pComponentCandidate = NULL; + int numElem = 0; + int lowCompDetect = 0; + int maxResource = 0; + + FunctionIn(); + + Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex); + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pRMComponentList = getRMList(pExynosComponent, gpRMList, &maxResource); + +#ifndef USE_SECURE_WITH_NONSECURE + if ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC)) { + if (gpRMList[VIDEO_SECURE] != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s][%s] can't use secure with non-secure", + pExynosComponent, __FUNCTION__, pExynosComponent->componentName); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + if ((gpRMList[VIDEO_DEC] != NULL) || + (gpRMList[VIDEO_ENC] != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s][%s] can't use secure with non-secure", + pExynosComponent, __FUNCTION__, pExynosComponent->componentName); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } +#endif + + pComponentTemp = pRMComponentList; + if (pComponentTemp != NULL) { + while (pComponentTemp) { + numElem++; + pComponentTemp = pComponentTemp->pNext; + } + } else { + numElem = 0; + } + + if (numElem >= maxResource) { + lowCompDetect = searchLowPriority(pRMComponentList, + pExynosComponent->compPriority.nGroupPriority, + &pComponentCandidate); + if (lowCompDetect <= 0) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } else { + ret = removeComponent(pComponentCandidate->pOMXStandComp); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } else { + ret = removeElementList(&pRMComponentList, pComponentCandidate->pOMXStandComp); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = addElementList(&pRMComponentList, pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + } + } + } else { + ret = addElementList(&pRMComponentList, pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + } + + ret = setRMList(pExynosComponent, gpRMList, pRMComponentList); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = OMX_ErrorNone; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s][%s] has got a resource", pExynosComponent, __FUNCTION__, pExynosComponent->componentName); + +EXIT: + Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex); + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Release_Resource(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_RM_COMPONENT_LIST *pRMComponentList = NULL; + EXYNOS_OMX_RM_COMPONENT_LIST *pRMComponentWaitList = NULL; + EXYNOS_OMX_RM_COMPONENT_LIST *pComponentTemp = NULL; + OMX_COMPONENTTYPE *pOMXWaitComponent = NULL; + int numElem = 0; + + FunctionIn(); + + Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex); + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pRMComponentList = getRMList(pExynosComponent, gpRMList, NULL); + if (pRMComponentList == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + ret = removeElementList(&pRMComponentList, pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = setRMList(pExynosComponent, gpRMList, pRMComponentList); + if (ret != OMX_ErrorNone) + goto EXIT; + + pRMComponentWaitList = getRMList(pExynosComponent, gpRMWaitList, NULL); + pComponentTemp = pRMComponentWaitList; + + while (pComponentTemp) { + numElem++; + pComponentTemp = pComponentTemp->pNext; + } + + if (numElem > 0) { + pOMXWaitComponent = pRMComponentWaitList->pOMXStandComp; + ret = removeElementList(&pRMComponentWaitList, pOMXWaitComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = setRMList(pExynosComponent, gpRMWaitList, pRMComponentWaitList); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL); + if (ret != OMX_ErrorNone) + goto EXIT; + } + +EXIT: + Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex); + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_In_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_RM_COMPONENT_LIST *pRMComponentWaitList = NULL; + + FunctionIn(); + + Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex); + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pRMComponentWaitList = getRMList(pExynosComponent, gpRMWaitList, NULL); + + ret = addElementList(&pRMComponentWaitList, pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = setRMList(pExynosComponent, gpRMWaitList, pRMComponentWaitList); + +EXIT: + Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex); + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Out_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_RM_COMPONENT_LIST *pRMComponentWaitList = NULL; + + FunctionIn(); + + Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex); + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pRMComponentWaitList = getRMList(pExynosComponent, gpRMWaitList, NULL); + + ret = removeElementList(&pRMComponentWaitList, pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = setRMList(pExynosComponent, gpRMWaitList, pRMComponentWaitList); + +EXIT: + Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex); + + FunctionOut(); + + return ret; +} + diff --git a/openmax/component/common/Exynos_OMX_Resourcemanager.h b/openmax/component/common/Exynos_OMX_Resourcemanager.h new file mode 100644 index 0000000..fb896a7 --- /dev/null +++ b/openmax/component/common/Exynos_OMX_Resourcemanager.h @@ -0,0 +1,50 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Resourcemanager.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_RESOURCEMANAGER +#define EXYNOS_OMX_RESOURCEMANAGER + + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OMX_ResourceManager_Init(); +OMX_ERRORTYPE Exynos_OMX_ResourceManager_Deinit(); +OMX_ERRORTYPE Exynos_OMX_Get_Resource(OMX_COMPONENTTYPE *pOMXComponent); +OMX_ERRORTYPE Exynos_OMX_Release_Resource(OMX_COMPONENTTYPE *pOMXComponent); +OMX_ERRORTYPE Exynos_OMX_In_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent); +OMX_ERRORTYPE Exynos_OMX_Out_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/common/NOTICE b/openmax/component/common/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/common/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/dec/Android.mk b/openmax/component/video/dec/Android.mk new file mode 100644 index 0000000..a4ecf60 --- /dev/null +++ b/openmax/component/video/dec/Android.mk @@ -0,0 +1,61 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + Exynos_OMX_VdecControl.c \ + Exynos_OMX_Vdec.c + +LOCAL_MODULE := libExynosOMX_Vdec +LOCAL_ARM_MODE := arm +LOCAL_MODULE_TAGS := optional +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/dec \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +LOCAL_STATIC_LIBRARIES := libExynosVideoApi libVendorVideoApi libExynosOMX_OSAL +LOCAL_SHARED_LIBRARIES := liblog + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(EXYNOS_OMX_SUPPORT_TUNNELING), true) +LOCAL_CFLAGS += -DTUNNELING_SUPPORT +endif + +ifeq ($(BOARD_USE_SMALL_SECURE_MEMORY), true) +LOCAL_CFLAGS += -DUSE_SMALL_SECURE_MEMORY +endif + +ifeq ($(BOARD_USE_COMPRESSED_COLOR), true) +LOCAL_CFLAGS += -DUSE_COMPRESSED_COLOR +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_STATIC_LIBRARY) diff --git a/openmax/component/video/dec/Exynos_OMX_Vdec.c b/openmax/component/video/dec/Exynos_OMX_Vdec.c new file mode 100644 index 0000000..63fac01 --- /dev/null +++ b/openmax/component/video/dec/Exynos_OMX_Vdec.c @@ -0,0 +1,2102 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Vdec.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * HyeYeon Chung (hyeon.chung@samsung.com) + * Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include "Exynos_OMX_Macros.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OMX_Vdec.h" +#include "Exynos_OMX_VdecControl.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_ETC.h" + +#include "Exynos_OSAL_Platform.h" + +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VIDEO_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +void Exynos_UpdateFrameSize(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + OMX_U32 width = 0, height = 0; + + FunctionIn(); + + if ((exynosOutputPort->portDefinition.format.video.nFrameWidth != + exynosInputPort->portDefinition.format.video.nFrameWidth) || + (exynosOutputPort->portDefinition.format.video.nFrameHeight != + exynosInputPort->portDefinition.format.video.nFrameHeight) || + (exynosOutputPort->portDefinition.format.video.nStride != + exynosInputPort->portDefinition.format.video.nStride) || + (exynosOutputPort->portDefinition.format.video.nSliceHeight != + exynosInputPort->portDefinition.format.video.nSliceHeight)) { + + exynosOutputPort->portDefinition.format.video.nFrameWidth = + exynosInputPort->portDefinition.format.video.nFrameWidth; + exynosOutputPort->portDefinition.format.video.nFrameHeight = + exynosInputPort->portDefinition.format.video.nFrameHeight; + exynosOutputPort->portDefinition.format.video.nStride = + exynosInputPort->portDefinition.format.video.nStride; + exynosOutputPort->portDefinition.format.video.nSliceHeight = + exynosInputPort->portDefinition.format.video.nSliceHeight; + } + + width = exynosOutputPort->portDefinition.format.video.nStride; + height = exynosOutputPort->portDefinition.format.video.nSliceHeight; + + if (width && height) { + switch((int)exynosOutputPort->portDefinition.format.video.eColorFormat) { + case OMX_COLOR_FormatYUV420Planar: + case OMX_COLOR_FormatYUV420SemiPlanar: + case OMX_SEC_COLOR_FormatNV12Tiled: + case OMX_SEC_COLOR_FormatYVU420Planar: + case OMX_SEC_COLOR_FormatNV21Linear: + exynosOutputPort->portDefinition.nBufferSize = (ALIGN(width, 16) * ALIGN(height, 16) * 3) / 2; + break; + case OMX_COLOR_FormatYUV420Planar16: /* 10bit format */ + exynosOutputPort->portDefinition.nBufferSize = (ALIGN(width * 2, 16) * ALIGN(height, 16) * 3) / 2; + break; + case OMX_COLOR_Format32bitARGB8888: + exynosOutputPort->portDefinition.format.video.nStride = exynosInputPort->portDefinition.format.video.nStride * 4; + exynosOutputPort->portDefinition.nBufferSize = ALIGN(width, 16) * ALIGN(height, 16) * 4; + break; + case OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC: + case OMX_SEC_COLOR_FormatYVU420SemiPlanarSBWC: + exynosOutputPort->portDefinition.nBufferSize = SBWC_8B_Y_SIZE(width, height) + SBWC_8B_Y_HEADER_SIZE(width, height) + + SBWC_8B_CBCR_SIZE(width, height) + SBWC_8B_CBCR_HEADER_SIZE(width, height); + break; + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC: + case OMX_SEC_COLOR_Format10bitYVU420SemiPlanarSBWC: + exynosOutputPort->portDefinition.nBufferSize = SBWC_10B_Y_SIZE(width, height) + SBWC_10B_Y_HEADER_SIZE(width, height) + + SBWC_10B_CBCR_SIZE(width, height) + SBWC_10B_CBCR_HEADER_SIZE(width, height); + break; + default: + exynosOutputPort->portDefinition.nBufferSize = ALIGN(width, 16) * ALIGN(height, 16) * 2; + break; + } + } + + FunctionOut(); + + return; +} + +void Exynos_Output_SetSupportFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + if ((pVideoDec == NULL) || (pOutputPort == NULL)) + return ; + + if (pOutputPort->supportFormat != NULL) { + OMX_BOOL ret = OMX_FALSE; + int nLastIndex = OUTPUT_PORT_SUPPORTFORMAT_DEFAULT_NUM; + int i; + + /* Default supported formats */ + /* Customer wants OMX_COLOR_FormatYUV420SemiPlanar in the default colors format. */ + /* But, Google wants OMX_COLOR_FormatYUV420Planar in the default colors format. */ + /* Google's Videoeditor uses OMX_COLOR_FormatYUV420Planar(YV12) in the default colors format. */ + /* Therefore, only when you load the OpenMAX IL component by the customer name, */ + /* to change the default OMX_COLOR_FormatYUV420SemiPlanar color format. */ + /* It is determined by case-sensitive. */ + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) != OMX_TRUE) { + /* Google GED & S.LSI Component, for video editor*/ + pOutputPort->supportFormat[0] = OMX_COLOR_FormatYUV420Planar; + pOutputPort->supportFormat[1] = OMX_COLOR_FormatYUV420SemiPlanar; + } else { + /* Customer Component*/ + pOutputPort->supportFormat[0] = OMX_COLOR_FormatYUV420SemiPlanar; + pOutputPort->supportFormat[1] = OMX_COLOR_FormatYUV420Planar; + } + pOutputPort->supportFormat[2] = OMX_COLOR_Format32bitARGB8888; + + /* add extra formats, if It is supported by H/W. (CSC doesn't exist) */ + /* OMX_SEC_COLOR_FormatNV12Tiled */ + ret = pVideoDec->exynos_codec_checkFormatSupport(pExynosComponent, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled); + if (ret == OMX_TRUE) + pOutputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled; + + /* OMX_SEC_COLOR_FormatYVU420Planar */ + ret = pVideoDec->exynos_codec_checkFormatSupport(pExynosComponent, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420Planar); + if (ret == OMX_TRUE) + pOutputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420Planar; + + /* OMX_SEC_COLOR_FormatNV21Linear */ + ret = pVideoDec->exynos_codec_checkFormatSupport(pExynosComponent, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV21Linear); + if (ret == OMX_TRUE) + pOutputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV21Linear; + + /* OMX_COLOR_FormatYUV420Planar16 */ + ret = pVideoDec->exynos_codec_checkFormatSupport(pExynosComponent, (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatYUV420Planar16); + if (ret == OMX_TRUE) + pOutputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatYUV420Planar16; + + /* OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC */ + ret = pVideoDec->exynos_codec_checkFormatSupport(pExynosComponent, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC); + if (ret == OMX_TRUE) + pOutputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC; + + for (i = 0; i < nLastIndex; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] Supported Format[%d] : 0x%x", + pExynosComponent, __FUNCTION__, i, pOutputPort->supportFormat[i]); + } + + pOutputPort->supportFormat[nLastIndex] = OMX_COLOR_FormatUnused; + } + + return ; +} + +void Exynos_Free_CodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + CODEC_DEC_BUFFER **ppCodecBuffer = NULL; + + int nBufferCnt = 0, nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]); + nBufferCnt = MFC_INPUT_BUFFER_NUM_MAX; + } else { + ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]); + nBufferCnt = MFC_OUTPUT_BUFFER_NUM_MAX; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + for (i = 0; i < nBufferCnt; i++) { + if (ppCodecBuffer[i] != NULL) { + for (j = 0; j < nPlaneCnt; j++) { + if (ppCodecBuffer[i]->pVirAddr[j] != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] %s codec buffer[%d][%d] : %d", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + i, j, ppCodecBuffer[i]->fd[j]); + Exynos_OSAL_SharedMemory_Free(pVideoDec->hSharedMemory, ppCodecBuffer[i]->pVirAddr[j]); + } + } + + Exynos_OSAL_Free(ppCodecBuffer[i]); + ppCodecBuffer[i] = NULL; + } + } + + FunctionOut(); +} + +OMX_ERRORTYPE Exynos_Allocate_CodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt, + unsigned int nAllocLen[MAX_BUFFER_PLANE]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + MEMORY_TYPE eMemoryType = CACHED_MEMORY; + CODEC_DEC_BUFFER **ppCodecBuffer = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]); + } else { + ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]); +#ifdef USE_CSC_HW + eMemoryType = NORMAL_MEMORY; +#endif + } + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + eMemoryType = SECURE_MEMORY; + + for (i = 0; i < nBufferCnt; i++) { + ppCodecBuffer[i] = (CODEC_DEC_BUFFER *)Exynos_OSAL_Malloc(sizeof(CODEC_DEC_BUFFER)); + if (ppCodecBuffer[i] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(ppCodecBuffer[i], 0, sizeof(CODEC_DEC_BUFFER)); + + for (j = 0; j < nPlaneCnt; j++) { + ppCodecBuffer[i]->pVirAddr[j] = + (void *)Exynos_OSAL_SharedMemory_Alloc(pVideoDec->hSharedMemory, nAllocLen[j], eMemoryType); + if (ppCodecBuffer[i]->pVirAddr[j] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Alloc for %s codec buffer", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ppCodecBuffer[i]->fd[j] = + Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, ppCodecBuffer[i]->pVirAddr[j]); + ppCodecBuffer[i]->bufferSize[j] = nAllocLen[j]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s codec buffer[%d][%d] : %d", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + i, j, ppCodecBuffer[i]->fd[j]); + } + + ppCodecBuffer[i]->dataSize = 0; + } + + FunctionOut(); + + return OMX_ErrorNone; + +EXIT: + Exynos_Free_CodecBuffers(pOMXComponent, nPortIndex); + + FunctionOut(); + + return ret; +} + +void Exynos_SetReorderTimestamp( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 *nIndex, + OMX_TICKS timeStamp, + OMX_U32 nFlags) { + + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || (nIndex == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* find a empty slot */ + for (i = 0; i < MAX_TIMESTAMP; i++) { + if (pExynosComponent->bTimestampSlotUsed[*nIndex] == OMX_FALSE) + break; + + (*nIndex)++; + (*nIndex) %= MAX_TIMESTAMP; + } + + if (i >= MAX_TIMESTAMP) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Can not find empty slot of timestamp. Timestamp slot is full.", + pExynosComponent, __FUNCTION__); + + pExynosComponent->timeStamp[*nIndex] = timeStamp; + pExynosComponent->nFlags[*nIndex] = nFlags; + pExynosComponent->bTimestampSlotUsed[*nIndex] = OMX_TRUE; + +EXIT: + FunctionOut(); + + return; +} + +void Exynos_GetReorderTimestamp( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + EXYNOS_OMX_CURRENT_FRAME_TIMESTAMP *sCurrentTimestamp, + OMX_S32 nFrameIndex, + OMX_S32 eFrameType) { + + EXYNOS_OMX_BASEPORT *pExynosOutputPort = NULL; + int i = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || (sCurrentTimestamp == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + Exynos_OSAL_Memset(sCurrentTimestamp, 0, sizeof(EXYNOS_OMX_CURRENT_FRAME_TIMESTAMP)); + sCurrentTimestamp->timeStamp = DEFAULT_TIMESTAMP_VAL; + + for (i = 0; i < MAX_TIMESTAMP; i++) { + /* NOTE: In case of CODECCONFIG, no return any frame */ + if ((pExynosComponent->bTimestampSlotUsed[i] == OMX_TRUE) && + (pExynosComponent->nFlags[i] != (OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME))) { + + /* NOTE: In case of EOS, timestamp is not valid */ + if ((sCurrentTimestamp->timeStamp == DEFAULT_TIMESTAMP_VAL) || + ((sCurrentTimestamp->timeStamp > pExynosComponent->timeStamp[i]) && + (((pExynosComponent->nFlags[i] & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS) || + (pExynosComponent->bBehaviorEOS == OMX_TRUE))) || + ((sCurrentTimestamp->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + sCurrentTimestamp->timeStamp = pExynosComponent->timeStamp[i]; + sCurrentTimestamp->nFlags = pExynosComponent->nFlags[i]; + sCurrentTimestamp->nIndex = i; + } + } + } + + if (sCurrentTimestamp->timeStamp == DEFAULT_TIMESTAMP_VAL) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] could not find a valid timestamp", pExynosComponent, __FUNCTION__); + + /* PTS : all index is same as tag */ + /* DTS : only in case of I-Frame, the index is same as tag */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] disp_pic_frame_type: %d", pExynosComponent, __FUNCTION__, eFrameType); + if ((ExynosVideoFrameType)eFrameType & VIDEO_FRAME_I) { + /* Timestamp is weird */ + if (sCurrentTimestamp->nIndex != nFrameIndex) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Timestamp is not same in spite of I-Frame", pExynosComponent, __FUNCTION__); + + /* trust a tag index returned from D/D */ + sCurrentTimestamp->timeStamp = pExynosComponent->timeStamp[nFrameIndex]; + sCurrentTimestamp->nFlags = pExynosComponent->nFlags[nFrameIndex]; + sCurrentTimestamp->nIndex = nFrameIndex; + + /* delete past timestamps */ + for(i = 0; i < MAX_TIMESTAMP; i++) { + if ((pExynosComponent->bTimestampSlotUsed[i] == OMX_TRUE) && + ((sCurrentTimestamp->timeStamp > pExynosComponent->timeStamp[i]) && + ((pExynosComponent->nFlags[i] & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] clear an past timestamp %lld us (%.2f secs)", + pExynosComponent, __FUNCTION__, + pExynosComponent->timeStamp[i], (double)(pExynosComponent->timeStamp[i] / 1E6)); + pExynosComponent->nFlags[i] = 0x00; + pExynosComponent->bTimestampSlotUsed[i] = OMX_FALSE; + } + + if ((pExynosComponent->bTimestampSlotUsed[i] == OMX_FALSE) && + (sCurrentTimestamp->timeStamp < pExynosComponent->timeStamp[i])) { + pExynosComponent->bTimestampSlotUsed[i] = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] revive an past timestamp %lld us (%.2f secs) by I-frame sync", + pExynosComponent, __FUNCTION__, + pExynosComponent->timeStamp[i], (double)(pExynosComponent->timeStamp[i] / 1E6)); + } + } + } + + if (sCurrentTimestamp->timeStamp == DEFAULT_TIMESTAMP_VAL) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] the index of frame(%d) about I-frame is wrong", + pExynosComponent, __FUNCTION__, nFrameIndex); + + sCurrentTimestamp->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + } + + if (sCurrentTimestamp->timeStamp != DEFAULT_TIMESTAMP_VAL) { + if (pExynosOutputPort->latestTimeStamp <= sCurrentTimestamp->timeStamp) { + pExynosOutputPort->latestTimeStamp = sCurrentTimestamp->timeStamp; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] timestamp(%lld) is smaller than latest timeStamp(%lld), uses latestTimeStamp", + pExynosComponent, __FUNCTION__, + sCurrentTimestamp->timeStamp, pExynosOutputPort->latestTimeStamp); + sCurrentTimestamp->timeStamp = pExynosOutputPort->latestTimeStamp; + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] can't find a valid timestamp, uses latestTimeStamp(%lld)", + pExynosComponent, __FUNCTION__, pExynosOutputPort->latestTimeStamp); + sCurrentTimestamp->timeStamp = pExynosOutputPort->latestTimeStamp; + } + +EXIT: + FunctionOut(); + + return; +} + +OMX_BOOL Exynos_Check_BufferProcess_State(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex) +{ + OMX_BOOL ret = OMX_FALSE; + + if ((pExynosComponent == NULL) || + (pExynosComponent->pExynosPort == NULL)) + return OMX_FALSE; + + if ((pExynosComponent->currentState == OMX_StateExecuting) && + ((pExynosComponent->pExynosPort[nPortIndex].portState == EXYNOS_OMX_PortStateIdle) || + (pExynosComponent->pExynosPort[nPortIndex].portState == EXYNOS_OMX_PortStateDisabling)) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateIdleToExecuting)) { + ret = OMX_TRUE; + } else { + ret = OMX_FALSE; + } + + return ret; +} + +OMX_ERRORTYPE Exynos_ResetAllPortConfig(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + int i = 0; + + FunctionIn(); + + /* Input port */ + pInputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pInputPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pInputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pInputPort->portDefinition.format.video.nSliceHeight = 0; + pInputPort->portDefinition.format.video.pNativeRender = 0; + pInputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pInputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + + pInputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + pInputPort->portDefinition.bEnabled = OMX_TRUE; + + pInputPort->bufferProcessType = BUFFER_SHARE; + pOutputPort->eMetaDataType = METADATA_TYPE_DISABLED; + + pInputPort->portWayType = WAY2_PORT; + Exynos_SetPlaneToPort(pInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + + for (i = 0; i < IMG_CROP_PORT_MAX; i++) { + pInputPort->cropRectangle[i].nTop = 0; + pInputPort->cropRectangle[i].nLeft = 0; + pInputPort->cropRectangle[i].nWidth = DEFAULT_FRAME_WIDTH; + pInputPort->cropRectangle[i].nHeight = DEFAULT_FRAME_HEIGHT; + } + Exynos_ResetImgCropInfo(pOMXComponent, INPUT_PORT_INDEX); + + /* Output port */ + pOutputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pOutputPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pOutputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pOutputPort->portDefinition.format.video.nSliceHeight = 0; + pOutputPort->portDefinition.format.video.pNativeRender = 0; + pOutputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pOutputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; + + pOutputPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM; + pOutputPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM; + pOutputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pOutputPort->portDefinition.bEnabled = OMX_TRUE; + + pOutputPort->bufferProcessType = BUFFER_COPY; + pOutputPort->eMetaDataType = METADATA_TYPE_DISABLED; + + pOutputPort->portWayType = WAY2_PORT; + pOutputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(OMX_COLOR_FormatYUV420Planar, pOutputPort->ePlaneType)); + + for (i = 0; i < IMG_CROP_PORT_MAX; i++) { + pOutputPort->cropRectangle[i].nTop = 0; + pOutputPort->cropRectangle[i].nLeft = 0; + pOutputPort->cropRectangle[i].nWidth = DEFAULT_FRAME_WIDTH; + pOutputPort->cropRectangle[i].nHeight = DEFAULT_FRAME_HEIGHT; + } + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_CodecBufferToData( + CODEC_DEC_BUFFER *pCodecBuffer, + EXYNOS_OMX_DATA *pData, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + int i; + + if (nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pData->allocSize = 0; + pData->usedDataLen = 0; + pData->nFlags = 0; + pData->timeStamp = 0; + pData->pPrivate = pCodecBuffer; + pData->bufferHeader = NULL; + + for (i = 0; i < MAX_BUFFER_PLANE; i++) { + pData->buffer.addr[i] = pCodecBuffer->pVirAddr[i]; + pData->buffer.fd[i] = pCodecBuffer->fd[i]; + + pData->allocSize += pCodecBuffer->bufferSize[i]; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + pData->dataLen = pCodecBuffer->dataSize; + pData->remainDataLen = pCodecBuffer->dataSize; + } else { + pData->dataLen = 0; + pData->remainDataLen = 0; + } + +EXIT: + return ret; +} + +void Exynos_Wait_ProcessPause(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex) +{ + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosOMXPort = &pExynosComponent->pExynosPort[nPortIndex]; + + FunctionIn(); + + if (((pExynosComponent->currentState == OMX_StatePause) || + (pExynosComponent->currentState == OMX_StateIdle) || + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle) || + (pExynosComponent->transientState == EXYNOS_OMX_TransStateExecutingToIdle)) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateIdleToLoaded) && + (!CHECK_PORT_BEING_FLUSHED(exynosOMXPort))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port -> pause : state(0x%x), transient state(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosComponent->transientState); + Exynos_OSAL_SignalWait(pExynosComponent->pExynosPort[nPortIndex].pauseEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port -> resume : state(0x%x), transient state(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosComponent->transientState); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + Exynos_OSAL_SignalReset(pExynosComponent->pExynosPort[nPortIndex].pauseEvent); + } + +EXIT: + FunctionOut(); + + return; +} + +OMX_BOOL Exynos_CSC_OutputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + EXYNOS_OMX_DATABUFFER *pOutputUseBuffer = &(pOutputPort->way.port2WayDataBuffer.outputDataBuffer); + DECODE_CODEC_EXTRA_BUFFERINFO *pExtBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + OMX_COLOR_FORMATTYPE eColorFormat = pOutputPort->portDefinition.format.video.eColorFormat; + + void *pOutputBuf = (void *)pOutputUseBuffer->bufferHeader->pBuffer; + void *pSrcBuf[MAX_BUFFER_PLANE] = { NULL, }; + void *pDstBuf[MAX_BUFFER_PLANE] = { NULL, }; + + CSC_MEMTYPE csc_memType = CSC_MEMORY_USERPTR; + CSC_METHOD csc_method = CSC_METHOD_SW; + CSC_ERRORCODE csc_ret = CSC_ErrorNone; + unsigned int csc_src_cacheable = 1; + unsigned int csc_dst_cacheable = 1; + + EXYNOS_OMX_IMG_INFO srcImgInfo, dstImgInfo; + + FunctionIn(); + + /* choose csc method */ + csc_get_method(pVideoDec->csc_handle, &csc_method); + if (csc_method == CSC_METHOD_SW) { + if (((pVideoDec->eDataType == DATA_TYPE_10BIT) && + (eColorFormat != (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatYUV420Planar16)) || + ((pVideoDec->eDataType == DATA_TYPE_8BIT_SBWC) || + (pVideoDec->eDataType == DATA_TYPE_10BIT_SBWC))) { + csc_memType = CSC_MEMORY_DMABUF; + csc_src_cacheable = 0; + csc_dst_cacheable = 0; + + csc_method = CSC_METHOD_HW; + csc_set_method(pVideoDec->csc_handle, csc_method); + } else if (pVideoDec->exynos_codec_checkFormatSupport(pExynosComponent, eColorFormat) == OMX_TRUE) { + /* only remove stride value */ + csc_memType = CSC_MEMORY_MFC; + } + } else { + csc_memType = CSC_MEMORY_DMABUF; + csc_src_cacheable = 0; + csc_dst_cacheable = 0; + } + + /******************/ + /* get image info */ + /******************/ + /* 1. SRC : MFC OUTPUT */ + srcImgInfo.nStride = pExtBufferInfo->imageStride; + srcImgInfo.nSliceHeight = pExtBufferInfo->imageHeight; + srcImgInfo.nImageWidth = pExtBufferInfo->imageWidth; + srcImgInfo.nImageHeight = pExtBufferInfo->imageHeight; + + if (pOutputPort->bUseImgCrop[IMG_CROP_INPUT_PORT] == OMX_FALSE) { + /* read original image fully except padding data */ + srcImgInfo.nLeft = 0; + srcImgInfo.nTop = 0; + srcImgInfo.nWidth = pExtBufferInfo->imageWidth; + srcImgInfo.nHeight = pExtBufferInfo->imageHeight; + } else { + /* crop an original image */ + srcImgInfo.nLeft = pOutputPort->cropRectangle[IMG_CROP_INPUT_PORT].nLeft; + srcImgInfo.nTop = pOutputPort->cropRectangle[IMG_CROP_INPUT_PORT].nTop; + srcImgInfo.nWidth = pOutputPort->cropRectangle[IMG_CROP_INPUT_PORT].nWidth; + srcImgInfo.nHeight = pOutputPort->cropRectangle[IMG_CROP_INPUT_PORT].nHeight; + } + + /* 2. DST : OMX OUTPUT */ + dstImgInfo.nStride = pOutputPort->portDefinition.format.video.nFrameWidth; // pExtBufferInfo->imageWidth?? + dstImgInfo.nSliceHeight = pOutputPort->portDefinition.format.video.nFrameHeight; // pExtBufferInfo->imageHeight?? + dstImgInfo.nImageWidth = pExtBufferInfo->imageWidth; + dstImgInfo.nImageHeight = pExtBufferInfo->imageHeight; + + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_FALSE) { + /* write image fully */ + dstImgInfo.nLeft = 0; + dstImgInfo.nTop = 0; + dstImgInfo.nWidth = pExtBufferInfo->imageWidth; + dstImgInfo.nHeight = pExtBufferInfo->imageHeight; + } else { + /* use positioning and scaling */ + dstImgInfo.nLeft = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nLeft; + dstImgInfo.nTop = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nTop; + dstImgInfo.nWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + dstImgInfo.nHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } + + /*******************/ + /* get buffer info */ + /*******************/ + /* 1. SRC : MFC OUTPUT */ + if (csc_method == CSC_METHOD_HW) { + pSrcBuf[0] = (void *)pDstOutputData->buffer.fd[0]; + pSrcBuf[1] = (void *)pDstOutputData->buffer.fd[1]; + pSrcBuf[2] = (void *)pDstOutputData->buffer.fd[2]; + } else { + if (pOutputPort->ePlaneType == PLANE_SINGLE) { + /* single-FD. only Y addr is valid */ + int nPlaneCnt = Exynos_OSAL_GetPlaneCount(pExtBufferInfo->colorFormat, PLANE_MULTIPLE); + + pSrcBuf[0] = pDstOutputData->buffer.addr[0]; + + switch (pVideoDec->eDataType) { + case DATA_TYPE_10BIT: + if (nPlaneCnt == 2) { /* Semi-Planar : interleaved */ + pSrcBuf[1] = (void *)(((char *)pSrcBuf[0]) + GET_UV_OFFSET((srcImgInfo.nImageWidth * 2), srcImgInfo.nImageHeight)); + } else if (nPlaneCnt == 3) { /* Planar */ + pSrcBuf[1] = (void *)(((char *)pSrcBuf[0]) + GET_CB_OFFSET((srcImgInfo.nImageWidth * 2), srcImgInfo.nImageHeight)); + pSrcBuf[2] = (void *)(((char *)pSrcBuf[0]) + GET_CR_OFFSET((srcImgInfo.nImageWidth * 2), srcImgInfo.nImageHeight)); + } + break; + case DATA_TYPE_8BIT_WITH_2BIT: + if (nPlaneCnt == 2) { /* Semi-Planar : interleaved */ + pSrcBuf[1] = (void *)(((char *)pSrcBuf[0]) + GET_10B_UV_OFFSET(srcImgInfo.nImageWidth, srcImgInfo.nImageHeight)); + } else if (nPlaneCnt == 3) { /* Planar */ + pSrcBuf[1] = (void *)(((char *)pSrcBuf[0]) + GET_10B_CB_OFFSET(srcImgInfo.nImageWidth, srcImgInfo.nImageHeight)); + pSrcBuf[2] = (void *)(((char *)pSrcBuf[0]) + GET_10B_CR_OFFSET(srcImgInfo.nImageWidth, srcImgInfo.nImageHeight)); + } + break; + default: + if (nPlaneCnt == 2) { /* Semi-Planar : interleaved */ + pSrcBuf[1] = (void *)(((char *)pSrcBuf[0]) + GET_UV_OFFSET(srcImgInfo.nImageWidth, srcImgInfo.nImageHeight)); + } else if (nPlaneCnt == 3) { /* Planar */ + pSrcBuf[1] = (void *)(((char *)pSrcBuf[0]) + GET_CB_OFFSET(srcImgInfo.nImageWidth, srcImgInfo.nImageHeight)); + pSrcBuf[2] = (void *)(((char *)pSrcBuf[0]) + GET_CR_OFFSET(srcImgInfo.nImageWidth, srcImgInfo.nImageHeight)); + } + break; + } + } else { + /* multi-FD */ + pSrcBuf[0] = pDstOutputData->buffer.addr[0]; + pSrcBuf[1] = pDstOutputData->buffer.addr[1]; + pSrcBuf[2] = pDstOutputData->buffer.addr[2]; + } + } + + /* 2. DST : OMX OUTPUT */ + if (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED) { + /* 1. meta data is enabled (surface buffer) + * 1) format is not supported at HW codec + * needs CSC(Color-Space-Conversion). + */ + if (pOutputPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) { + /* graphic buffer */ + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + + OMX_ERRORTYPE err = OMX_ErrorNone; + EXYNOS_OMX_LOCK_RANGE range; + OMX_U32 stride = 0; + + range.nWidth = dstImgInfo.nStride; + range.nHeight = dstImgInfo.nSliceHeight; + range.eColorFormat = eColorFormat; + + err = Exynos_OSAL_LockMetaData(pOutputBuf, range, &stride, &bufferInfo, pOutputPort->eMetaDataType); + if (err != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to Exynos_OSAL_LockMetaData (err:0x%x)", + pExynosComponent, __FUNCTION__, err); + ret = OMX_FALSE; + goto EXIT; + } + + dstImgInfo.nStride = stride; + + /* update extra information to vendor path for renderer */ + { + ExynosVideoMeta *pMeta = (ExynosVideoMeta *)bufferInfo.addr[2]; + + if (pVideoDec->exynos_codec_updateExtraInfo != NULL) + pVideoDec->exynos_codec_updateExtraInfo(pOMXComponent, pMeta); + } + + if (csc_method == CSC_METHOD_HW) { + pDstBuf[0] = (void *)bufferInfo.fd[0]; + pDstBuf[1] = (void *)bufferInfo.fd[1]; + pDstBuf[2] = (void *)bufferInfo.fd[2]; + } else { + pDstBuf[0] = (void *)bufferInfo.addr[0]; + pDstBuf[1] = (void *)bufferInfo.addr[1]; + pDstBuf[2] = (void *)bufferInfo.addr[2]; + } + } else { + /*************/ + /* TBD */ + /*************/ + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: OMX_ErrorNotImplemented(%d)", pExynosComponent, __FUNCTION__, __LINE__); + /* OMX_ErrorNotImplemented */ + ret = OMX_FALSE; + goto EXIT; + } + } else { + /* 2. meta data is not enabled (user application format) + * 1) user application couldn't handle non-continuous data + * 2) format is not supported at HW codec + * needs CSC(Color-Space-Conversion). + */ + + if (csc_method == CSC_METHOD_HW) { + pDstBuf[0] = (void *)Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, pOutputBuf); + pDstBuf[1] = NULL; + pDstBuf[2] = NULL; + } else { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = { 0, 0, 0 }; + unsigned int nDataLen[MAX_BUFFER_PLANE] = { 0, 0, 0 }; + + Exynos_OSAL_GetPlaneSize(eColorFormat, PLANE_SINGLE_USER, dstImgInfo.nStride, dstImgInfo.nSliceHeight, nDataLen, nAllocLen); + + pDstBuf[0] = (void *)((char *)pOutputBuf); + pDstBuf[1] = (void *)((char *)pOutputBuf + nDataLen[0]); + pDstBuf[2] = (void *)((char *)pOutputBuf + nDataLen[0] + nDataLen[1]); + } + } + + /**************************/ + /* [CSC] setup image info */ + /**************************/ + if (pVideoDec->csc_set_format == OMX_FALSE) { + /********************/ + /* get color format */ + /********************/ + unsigned int csc_src_color_format = Exynos_OSAL_OMX2HALPixelFormat(pExtBufferInfo->colorFormat, pOutputPort->ePlaneType); + unsigned int csc_dst_color_format = Exynos_OSAL_OMX2HALPixelFormat(eColorFormat, PLANE_SINGLE_USER); + + if (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED) + csc_dst_color_format = Exynos_OSAL_OMX2HALPixelFormat(eColorFormat, pOutputPort->ePlaneType); + + csc_set_src_format( + pVideoDec->csc_handle, /* handle */ + srcImgInfo.nStride, /* width */ + srcImgInfo.nSliceHeight, /* height */ + srcImgInfo.nLeft, /* crop_left */ + srcImgInfo.nTop, /* crop_top */ + srcImgInfo.nWidth, /* crop_width */ + srcImgInfo.nHeight, /* crop_height */ + csc_src_color_format, /* color_format */ + csc_src_cacheable); /* cacheable */ + + csc_set_dst_format( + pVideoDec->csc_handle, /* handle */ + dstImgInfo.nStride, /* width */ + dstImgInfo.nSliceHeight, /* height */ + dstImgInfo.nLeft, /* crop_left */ + dstImgInfo.nTop, /* crop_top */ + dstImgInfo.nWidth, /* crop_width */ + dstImgInfo.nHeight, /* crop_height */ + csc_dst_color_format, /* color_format */ + csc_dst_cacheable); /* cacheable */ + + csc_set_eq_property( + pVideoDec->csc_handle, /* handle */ + CSC_EQ_MODE_USER, /* user select */ + CSC_EQ_RANGE_NARROW, /* narrow */ + CSC_EQ_COLORSPACE_SMPTE170M); /* bt.601 */ + + pVideoDec->csc_set_format = OMX_TRUE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s CSC(%x) / [SRC] resol(%dx%d), rect(%d/%d/%d/%d), format(0x%x) -> [DST] resol(%dx%d), rect(%d/%d/%d/%d), format(0x%x)", + pExynosComponent, __FUNCTION__, + (csc_method == CSC_METHOD_SW)? "SW":"HW", csc_memType, + srcImgInfo.nStride, srcImgInfo.nSliceHeight, + srcImgInfo.nLeft, srcImgInfo.nTop, srcImgInfo.nWidth, srcImgInfo.nHeight, csc_src_color_format, + dstImgInfo.nStride, dstImgInfo.nSliceHeight, + dstImgInfo.nLeft, dstImgInfo.nTop, dstImgInfo.nWidth, dstImgInfo.nHeight, csc_dst_color_format); + } + + /***************************/ + /* [CSC] setup buffer info */ + /***************************/ + csc_set_src_buffer( + pVideoDec->csc_handle, /* handle */ + pSrcBuf, + csc_memType); + csc_set_dst_buffer( + pVideoDec->csc_handle, /* handle */ + pDstBuf, + csc_memType); + + /*****************/ + /* [CSC] convert */ + /*****************/ + csc_ret = csc_convert(pVideoDec->csc_handle); + ret = (csc_ret != CSC_ErrorNone)? OMX_FALSE:OMX_TRUE; + + if (pOutputPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) + Exynos_OSAL_UnlockMetaData(pOutputBuf, pOutputPort->eMetaDataType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_BOOL Exynos_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *srcInputData) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *inputUseBuffer = &exynosInputPort->way.port2WayDataBuffer.inputDataBuffer; + + OMX_BYTE pInputStream = NULL; + OMX_U32 copySize = 0; + + FunctionIn(); + + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + if ((srcInputData->buffer.addr[0] == NULL) || + (srcInputData->pPrivate == NULL)) { + ret = OMX_FALSE; + goto EXIT; + } + } + + if (inputUseBuffer->dataValid == OMX_TRUE) { + if (exynosInputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_Shared_BufferToData(exynosInputPort, inputUseBuffer, srcInputData); + + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) { + unsigned long ionFD = 0; + OMX_PTR dataBuffer = NULL; + + if (exynosInputPort->eMetaDataType == METADATA_TYPE_HANDLE) { + if (srcInputData->buffer.fd[0] == 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] FD is invalid at %p", + pExynosComponent, __FUNCTION__, inputUseBuffer->bufferHeader); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + ret = OMX_FALSE; + goto EXIT; + } + + ionFD = srcInputData->buffer.fd[0]; + } else { + /* backward compatibility */ + ionFD = (unsigned long)srcInputData->buffer.addr[0]; + } + + dataBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoDec->hSharedMemory, ionFD); + if (dataBuffer == NULL) { + ret = OMX_FALSE; + goto EXIT; + } + + srcInputData->buffer.fd[0] = ionFD; + srcInputData->buffer.addr[0] = dataBuffer; + } + + if (exynosInputPort->eMetaDataType == METADATA_TYPE_DISABLED) { + srcInputData->buffer.fd[0] = + Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, + srcInputData->buffer.addr[0]); + } + + /* reset dataBuffer */ + Exynos_ResetDataBuffer(inputUseBuffer); + + ret = OMX_TRUE; + } else if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + pInputStream = inputUseBuffer->bufferHeader->pBuffer + inputUseBuffer->usedDataLen; + copySize = inputUseBuffer->remainDataLen; + + if (((srcInputData->allocSize) - (srcInputData->dataLen)) < copySize) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] codec buffer's remaining space(%d) is smaller than input data(%d)", + pExynosComponent, __FUNCTION__, + ((srcInputData->allocSize) - (srcInputData->dataLen)), copySize); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + ret = OMX_FALSE; + goto EXIT; + } + + if (copySize > 0) { + Exynos_OSAL_Memcpy((OMX_PTR)((char *)srcInputData->buffer.addr[0] + srcInputData->dataLen), + pInputStream, copySize); + } + + inputUseBuffer->dataLen -= copySize; + inputUseBuffer->remainDataLen -= copySize; + inputUseBuffer->usedDataLen += copySize; + + srcInputData->dataLen += copySize; + srcInputData->remainDataLen += copySize; + + srcInputData->timeStamp = inputUseBuffer->timeStamp; + srcInputData->nFlags = inputUseBuffer->nFlags; + srcInputData->bufferHeader = inputUseBuffer->bufferHeader; + + /* return OMX buffer and reset dataBuffer */ + Exynos_InputBufferReturn(pOMXComponent, inputUseBuffer); + + ret = OMX_TRUE; + } + + if ((srcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + if (srcInputData->dataLen != 0) { + pExynosComponent->bBehaviorEOS = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] behavior EOS frame", pExynosComponent, __FUNCTION__); + } + } + + if ((pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) && + ((srcInputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG) != OMX_BUFFERFLAG_CODECCONFIG)) { + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_TRUE; + pExynosComponent->checkTimeStamp.startTimeStamp = srcInputData->timeStamp; + pOutputPort->latestTimeStamp = srcInputData->timeStamp; // for reordering timestamp mode + pExynosComponent->checkTimeStamp.nStartFlags = srcInputData->nFlags; + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame timestamp after seeking %lld us (%.2f secs)", + pExynosComponent, __FUNCTION__, srcInputData->timeStamp, (double)(srcInputData->timeStamp / 1E6)); + } + } + +EXIT: + + if (ret != OMX_TRUE) { + /* return OMX buffer and reset dataBuffer */ + Exynos_InputBufferReturn(pOMXComponent, inputUseBuffer); + } + + FunctionOut(); + + return ret; +} + +OMX_BOOL Exynos_Postprocess_OutputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *dstOutputData) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *outputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)dstOutputData->extInfo; + + FunctionIn(); + + if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) { + if (Exynos_Shared_DataToBuffer(exynosOutputPort, outputUseBuffer, dstOutputData) == OMX_ErrorNone) { + outputUseBuffer->dataValid = OMX_TRUE; + } else { + ret = OMX_FALSE; + goto EXIT; + } + } + + if (outputUseBuffer->dataValid == OMX_TRUE) { + if ((pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE) && + ((dstOutputData->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS)) { + unsigned int discardFlags = (OMX_BUFFERFLAG_SYNCFRAME | OMX_BUFFERFLAG_DATACORRUPT | OMX_BUFFERFLAG_ENDOFFRAME); + + if ((pExynosComponent->checkTimeStamp.startTimeStamp == dstOutputData->timeStamp) && + ((pExynosComponent->checkTimeStamp.nStartFlags & ~discardFlags) == + (dstOutputData->nFlags & ~discardFlags))) { + pExynosComponent->checkTimeStamp.startTimeStamp = RESET_TIMESTAMP_VAL; + pExynosComponent->checkTimeStamp.nStartFlags = 0x0; + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + } else { + if (pExynosComponent->checkTimeStamp.startTimeStamp < dstOutputData->timeStamp) { + pExynosComponent->checkTimeStamp.startTimeStamp = RESET_TIMESTAMP_VAL; + pExynosComponent->checkTimeStamp.nStartFlags = 0x0; + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] drop frame after seeking(in: %lld vs out: %lld)", + pExynosComponent, __FUNCTION__, + pExynosComponent->checkTimeStamp.startTimeStamp, dstOutputData->timeStamp); + if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) + Exynos_OMX_FillThisBufferAgain(pOMXComponent, outputUseBuffer->bufferHeader); + + ret = OMX_TRUE; + goto EXIT; + } + } + } else if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) { + ret = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] not set check timestamp after seeking", pExynosComponent, __FUNCTION__); + + if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) + Exynos_OMX_FillThisBufferAgain(pOMXComponent, outputUseBuffer->bufferHeader); + + goto EXIT; + } + + if (exynosOutputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) + Exynos_OSAL_UpdateDataspaceToGraphicMeta(outputUseBuffer->bufferHeader->pBuffer, exynosOutputPort->ColorAspects.nDataSpace); + + if (exynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if (exynosOutputPort->eMetaDataType & METADATA_TYPE_DATA) + dstOutputData->remainDataLen = outputUseBuffer->allocSize; + + if (((exynosOutputPort->eMetaDataType & METADATA_TYPE_DATA) || + (dstOutputData->remainDataLen <= (outputUseBuffer->allocSize - outputUseBuffer->dataLen))) && + (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + + if (dstOutputData->remainDataLen > 0) { + ret = Exynos_CSC_OutputData(pOMXComponent, dstOutputData); + } else { + ret = OMX_TRUE; + } + + if (ret == OMX_TRUE) { + outputUseBuffer->dataLen += dstOutputData->remainDataLen; + outputUseBuffer->remainDataLen += dstOutputData->remainDataLen; + outputUseBuffer->nFlags = dstOutputData->nFlags; + outputUseBuffer->timeStamp = dstOutputData->timeStamp; + + if ((outputUseBuffer->remainDataLen > 0) || + (outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) || + (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { +#ifdef USE_ANDROID + if ((pVideoDec->hImgConv != NULL) && + (outputUseBuffer->remainDataLen > 0)) { + if (Exynos_OSAL_ImgConv_Run(pVideoDec->hImgConv, pOMXComponent, + (OMX_PTR)outputUseBuffer->bufferHeader->pBuffer, + (OMX_PTR)&(pBufferInfo->HDRDynamic)) == OMX_ErrorNone) { + outputUseBuffer->nFlags |= OMX_BUFFERFLAG_CONVERTEDIMAGE; + } + } +#endif + Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer); + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to CSC", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + ret = OMX_FALSE; + } + } else if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) { + outputUseBuffer->dataLen = 0; + outputUseBuffer->remainDataLen = 0; + outputUseBuffer->nFlags = dstOutputData->nFlags; + outputUseBuffer->timeStamp = dstOutputData->timeStamp; + Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] codec buffer's remaining space(%d) is smaller than output data(%d)", + pExynosComponent, __FUNCTION__, + (outputUseBuffer->allocSize - outputUseBuffer->dataLen), dstOutputData->remainDataLen); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + ret = OMX_FALSE; + } + } else if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) { + if ((outputUseBuffer->remainDataLen > 0) || + (outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) || + (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { +#ifdef USE_ANDROID + if ((pVideoDec->hImgConv != NULL) && + (outputUseBuffer->remainDataLen > 0)) { + if (Exynos_OSAL_ImgConv_Run(pVideoDec->hImgConv, pOMXComponent, + (OMX_PTR)outputUseBuffer->bufferHeader->pBuffer, + (OMX_PTR)&(pBufferInfo->HDRDynamic)) == OMX_ErrorNone) { + outputUseBuffer->nFlags |= OMX_BUFFERFLAG_CONVERTEDIMAGE; + } + } +#endif + Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer); + } else { + Exynos_OMX_FillThisBufferAgain(pOMXComponent, outputUseBuffer->bufferHeader); + Exynos_ResetDataBuffer(outputUseBuffer); + } + } + } else { + ret = OMX_FALSE; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SrcInputBufferProcess(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *srcInputUseBuffer = &exynosInputPort->way.port2WayDataBuffer.inputDataBuffer; + EXYNOS_OMX_DATA *pSrcInputData = &exynosInputPort->processData; + + OMX_BOOL bCheckInputData = OMX_FALSE; + + FunctionIn(); + + while (!pVideoDec->bExitBufferProcessThread) { + Exynos_OSAL_SleepMillisec(0); + Exynos_Wait_ProcessPause(pExynosComponent, INPUT_PORT_INDEX); + if ((exynosInputPort->semWaitPortEnable[INPUT_WAY_INDEX] != NULL) && + ((CHECK_PORT_BEING_DISABLED(exynosInputPort)) || + (!CHECK_PORT_ENABLED(exynosInputPort)))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> wait(port enable)", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(exynosInputPort->semWaitPortEnable[INPUT_WAY_INDEX]); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> post(port enable)", pExynosComponent, __FUNCTION__); + continue; + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) && + (!pVideoDec->bExitBufferProcessThread)) { + Exynos_OSAL_SleepMillisec(0); + + if ((CHECK_PORT_BEING_FLUSHED(exynosInputPort)) || + (exynosOutputPort->exceptionFlag == INVALID_STATE)) + break; + + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorInputDataDecodeYet) || + ((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorNoneSrcSetupFinish)) { + if (exynosOutputPort->exceptionFlag != GENERAL_STATE) + break; + } + + Exynos_OSAL_MutexLock(srcInputUseBuffer->bufferMutex); + if ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorInputDataDecodeYet) { + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + OMX_PTR codecBuffer; + if ((pSrcInputData->buffer.addr[0] == NULL) || + (pSrcInputData->pPrivate == NULL)) { + Exynos_CodecBufferDeQueue(pExynosComponent, INPUT_PORT_INDEX, &codecBuffer); + if (pVideoDec->bExitBufferProcessThread) { + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + goto EXIT; + } + + if (codecBuffer != NULL) { + Exynos_CodecBufferToData(codecBuffer, pSrcInputData, INPUT_PORT_INDEX); + } + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + break; + } + } + + if (srcInputUseBuffer->dataValid == OMX_TRUE) { + bCheckInputData = Exynos_Preprocessor_InputData(pOMXComponent, pSrcInputData); + } else { + bCheckInputData = OMX_FALSE; + } + + if ((bCheckInputData == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(exynosInputPort))) { + ret = Exynos_InputBufferGetQueue(pExynosComponent); + if (pVideoDec->bExitBufferProcessThread) { + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + goto EXIT; + } + + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + break; + } + + if (CHECK_PORT_BEING_FLUSHED(exynosInputPort)) { + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + break; + } + } + + /* if input flush is occured before obtaining bufferMutex, + * bufferHeader can be NULL. + */ + if (pSrcInputData->bufferHeader == NULL) { + ret = OMX_ErrorNone; + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + break; + } + + ret = pVideoDec->exynos_codec_srcInputProcess(pOMXComponent, pSrcInputData); + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedFrame) || + ((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input data is weird(0x%x)", + pExynosComponent, __FUNCTION__, ret); + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + OMX_PTR codecBuffer; + codecBuffer = pSrcInputData->pPrivate; + if (codecBuffer != NULL) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, codecBuffer); + } + + if (exynosInputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_OMX_InputBufferReturn(pOMXComponent, pSrcInputData->bufferHeader); + } + } + + if ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorInputDataDecodeYet) { + Exynos_ResetCodecData(pSrcInputData); + } + + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + + if ((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCodecInit) + pVideoDec->bExitBufferProcessThread = OMX_TRUE; + } + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SrcOutputBufferProcess(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *srcOutputUseBuffer = &exynosInputPort->way.port2WayDataBuffer.outputDataBuffer; + EXYNOS_OMX_DATA srcOutputData; + + FunctionIn(); + + Exynos_ResetCodecData(&srcOutputData); + + while (!pVideoDec->bExitBufferProcessThread) { + Exynos_OSAL_SleepMillisec(0); + if ((exynosInputPort->semWaitPortEnable[OUTPUT_WAY_INDEX] != NULL) && + ((CHECK_PORT_BEING_DISABLED(exynosInputPort)) || + (!CHECK_PORT_ENABLED(exynosInputPort)))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> wait(port enable)", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(exynosInputPort->semWaitPortEnable[OUTPUT_WAY_INDEX]); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> post(port enable)", pExynosComponent, __FUNCTION__); + continue; + } + + while (!pVideoDec->bExitBufferProcessThread) { + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + if (Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX) == OMX_FALSE) + break; + } + Exynos_OSAL_SleepMillisec(0); + + if (CHECK_PORT_BEING_FLUSHED(exynosInputPort)) + break; + + Exynos_OSAL_MutexLock(srcOutputUseBuffer->bufferMutex); + ret = pVideoDec->exynos_codec_srcOutputProcess(pOMXComponent, &srcOutputData); + + if (ret == OMX_ErrorNone) { + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + OMX_PTR codecBuffer; + codecBuffer = srcOutputData.pPrivate; + if (codecBuffer != NULL) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, codecBuffer); + } + if (exynosInputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_Shared_DataToBuffer(exynosInputPort, srcOutputUseBuffer, &srcOutputData); + Exynos_InputBufferReturn(pOMXComponent, srcOutputUseBuffer); + } + Exynos_ResetCodecData(&srcOutputData); + } + Exynos_OSAL_MutexUnlock(srcOutputUseBuffer->bufferMutex); + } + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_DstInputBufferProcess(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *dstInputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.inputDataBuffer; + EXYNOS_OMX_DATA dstInputData; + + FunctionIn(); + + Exynos_ResetCodecData(&dstInputData); + + while (!pVideoDec->bExitBufferProcessThread) { + Exynos_OSAL_SleepMillisec(0); + if ((exynosOutputPort->semWaitPortEnable[INPUT_WAY_INDEX] != NULL) && + ((CHECK_PORT_BEING_DISABLED(exynosOutputPort)) || + (!CHECK_PORT_ENABLED(exynosOutputPort)))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> wait(port enable)", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(exynosOutputPort->semWaitPortEnable[INPUT_WAY_INDEX]); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> post(port enable)", pExynosComponent, __FUNCTION__); + continue; + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) && + (!pVideoDec->bExitBufferProcessThread)) { + Exynos_OSAL_SleepMillisec(0); + + if ((CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) || + (exynosOutputPort->exceptionFlag != GENERAL_STATE)) + break; + + Exynos_OSAL_MutexLock(dstInputUseBuffer->bufferMutex); + if ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorOutputBufferUseYet) { + if (exynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + CODEC_DEC_BUFFER *pCodecBuffer = NULL; + ret = Exynos_CodecBufferDeQueue(pExynosComponent, OUTPUT_PORT_INDEX, (OMX_PTR *)&pCodecBuffer); + if (pVideoDec->bExitBufferProcessThread) { + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + goto EXIT; + } + + if (ret != OMX_ErrorNone) { + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + Exynos_CodecBufferToData(pCodecBuffer, &dstInputData, OUTPUT_PORT_INDEX); + } + + if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) { + if ((dstInputUseBuffer->dataValid != OMX_TRUE) && + (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + ret = Exynos_OutputBufferGetQueue(pExynosComponent); + if (pVideoDec->bExitBufferProcessThread) { + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + goto EXIT; + } + + if (ret != OMX_ErrorNone) { + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + + ret = Exynos_Shared_BufferToData(exynosOutputPort, dstInputUseBuffer, &dstInputData); + if (ret != OMX_ErrorNone) { + dstInputUseBuffer->dataValid = OMX_FALSE; + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } +#ifdef USE_ANDROID + if (pVideoDec->bDrvDPBManaging != OMX_TRUE) { + if ((exynosOutputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) || + (exynosOutputPort->eMetaDataType == METADATA_TYPE_GRAPHIC_HANDLE)) { + Exynos_OSAL_RefCount_Increase(pVideoDec->hRefHandle, + dstInputData.bufferHeader->pBuffer, + exynosOutputPort); + } + } +#endif + Exynos_ResetDataBuffer(dstInputUseBuffer); + } + } + + if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) { + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + } + + ret = pVideoDec->exynos_codec_dstInputProcess(pOMXComponent, &dstInputData); + if ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorOutputBufferUseYet) { + /* + * process data could be invalid by flush operation at next dstInputPorcess(). + * then, need to clean up buffer internally for reusing it. + */ + if ((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorNoneReuseBuffer) { + if (exynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, dstInputData.pPrivate); + } + + if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) { +#ifdef USE_ANDROID + if (pVideoDec->bDrvDPBManaging != OMX_TRUE) { + if ((exynosOutputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) || + (exynosOutputPort->eMetaDataType == METADATA_TYPE_GRAPHIC_HANDLE)) { + ReleaseDPB dpbFD[VIDEO_BUFFER_MAX_NUM]; + Exynos_OSAL_Memset(dpbFD, 0, sizeof(dpbFD)); + + dpbFD[0].fd = dstInputData.buffer.fd[0]; + dpbFD[1].fd = -1; + + Exynos_OSAL_RefCount_Decrease(pVideoDec->hRefHandle, + dstInputData.bufferHeader->pBuffer, dpbFD, exynosOutputPort); + } + } +#endif + Exynos_OMX_FillThisBufferAgain(hComponent, dstInputData.bufferHeader); + } + } + + Exynos_ResetCodecData(&dstInputData); + } + + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + } + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_DstOutputBufferProcess(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + EXYNOS_OMX_DATA *pDstOutputData = &exynosOutputPort->processData; + + FunctionIn(); + + while (!pVideoDec->bExitBufferProcessThread) { + Exynos_OSAL_SleepMillisec(0); + Exynos_Wait_ProcessPause(pExynosComponent, OUTPUT_PORT_INDEX); + if ((exynosOutputPort->semWaitPortEnable[OUTPUT_WAY_INDEX] != NULL) && + ((CHECK_PORT_BEING_DISABLED(exynosOutputPort)) || + (!CHECK_PORT_ENABLED(exynosOutputPort)))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> wait(port enable)", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(exynosOutputPort->semWaitPortEnable[OUTPUT_WAY_INDEX]); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> post(port enable)", pExynosComponent, __FUNCTION__); + continue; + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) && + (!pVideoDec->bExitBufferProcessThread)) { + Exynos_OSAL_SleepMillisec(0); + + if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) + break; + + Exynos_OSAL_MutexLock(dstOutputUseBuffer->bufferMutex); + if (exynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if ((dstOutputUseBuffer->dataValid != OMX_TRUE) && + (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + ret = Exynos_OutputBufferGetQueue(pExynosComponent); + if (pVideoDec->bExitBufferProcessThread) { + Exynos_OSAL_MutexUnlock(dstOutputUseBuffer->bufferMutex); + goto EXIT; + } + + if (ret != OMX_ErrorNone) { + Exynos_OSAL_MutexUnlock(dstOutputUseBuffer->bufferMutex); + break; + } + } + } + + if ((dstOutputUseBuffer->dataValid == OMX_TRUE) || + (exynosOutputPort->bufferProcessType == BUFFER_SHARE)) { + ret = pVideoDec->exynos_codec_dstOutputProcess(pOMXComponent, pDstOutputData); + } + + if (((ret == OMX_ErrorNone) && (dstOutputUseBuffer->dataValid == OMX_TRUE)) || + (exynosOutputPort->bufferProcessType == BUFFER_SHARE)) { +#ifdef USE_ANDROID + if (pVideoDec->bDrvDPBManaging != OMX_TRUE) { + if ((exynosOutputPort->bufferProcessType == BUFFER_SHARE) && + (pDstOutputData->bufferHeader != NULL)) { + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + int i; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + Exynos_OSAL_RefCount_Decrease(pVideoDec->hRefHandle, + pDstOutputData->bufferHeader->pBuffer, + pBufferInfo->PDSB.dpbFD, + exynosOutputPort); + } + } +#endif + if (ret == OMX_ErrorNoneReuseBuffer){ + if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) { + ret = Exynos_OMX_FillThisBufferAgain(hComponent, pDstOutputData->bufferHeader); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] FillThisBufferAgain failed(0x%x)", __FUNCTION__, pOMXComponent, ret); + } + } + } else { + Exynos_Postprocess_OutputData(pOMXComponent, pDstOutputData); + } + } + + if (exynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if (pDstOutputData->pPrivate != NULL) { + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pDstOutputData->pPrivate); + pDstOutputData->pPrivate = NULL; + } + } + + /* reset outputData */ + Exynos_ResetCodecData(pDstOutputData); + Exynos_OSAL_MutexUnlock(dstOutputUseBuffer->bufferMutex); + } + } + +EXIT: + + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_SrcInputProcessThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + + FunctionIn(); + + if (threadData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + Exynos_OMX_SrcInputBufferProcess(pOMXComponent); + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_SrcOutputProcessThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + + FunctionIn(); + + if (threadData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + Exynos_OMX_SrcOutputBufferProcess(pOMXComponent); + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_DstInputProcessThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + + FunctionIn(); + + if (threadData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + Exynos_OMX_DstInputBufferProcess(pOMXComponent); + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_DstOutputProcessThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + + FunctionIn(); + + if (threadData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + Exynos_OMX_DstOutputBufferProcess(pOMXComponent); + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferProcess_Create(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + FunctionIn(); + + pVideoDec->bExitBufferProcessThread = OMX_FALSE; + + ret = Exynos_OSAL_ThreadCreate(&pVideoDec->hDstOutputThread, + Exynos_OMX_DstOutputProcessThread, + pOMXComponent); + if (ret == OMX_ErrorNone) + ret = Exynos_OSAL_ThreadCreate(&pVideoDec->hSrcOutputThread, + Exynos_OMX_SrcOutputProcessThread, + pOMXComponent); + if (ret == OMX_ErrorNone) + ret = Exynos_OSAL_ThreadCreate(&pVideoDec->hDstInputThread, + Exynos_OMX_DstInputProcessThread, + pOMXComponent); + if (ret == OMX_ErrorNone) + ret = Exynos_OSAL_ThreadCreate(&pVideoDec->hSrcInputThread, + Exynos_OMX_SrcInputProcessThread, + pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferProcess_Terminate(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + OMX_S32 countValue = 0; + + FunctionIn(); + + pVideoDec->bExitBufferProcessThread = OMX_TRUE; + + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bufferSemID, &countValue); + if (countValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bufferSemID); + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].codecSemID, &countValue); + if (countValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].codecSemID); + + /* srcInput */ + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].pauseEvent); + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].semWaitPortEnable[INPUT_WAY_INDEX]); + Exynos_OSAL_ThreadTerminate(pVideoDec->hSrcInputThread); + pVideoDec->hSrcInputThread = NULL; + Exynos_OSAL_Set_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].semWaitPortEnable[INPUT_WAY_INDEX], 0); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] src input thread is terminated", pExynosComponent, __FUNCTION__); + + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bufferSemID, &countValue); + if (countValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bufferSemID); + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].codecSemID, &countValue); + if (countValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].codecSemID); + pVideoDec->exynos_codec_bufferProcessRun(pOMXComponent, OUTPUT_PORT_INDEX); + + /* dstInput */ + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].pauseEvent); + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].semWaitPortEnable[INPUT_WAY_INDEX]); + Exynos_OSAL_ThreadTerminate(pVideoDec->hDstInputThread); + pVideoDec->hDstInputThread = NULL; + Exynos_OSAL_Set_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].semWaitPortEnable[INPUT_WAY_INDEX], 0); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] dst input thread is terminated", pExynosComponent, __FUNCTION__); + + /* srcOutput */ + pVideoDec->exynos_codec_stop(pOMXComponent, INPUT_PORT_INDEX); + pVideoDec->exynos_codec_bufferProcessRun(pOMXComponent, INPUT_PORT_INDEX); + + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].pauseEvent); + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].semWaitPortEnable[OUTPUT_WAY_INDEX]); + Exynos_OSAL_ThreadTerminate(pVideoDec->hSrcOutputThread); + pVideoDec->hSrcOutputThread = NULL; + Exynos_OSAL_Set_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].semWaitPortEnable[OUTPUT_WAY_INDEX], 0); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] src output thread is terminated", pExynosComponent, __FUNCTION__); + + /* dstOutput */ + pVideoDec->exynos_codec_stop(pOMXComponent, OUTPUT_PORT_INDEX); + pVideoDec->exynos_codec_bufferProcessRun(pOMXComponent, OUTPUT_PORT_INDEX); + + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].pauseEvent); + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].semWaitPortEnable[OUTPUT_WAY_INDEX]); + Exynos_OSAL_ThreadTerminate(pVideoDec->hDstOutputThread); + pVideoDec->hDstOutputThread = NULL; + Exynos_OSAL_Set_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].semWaitPortEnable[OUTPUT_WAY_INDEX], 0); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] dst output thread is terminated", pExynosComponent, __FUNCTION__); + + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoDecodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + + int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = Exynos_OMX_BaseComponent_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to BaseComponent_Constructor", __FUNCTION__); + goto EXIT; + } + + ret = Exynos_OMX_Port_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Port_Constructor", __FUNCTION__); + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pVideoDec = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_VIDEODEC_COMPONENT)); + if (pVideoDec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_Port_Destructor(pOMXComponent); + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Memset(pVideoDec, 0, sizeof(EXYNOS_OMX_VIDEODEC_COMPONENT)); + pVideoDec->bForceHeaderParsing = OMX_FALSE; + pVideoDec->bReconfigDPB = OMX_FALSE; + pVideoDec->bDTSMode = OMX_FALSE; + pVideoDec->bReorderMode = OMX_FALSE; + pVideoDec->eDataType = DATA_TYPE_8BIT; + pVideoDec->bQosChanged = OMX_FALSE; + pVideoDec->nQosRatio = 0; + pVideoDec->bThumbnailMode = OMX_FALSE; + pVideoDec->bSearchBlackBarChanged = OMX_FALSE; + pVideoDec->bSearchBlackBar = OMX_FALSE; + pVideoDec->nImageConvMode = 1; + pVideoDec->bForceUseNonCompFormat = OMX_FALSE; + pVideoDec->bDiscardCSDError = OMX_FALSE; +#ifdef USE_COMPRESSED_COLOR + pVideoDec->nCompColorFormat = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC; +#endif + pExynosComponent->hComponentHandle = (OMX_HANDLETYPE)pVideoDec; + + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + +#ifdef USE_ANDROID + pVideoDec->pPerfHandle = Exynos_OSAL_CreatePerformanceHandle(OMX_FALSE /* bIsEncoder = false */); +#endif + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->supportFormat = Exynos_OSAL_Malloc(sizeof(OMX_COLOR_FORMATTYPE) * INPUT_PORT_SUPPORTFORMAT_NUM_MAX); + if (pExynosPort->supportFormat == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort->supportFormat, 0, (sizeof(OMX_COLOR_FORMATTYPE) * INPUT_PORT_SUPPORTFORMAT_NUM_MAX)); + + pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MIN_VIDEO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = 0; + pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo; + + pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + if (pExynosPort->portDefinition.format.video.cMIMEType == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + + pExynosPort->portDefinition.format.video.nFrameWidth = 0; + pExynosPort->portDefinition.format.video.nFrameHeight= 0; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.format.video.nBitrate = 64000; + pExynosPort->portDefinition.format.video.xFramerate = (15 << 16); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.format.video.pNativeWindow = NULL; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->supportFormat = Exynos_OSAL_Malloc(sizeof(OMX_COLOR_FORMATTYPE) * OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX); + if (pExynosPort->supportFormat == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort->supportFormat, 0, (sizeof(OMX_COLOR_FORMATTYPE) * OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX)); + + pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo; + + pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + if (pExynosPort->portDefinition.format.video.cMIMEType == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + + pExynosPort->portDefinition.format.video.nFrameWidth = 0; + pExynosPort->portDefinition.format.video.nFrameHeight= 0; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.format.video.nBitrate = 64000; + pExynosPort->portDefinition.format.video.xFramerate = (15 << 16); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.format.video.pNativeWindow = NULL; + + pExynosPort->processData.extInfo = (OMX_PTR)Exynos_OSAL_Malloc(sizeof(DECODE_CODEC_EXTRA_BUFFERINFO)); + if (pExynosPort->processData.extInfo == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(((char *)pExynosPort->processData.extInfo), 0, sizeof(DECODE_CODEC_EXTRA_BUFFERINFO)); + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)(pExynosPort->processData.extInfo); + for (i = 0; i < VIDEO_BUFFER_MAX_NUM; i++) { + pBufferInfo->PDSB.dpbFD[i].fd = 0; + pBufferInfo->PDSB.dpbFD[i].fd1 = 0; + pBufferInfo->PDSB.dpbFD[i].fd2 = 0; + } + + pOMXComponent->UseBuffer = &Exynos_OMX_UseBuffer; + pOMXComponent->AllocateBuffer = &Exynos_OMX_AllocateBuffer; + pOMXComponent->FreeBuffer = &Exynos_OMX_FreeBuffer; + +#ifdef TUNNELING_SUPPORT + pOMXComponent->ComponentTunnelRequest = &Exynos_OMX_ComponentTunnelRequest; + pExynosComponent->exynos_AllocateTunnelBuffer = &Exynos_OMX_AllocateTunnelBuffer; + pExynosComponent->exynos_FreeTunnelBuffer = &Exynos_OMX_FreeTunnelBuffer; +#endif + + pExynosComponent->exynos_BufferProcessCreate = &Exynos_OMX_BufferProcess_Create; + pExynosComponent->exynos_BufferProcessTerminate = &Exynos_OMX_BufferProcess_Terminate; + pExynosComponent->exynos_BufferFlush = &Exynos_OMX_BufferFlush; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoDecodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + +#ifdef USE_ANDROID + if (pVideoDec->bDrvDPBManaging != OMX_TRUE) + Exynos_OSAL_RefCount_Terminate(pVideoDec->hRefHandle); + + Exynos_OSAL_ImgConv_Terminate(pVideoDec->hImgConv); + + Exynos_OSAL_ReleasePerformanceHandle(pVideoDec->pPerfHandle); +#endif + + Exynos_OSAL_Free(pVideoDec); + pExynosComponent->hComponentHandle = pVideoDec = NULL; + + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + if (pExynosPort->processData.extInfo != NULL) { + Exynos_OSAL_Free(pExynosPort->processData.extInfo); + pExynosPort->processData.extInfo = NULL; + } + + for(i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + Exynos_OSAL_Free(pExynosPort->portDefinition.format.video.cMIMEType); + pExynosPort->portDefinition.format.video.cMIMEType = NULL; + + Exynos_OSAL_Free(pExynosPort->supportFormat); + pExynosPort->supportFormat = NULL; + } + + ret = Exynos_OMX_Port_Destructor(pOMXComponent); + + ret = Exynos_OMX_BaseComponent_Destructor(hComponent); + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/dec/Exynos_OMX_Vdec.h b/openmax/component/video/dec/Exynos_OMX_Vdec.h new file mode 100644 index 0000000..6761f29 --- /dev/null +++ b/openmax/component/video/dec/Exynos_OMX_Vdec.h @@ -0,0 +1,226 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Vdec.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * HyeYeon Chung (hyeon.chung@samsung.com) + * Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_VIDEO_DECODE +#define EXYNOS_OMX_VIDEO_DECODE + +#include "OMX_Component.h" +#include "Exynos_OMX_Def.h" +#include "Exynos_OSAL_Queue.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Basecomponent.h" +#include "VendorVideoAPI.h" +#include "ExynosVideoApi.h" + +#define MAX_VIDEO_INPUTBUFFER_NUM 5 +#define MIN_VIDEO_INPUTBUFFER_NUM 2 +#define MAX_VIDEO_OUTPUTBUFFER_NUM 4 + +#define MAX_FRAME_WIDTH 1920 +#define MAX_FRAME_HEIGHT 1080 + +#define DEFAULT_VIDEO_INPUT_BUFFER_SIZE (DEFAULT_FRAME_WIDTH * DEFAULT_FRAME_HEIGHT) * 2 +#define DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE (DEFAULT_FRAME_WIDTH * DEFAULT_FRAME_HEIGHT * 3) / 2 + +#define MFC_INPUT_BUFFER_NUM_MAX 3 + +/* min size of input buffer for DRC */ +#define DEFAULT_VIDEO_MIN_INPUT_BUFFER_SIZE (1024 * 1024 * 3 / 2) /* 1.5MB */ + +/* input buffer size for custom component */ +#define CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE (1024 * 1024 * 7) /* 7MB */ +#define CUSTOM_OVER_4K_VIDEO_INPUT_BUFFER_SIZE (1024 * 1024 * 15) /* 15MB */ +#define CUSTOM_LIMITED_DRM_INPUT_BUFFER_SIZE (1024 * 1024 * 5 / 2) /* 2.5MB : For projects which has small vstream heap */ + +#define MFC_OUTPUT_BUFFER_NUM_MAX 16 * 2 +#define DEFAULT_MFC_OUTPUT_YBUFFER_SIZE MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT +#define DEFAULT_MFC_OUTPUT_CBUFFER_SIZE MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 2 + +#define INPUT_PORT_SUPPORTFORMAT_NUM_MAX 1 +#define OUTPUT_PORT_SUPPORTFORMAT_DEFAULT_NUM 3 /* I420P, NV12, RGBA */ +#define OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX (OUTPUT_PORT_SUPPORTFORMAT_DEFAULT_NUM + 4) /* NV12T, YV12, NV21, UNUSED */ + +#define EXTRA_DPB_NUM 5 + +#define MFC_DEFAULT_INPUT_BUFFER_PLANE 1 +#define MFC_DEFAULT_OUTPUT_BUFFER_PLANE 2 + +#define MAX_INPUTBUFFER_NUM_DYNAMIC 0 /* Dynamic number of metadata buffer */ +#define MAX_OUTPUTBUFFER_NUM_DYNAMIC 0 /* Dynamic number of metadata buffer */ + +#define MAX_SECURE_INPUT_BUFFER_SIZE ((3 * 1024 * 1024) / 2) /* 1.5MB */ + +#define DEC_BLOCKS_PER_SECOND 979200 /* remove it and have to read a capability at media_codecs.xml */ + +typedef struct +{ + void *pAddrY; + void *pAddrC; +} CODEC_DEC_ADDR_INFO; + +typedef struct _BYPASS_BUFFER_INFO +{ + OMX_U32 nFlags; + OMX_TICKS timeStamp; +} BYPASS_BUFFER_INFO; + +typedef struct _CODEC_DEC_BUFFER +{ + void *pVirAddr[MAX_BUFFER_PLANE]; /* virtual address */ + unsigned int bufferSize[MAX_BUFFER_PLANE]; /* buffer alloc size */ + unsigned long fd[MAX_BUFFER_PLANE]; /* buffer FD */ + int dataSize; /* total data length */ +} CODEC_DEC_BUFFER; + +typedef struct _DECODE_CODEC_EXTRA_BUFFERINFO +{ + OMX_U32 imageWidth; /* original info of contents */ + OMX_U32 imageHeight; /* original info of contents */ + OMX_U32 imageStride; /* the size applibed H/W alignment. it is including padding data */ + OMX_CONFIG_RECTTYPE cropRect; /* original info of contents */ + OMX_COLOR_FORMATTYPE colorFormat; + PrivateDataShareBuffer PDSB; + ExynosHdrDynamicInfo HDRDynamic; +} DECODE_CODEC_EXTRA_BUFFERINFO; + +typedef struct _EXYNOS_OMX_CURRENT_FRAME_TIMESTAMP +{ + OMX_S32 nIndex; + OMX_TICKS timeStamp; + OMX_U32 nFlags; +} EXYNOS_OMX_CURRENT_FRAME_TIMESTAMP; + +typedef enum _EXYNOS_OMX_DATA_TYPE { + DATA_TYPE_8BIT = 0x00, + DATA_TYPE_10BIT = 0x01, + DATA_TYPE_8BIT_WITH_2BIT = 0x11, + DATA_TYPE_8BIT_SBWC = 0x100, + DATA_TYPE_10BIT_SBWC = 0x101, +} EXYNOS_OMX_DATA_TYPE; + +typedef struct _EXYNOS_OMX_VIDEODEC_COMPONENT +{ + OMX_HANDLETYPE hCodecHandle; + OMX_BOOL bDiscardCSDError; /* if it is true, discard a error event in CorruptedHeader case */ + OMX_BOOL bForceHeaderParsing; + OMX_BOOL bThumbnailMode; + OMX_BOOL bDTSMode; /* true:Decoding Time Stamp, false:Presentation Time Stamp */ + OMX_BOOL bReorderMode; /* true:use Time Stamp reordering, don't care about a mode like as PTS or DTS */ + EXYNOS_OMX_DATA_TYPE eDataType; + OMX_BOOL bQosChanged; + OMX_U32 nQosRatio; + OMX_U32 nOperatingRate; + OMX_U32 nPriority; + OMX_BOOL bSearchBlackBarChanged; /* true: Notify BlackBar searching option(en/disable) was changed */ + OMX_BOOL bSearchBlackBar; /* true: BlackBar searching enable, false: disable */ + OMX_CONFIG_RECTTYPE blackBarCropRect; + OMX_U32 nMinInBufSize; /* required min size of input buffer for DRC */ + CODEC_DEC_BUFFER *pMFCDecInputBuffer[MFC_INPUT_BUFFER_NUM_MAX]; + CODEC_DEC_BUFFER *pMFCDecOutputBuffer[MFC_OUTPUT_BUFFER_NUM_MAX]; + + /* Buffer Process */ + OMX_BOOL bExitBufferProcessThread; + OMX_HANDLETYPE hSrcInputThread; + OMX_HANDLETYPE hSrcOutputThread; + OMX_HANDLETYPE hDstInputThread; + OMX_HANDLETYPE hDstOutputThread; + + /* Shared Memory Handle */ + OMX_HANDLETYPE hSharedMemory; + + /* For Reconfiguration DPB */ + OMX_BOOL bReconfigDPB; + + /* For DPB Reference Handling (by OMX or MFC Driver) */ + OMX_BOOL bDrvDPBManaging; + + /* For SBWC Decoding */ + OMX_COLOR_FORMATTYPE nCompColorFormat; + + /* Protecting S/W Encoder uses SBWC by ConsumerUsage */ + OMX_BOOL bForceUseNonCompFormat; + + /* For Ref Cnt handling about graphic buffer */ + OMX_HANDLETYPE hRefHandle; + + /* CSC handle */ + OMX_PTR csc_handle; + OMX_U32 csc_set_format; + + /* For Image conversion when it is available */ + OMX_HANDLETYPE hImgConv; + OMX_U32 nImageConvMode; + + /* Performance handle */ + OMX_HANDLETYPE pPerfHandle; + + OMX_ERRORTYPE (*exynos_codec_srcInputProcess) (OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData); + OMX_ERRORTYPE (*exynos_codec_srcOutputProcess) (OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData); + OMX_ERRORTYPE (*exynos_codec_dstInputProcess) (OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pOutputData); + OMX_ERRORTYPE (*exynos_codec_dstOutputProcess) (OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pOutputData); + + OMX_ERRORTYPE (*exynos_codec_start)(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex); + OMX_ERRORTYPE (*exynos_codec_stop)(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex); + OMX_ERRORTYPE (*exynos_codec_bufferProcessRun)(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex); + OMX_ERRORTYPE (*exynos_codec_enqueueAllBuffer)(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex); + + OMX_ERRORTYPE (*exynos_codec_getCodecOutputPrivateData) (OMX_PTR codecBuffer, OMX_PTR addr[], OMX_U32 size[]); + + OMX_ERRORTYPE (*exynos_codec_reconfigAllBuffers) (OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex); + OMX_BOOL (*exynos_codec_checkFormatSupport)(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_COLOR_FORMATTYPE eColorFormat); + OMX_ERRORTYPE (*exynos_codec_checkResolutionChange)(OMX_COMPONENTTYPE *pOMXComponent); + + OMX_ERRORTYPE (*exynos_codec_updateExtraInfo)(OMX_COMPONENTTYPE *pOMXComponent, ExynosVideoMeta *pMeta); +} EXYNOS_OMX_VIDEODEC_COMPONENT; + +#ifdef __cplusplus +extern "C" { +#endif + +void Exynos_UpdateFrameSize(OMX_COMPONENTTYPE *pOMXComponent); +void Exynos_Output_SetSupportFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +void Exynos_SetReorderTimestamp(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 *nIndex, OMX_TICKS timeStamp, OMX_U32 nFlags); +void Exynos_GetReorderTimestamp(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, EXYNOS_OMX_CURRENT_FRAME_TIMESTAMP *sCurrentTimestamp, OMX_S32 nFrameIndex, OMX_S32 eFrameType); +OMX_BOOL Exynos_Check_BufferProcess_State(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_CodecBufferToData(CODEC_DEC_BUFFER *codecBuffer, EXYNOS_OMX_DATA *pData, OMX_U32 nPortIndex); +OMX_BOOL Exynos_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *srcInputData); +OMX_ERRORTYPE Exynos_OMX_SrcInputBufferProcess(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_SrcOutputBufferProcess(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_DstInputBufferProcess(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_DstOutputBufferProcess(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_VideoDecodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_VideoDecodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_Allocate_CodecBuffers(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex, int nBufferCnt, unsigned int nAllocSize[MAX_BUFFER_PLANE]); +void Exynos_Free_CodecBuffers(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_ResetAllPortConfig(OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/component/video/dec/Exynos_OMX_VdecControl.c b/openmax/component/video/dec/Exynos_OMX_VdecControl.c new file mode 100644 index 0000000..17b46c4 --- /dev/null +++ b/openmax/component/video/dec/Exynos_OMX_VdecControl.c @@ -0,0 +1,2648 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_VdecControl.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.5.0 + * @history + * 2012.02.20 : Create + * 2017.08.03 : Change event handling + */ + +#include +#include +#include +#include "Exynos_OMX_Macros.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OMX_Vdec.h" +#include "Exynos_OMX_VdecControl.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_SharedMemory.h" + +#include "Exynos_OSAL_Platform.h" + +#include "ExynosVideoApi.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VIDEO_DECCONTROL" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (pExynosPort->portState != EXYNOS_OMX_PortStateEnabling) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && + CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + temp_bufferHeader = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (temp_bufferHeader == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(temp_bufferHeader, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = temp_bufferHeader; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ASSIGNED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(temp_bufferHeader, OMX_BUFFERHEADERTYPE); + + temp_bufferHeader->pBuffer = pBuffer; + temp_bufferHeader->nAllocLen = nSizeBytes; + temp_bufferHeader->pAppPrivate = pAppPrivate; + + if (nPortIndex == INPUT_PORT_INDEX) + temp_bufferHeader->nInputPortIndex = INPUT_PORT_INDEX; + else + temp_bufferHeader->nOutputPortIndex = OUTPUT_PORT_INDEX; + + if (pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC_HANDLE) { + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + EXYNOS_OMX_LOCK_RANGE range; + OMX_U32 stride; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] use grahpic buffer", pExynosComponent, __FUNCTION__); + + range.nWidth = pExynosPort->portDefinition.format.video.nFrameWidth; + range.nHeight = pExynosPort->portDefinition.format.video.nFrameHeight; + range.eColorFormat = pExynosPort->portDefinition.format.video.eColorFormat; + stride = range.nWidth; + + ret = Exynos_OSAL_LockMetaData(temp_bufferHeader->pBuffer, + range, + &stride, &bufferInfo, + pExynosPort->eMetaDataType); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Exynos_OSAL_LockMetaData (0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pExynosPort->extendBufferHeader[i].buf_fd[0] = bufferInfo.fd[0]; + pExynosPort->extendBufferHeader[i].buf_fd[1] = bufferInfo.fd[1]; + pExynosPort->extendBufferHeader[i].buf_fd[2] = bufferInfo.fd[2]; + + pExynosPort->extendBufferHeader[i].pYUVBuf[0] = bufferInfo.addr[0]; + pExynosPort->extendBufferHeader[i].pYUVBuf[1] = bufferInfo.addr[1]; + pExynosPort->extendBufferHeader[i].pYUVBuf[2] = bufferInfo.addr[2]; + + Exynos_OSAL_UnlockMetaData(temp_bufferHeader->pBuffer, pExynosPort->eMetaDataType); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] buf %d pYUVBuf[0]:0x%x , pYUVBuf[1]:0x%x ", __FUNCTION__, + i, pExynosPort->extendBufferHeader[i].pYUVBuf[0], + pExynosPort->extendBufferHeader[i].pYUVBuf[1]); + } + + pExynosPort->assignedBufferNum++; + + *ppBufferHdr = temp_bufferHeader; + + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + + if ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle)) { + if (CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OMX_SendEventCommand(pExynosComponent, EVENT_CMD_STATE_TO_IDLE_STATE, NULL); + } + } else if ((!CHECK_PORT_ENABLED(pExynosPort)) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + Exynos_OMX_SendEventCommand(pExynosComponent, + ((nPortIndex == INPUT_PORT_INDEX)? EVENT_CMD_ENABLE_INPUT_PORT:EVENT_CMD_ENABLE_OUTPUT_PORT), + NULL); + } + } + + ret = OMX_ErrorNone; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p), size(%d)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + (*ppBufferHdr), nSizeBytes); + goto EXIT; + } + } + + Exynos_OSAL_Free(temp_bufferHeader); + ret = OMX_ErrorInsufficientResources; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + unsigned long temp_buffer_fd = -1; + MEMORY_TYPE mem_type = NORMAL_MEMORY; + + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (pExynosPort->portState != EXYNOS_OMX_PortStateEnabling) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && + CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) && + (nPortIndex == INPUT_PORT_INDEX)) + mem_type |= SECURE_MEMORY; + + if (!((nPortIndex == OUTPUT_PORT_INDEX) && + (pExynosPort->bufferProcessType == BUFFER_SHARE))) + mem_type |= CACHED_MEMORY; + + if (pExynosPort->bNeedContigMem == OMX_TRUE) + mem_type |= CONTIG_MEMORY; + + if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) && + (nPortIndex == INPUT_PORT_INDEX) && + (pExynosPort->eMetaDataType == METADATA_TYPE_HANDLE)) { /* for DRM input : metadata */ + temp_buffer = Exynos_OSAL_AllocMetaDataBuffer(pVideoDec->hSharedMemory, + pExynosPort->eMetaDataType, + nSizeBytes, + mem_type); + if (temp_buffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Alloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else { + temp_buffer = Exynos_OSAL_SharedMemory_Alloc(pVideoDec->hSharedMemory, nSizeBytes, mem_type); + if (temp_buffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Alloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + temp_buffer_fd = Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, temp_buffer); + } + + temp_bufferHeader = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (temp_bufferHeader == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(temp_bufferHeader, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = temp_bufferHeader; + pExynosPort->extendBufferHeader[i].buf_fd[0] = temp_buffer_fd; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ALLOCATED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(temp_bufferHeader, OMX_BUFFERHEADERTYPE); + + if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) && + (pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + /* backward compatibility */ + temp_bufferHeader->pBuffer = (void *)temp_buffer_fd; + } else { + temp_bufferHeader->pBuffer = temp_buffer; + } + + temp_bufferHeader->nAllocLen = nSizeBytes; + temp_bufferHeader->pAppPrivate = pAppPrivate; + + if (nPortIndex == INPUT_PORT_INDEX) + temp_bufferHeader->nInputPortIndex = INPUT_PORT_INDEX; + else + temp_bufferHeader->nOutputPortIndex = OUTPUT_PORT_INDEX; + + pExynosPort->assignedBufferNum++; + + *ppBuffer = temp_bufferHeader; + + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + + if ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle)) { + if (CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OMX_SendEventCommand(pExynosComponent, EVENT_CMD_STATE_TO_IDLE_STATE, NULL); + } + } else if((!CHECK_PORT_ENABLED(pExynosPort)) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + Exynos_OMX_SendEventCommand(pExynosComponent, + ((nPortIndex == INPUT_PORT_INDEX)? EVENT_CMD_ENABLE_INPUT_PORT:EVENT_CMD_ENABLE_OUTPUT_PORT), + NULL); + } + } + + ret = OMX_ErrorNone; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p), size(%d)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + (*ppBuffer), nSizeBytes); + goto EXIT; + } + } + + ret = OMX_ErrorInsufficientResources; + +EXIT: + if (ret == OMX_ErrorInsufficientResources) { + if (temp_bufferHeader != NULL) + Exynos_OSAL_Free(temp_bufferHeader); + + if (temp_buffer != NULL) { + if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) && + (nPortIndex == INPUT_PORT_INDEX) && + (pExynosPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + Exynos_OSAL_FreeMetaDataBuffer(pVideoDec->hSharedMemory, pExynosPort->eMetaDataType, temp_buffer); + } else if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) && + (pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + OMX_PTR mapBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoDec->hSharedMemory, temp_buffer_fd); + + Exynos_OSAL_SharedMemory_Free(pVideoDec->hSharedMemory, temp_buffer); + } else { + Exynos_OSAL_SharedMemory_Free(pVideoDec->hSharedMemory, temp_buffer); + } + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pOMXBufferHdr = NULL; + + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((pExynosPort->portState != EXYNOS_OMX_PortStateDisabling) && + (pExynosPort->portState != EXYNOS_OMX_PortStateFlushingForDisable) && + (pExynosPort->portState != EXYNOS_OMX_PortStateInvalid)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + + (*(pExynosComponent->pCallbacks->EventHandler)) (pOMXComponent, + pExynosComponent->callbackData, + (OMX_U32)OMX_EventError, + (OMX_U32)OMX_ErrorPortUnpopulated, + nPortIndex, NULL); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && + CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + for (i = 0; i < MAX_BUFFER_NUM; i++) { + if (((pExynosPort->bufferStateAllocate[i] | BUFFER_STATE_FREE) != 0) && + (pExynosPort->extendBufferHeader[i].OMXBufferHeader != NULL)) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Buffer can't be freed because this(%p) is already in component", pExynosComponent, __FUNCTION__, pBufferHdr); + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + } + + pOMXBufferHdr = pExynosPort->extendBufferHeader[i].OMXBufferHeader; + + if (pOMXBufferHdr->pBuffer == pBufferHdr->pBuffer) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pOMXBufferHdr); + if (pExynosPort->bufferStateAllocate[i] & BUFFER_STATE_ALLOCATED) { + if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) && + (nPortIndex == INPUT_PORT_INDEX) && + (pExynosPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + Exynos_OSAL_FreeMetaDataBuffer(pVideoDec->hSharedMemory, + pExynosPort->eMetaDataType, + pOMXBufferHdr->pBuffer); + } else if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) && + (pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + unsigned long ionFD = (unsigned long)pOMXBufferHdr->pBuffer; + + OMX_PTR mapBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoDec->hSharedMemory, ionFD); + Exynos_OSAL_SharedMemory_Free(pVideoDec->hSharedMemory, mapBuffer); + } else { + Exynos_OSAL_SharedMemory_Free(pVideoDec->hSharedMemory, pOMXBufferHdr->pBuffer); + } + + pOMXBufferHdr->pBuffer = NULL; + pBufferHdr->pBuffer = NULL; + } else if (pExynosPort->bufferStateAllocate[i] & BUFFER_STATE_ASSIGNED) { + ; /* None*/ + } + + pExynosPort->assignedBufferNum--; + + if (pExynosPort->bufferStateAllocate[i] & HEADER_STATE_ALLOCATED) { + Exynos_OSAL_Free(pOMXBufferHdr); + pExynosPort->extendBufferHeader[i].OMXBufferHeader = NULL; + pExynosPort->extendBufferHeader[i].bBufferInOMX = OMX_FALSE; + pBufferHdr = NULL; + } + + pExynosPort->bufferStateAllocate[i] = BUFFER_STATE_FREE; + ret = OMX_ErrorNone; + goto EXIT; + } + } + } + +EXIT: + if (ret == OMX_ErrorNone) { + if (pExynosPort->assignedBufferNum < (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) + pExynosPort->portDefinition.bPopulated = OMX_FALSE; + + if (pExynosPort->assignedBufferNum == 0) { + if ((pExynosComponent->currentState == OMX_StateIdle) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateIdleToLoaded)) { + if (!CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + !CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OMX_SendEventCommand(pExynosComponent, EVENT_CMD_STATE_TO_LOAD_STATE, NULL); + } + } else if((CHECK_PORT_ENABLED(pExynosPort)) && + (pExynosPort->portState == EXYNOS_OMX_PortStateDisabling)) { + Exynos_OMX_SendEventCommand(pExynosComponent, + ((nPortIndex == INPUT_PORT_INDEX)? EVENT_CMD_DISABLE_INPUT_PORT:EVENT_CMD_DISABLE_OUTPUT_PORT), + NULL); + } + } + } + + FunctionOut(); + + return ret; +} + +#ifdef TUNNELING_SUPPORT +OMX_ERRORTYPE Exynos_OMX_AllocateTunnelBuffer(EXYNOS_OMX_BASEPORT *pOMXBasePort, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + OMX_U32 bufferSize = 0; + OMX_PARAM_PORTDEFINITIONTYPE portDefinition; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FreeTunnelBuffer(EXYNOS_OMX_BASEPORT *pOMXBasePort, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + OMX_U32 bufferSize = 0; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentTunnelRequest( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 nPort, + OMX_IN OMX_HANDLETYPE hTunneledComp, + OMX_IN OMX_U32 nTunneledPort, + OMX_INOUT OMX_TUNNELSETUPTYPE *pTunnelSetup) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} +#endif + +OMX_ERRORTYPE Exynos_OMX_GetFlushBuffer(EXYNOS_OMX_BASEPORT *pExynosPort, EXYNOS_OMX_DATABUFFER *pDataBuffer[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + *pDataBuffer = NULL; + + if (pExynosPort->portWayType == WAY1_PORT) { + *pDataBuffer = &pExynosPort->way.port1WayDataBuffer.dataBuffer; + } else if (pExynosPort->portWayType == WAY2_PORT) { + pDataBuffer[0] = &(pExynosPort->way.port2WayDataBuffer.inputDataBuffer); + pDataBuffer[1] = &(pExynosPort->way.port2WayDataBuffer.outputDataBuffer); + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FlushPort(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 portIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *bufferHeader = NULL; + EXYNOS_OMX_DATABUFFER *pDataPortBuffer[2] = {NULL, NULL}; + EXYNOS_OMX_MESSAGE *message = NULL; + + OMX_S32 semValue = 0; + int i = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if ((portIndex < 0) || + (portIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + + while (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > 0) { + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[portIndex].bufferSemID, &semValue); + if (semValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[portIndex].bufferSemID); + + Exynos_OSAL_SemaphoreWait(pExynosComponent->pExynosPort[portIndex].bufferSemID); + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if ((message != NULL) && + (message->type != EXYNOS_OMX_CommandFakeBuffer)) { + bufferHeader = (OMX_BUFFERHEADERTYPE *)message->pCmdData; + bufferHeader->nFilledLen = 0; + + if (portIndex == OUTPUT_PORT_INDEX) + Exynos_OMX_OutputBufferReturn(pOMXComponent, bufferHeader); + else if (portIndex == INPUT_PORT_INDEX) + Exynos_OMX_InputBufferReturn(pOMXComponent, bufferHeader); + } + + Exynos_OSAL_Free(message); + message = NULL; + } + + Exynos_OMX_GetFlushBuffer(pExynosPort, pDataPortBuffer); + if (portIndex == INPUT_PORT_INDEX) { + if (pDataPortBuffer[0]->dataValid == OMX_TRUE) + Exynos_InputBufferReturn(pOMXComponent, pDataPortBuffer[0]); + if (pDataPortBuffer[1]->dataValid == OMX_TRUE) + Exynos_InputBufferReturn(pOMXComponent, pDataPortBuffer[1]); + } else if (portIndex == OUTPUT_PORT_INDEX) { + if (pDataPortBuffer[0]->dataValid == OMX_TRUE) + Exynos_OutputBufferReturn(pOMXComponent, pDataPortBuffer[0]); + if (pDataPortBuffer[1]->dataValid == OMX_TRUE) + Exynos_OutputBufferReturn(pOMXComponent, pDataPortBuffer[1]); + } + + if (pExynosPort->bufferProcessType == BUFFER_SHARE) { + if (pExynosPort->processData.bufferHeader != NULL) { + if (portIndex == INPUT_PORT_INDEX) { + Exynos_OMX_InputBufferReturn(pOMXComponent, pExynosPort->processData.bufferHeader); + } else if (portIndex == OUTPUT_PORT_INDEX) { + if (pExynosPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) + Exynos_OSAL_UnlockMetaData(pExynosPort->processData.bufferHeader->pBuffer, pExynosPort->eMetaDataType); + + Exynos_OMX_OutputBufferReturn(pOMXComponent, pExynosPort->processData.bufferHeader); + } + } + Exynos_ResetCodecData(&pExynosPort->processData); + + for (i = 0; i < MAX_BUFFER_NUM; i++) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_TRUE) { + if (portIndex == OUTPUT_PORT_INDEX) { + if (pExynosPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) + Exynos_OSAL_UnlockMetaData(pExynosPort->extendBufferHeader[i].OMXBufferHeader->pBuffer, pExynosPort->eMetaDataType); + + Exynos_OMX_OutputBufferReturn(pOMXComponent, pExynosPort->extendBufferHeader[i].OMXBufferHeader); + } else if (portIndex == INPUT_PORT_INDEX) { + Exynos_OMX_InputBufferReturn(pOMXComponent, pExynosPort->extendBufferHeader[i].OMXBufferHeader); + } + } + } + } + +#ifdef USE_ANDROID + if ((pExynosPort->bufferProcessType == BUFFER_SHARE) && + (portIndex == OUTPUT_PORT_INDEX) && + (pVideoDec->bDrvDPBManaging != OMX_TRUE)) + Exynos_OSAL_RefCount_Reset(pVideoDec->hRefHandle); +#endif + + if (pExynosPort->bufferSemID != NULL) { + while (1) { + OMX_S32 cnt = 0; + Exynos_OSAL_Get_SemaphoreCount(pExynosPort->bufferSemID, &cnt); + if (cnt == 0) + break; + else if (cnt > 0) + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + else if (cnt < 0) + Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + Exynos_OSAL_SleepMillisec(0); + } + } + + Exynos_OSAL_ResetQueue(&pExynosPort->bufferQ); + +EXIT: + FunctionOut(); + + return ret; +} + + +OMX_ERRORTYPE Exynos_OMX_ForceHeaderParsing( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATABUFFER *pSrcDataBuffer, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + OMX_PTR pCodecBuffer = NULL; + OMX_S32 nBufferCnt = 0; + OMX_BOOL bSubmitCSD = OMX_FALSE; + + FunctionIn(); + + pVideoDec->bForceHeaderParsing = OMX_TRUE; + + /* get a count of queued buffer */ + nBufferCnt = Exynos_OSAL_GetElemNum(&pInputPort->bufferQ); + + /* it is possible that input way has valid info, + * it means that Exynos_Preprocessor_InputData is not handled yet. + * so, do-while loop is used. + */ + do { + if (pSrcInputData->bufferHeader != NULL) { /* processData */ + if (!(pSrcInputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { + /* if does not have CSD flag, think of that all CSDs were already parsed */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] no more CSD buffer", pExynosComponent, __FUNCTION__); + break; + } + ret = pVideoDec->exynos_codec_srcInputProcess(pOMXComponent, pSrcInputData); + + if (ret == OMX_ErrorNone) + bSubmitCSD = OMX_TRUE; + } else if (pSrcDataBuffer->dataValid == OMX_TRUE) { + if (!(pSrcDataBuffer->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { + /* if does not have CSD flag, think of that all CSDs were already parsed */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] no more CSD buffer", pExynosComponent, __FUNCTION__); + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] has CSD buffer(%p), remains(%d)", + pExynosComponent, __FUNCTION__, pSrcDataBuffer->bufferHeader, nBufferCnt); + + /* for BUFFER_COPY mode, get a codec buffer */ + if ((pInputPort->bufferProcessType & BUFFER_COPY) && + ((pSrcInputData->buffer.addr[0] == NULL) || + (pSrcInputData->pPrivate == NULL))) { + Exynos_CodecBufferDeQueue(pExynosComponent, INPUT_PORT_INDEX, &pCodecBuffer); + if (pCodecBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] can't find a valid codec buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_CodecBufferToData(pCodecBuffer, pSrcInputData, INPUT_PORT_INDEX); + } + + if (Exynos_Preprocessor_InputData(pOMXComponent, pSrcInputData) == OMX_TRUE) { + ret = pVideoDec->exynos_codec_srcInputProcess(pOMXComponent, pSrcInputData); + + if (ret == OMX_ErrorNone) + bSubmitCSD = OMX_TRUE; + } else { + if (pInputPort->bufferProcessType & BUFFER_COPY) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pSrcInputData->pPrivate); + } + } + + switch ((int)ret) { + case OMX_ErrorCorruptedFrame: + case OMX_ErrorCorruptedHeader: + case OMX_ErrorInputDataDecodeYet: /* no need re-input scheme */ + { + /* discard current buffer */ + if (pInputPort->bufferProcessType & BUFFER_COPY) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pSrcInputData->pPrivate); + + if (pInputPort->bufferProcessType & BUFFER_SHARE) + Exynos_OMX_InputBufferReturn(pOMXComponent, pSrcInputData->bufferHeader); + } + break; + case OMX_ErrorNone: + case OMX_ErrorNeedNextHeaderInfo: + case OMX_ErrorNoneSrcSetupFinish: + { + /* no need to process anything */ + } + break; + default: + { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] error is occurred at pre-processing(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + break; + } + + /* info cleanup */ + Exynos_ResetDataBuffer(pSrcDataBuffer); + Exynos_ResetCodecData(pSrcInputData); + + if (nBufferCnt > 0) { + nBufferCnt--; + + /* get a buffer from port */ + ret = Exynos_InputBufferGetQueue(pExynosComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Failed to InputBufferGetQueue", pExynosComponent, __FUNCTION__); + break; + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] no more buffer", pExynosComponent, __FUNCTION__); + break; + } + } while (1); + +EXIT: + pVideoDec->exynos_codec_stop(pOMXComponent, INPUT_PORT_INDEX); + + if (bSubmitCSD == OMX_TRUE) { + ret = pVideoDec->exynos_codec_checkResolutionChange(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] error is occurred at resolution check(0x%x)", + pExynosComponent, __FUNCTION__, ret); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + + pVideoDec->bForceHeaderParsing = OMX_FALSE; + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferFlush( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex, + OMX_BOOL bEvent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_DATABUFFER *flushPortBuffer[2] = {NULL, NULL}; + EXYNOS_OMX_PORT_STATETYPE ePortState = EXYNOS_OMX_PortStateInvalid; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if ((nPortIndex < 0) || + (nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + ePortState = pExynosPort->portState; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] OMX_CommandFlush start, port:%d, event:%d", + pExynosComponent, __FUNCTION__, nPortIndex, bEvent); + + Exynos_OSAL_SignalSet(pExynosPort->pauseEvent); + + Exynos_OMX_GetFlushBuffer(pExynosPort, flushPortBuffer); + if (flushPortBuffer[0] == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pExynosPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) + Exynos_OSAL_SemaphorePost(pExynosPort->codecSemID); + + if (pExynosPort->bufferSemID != NULL) { + while (1) { + OMX_S32 cnt = 0; + Exynos_OSAL_Get_SemaphoreCount(pExynosPort->bufferSemID, &cnt); + if (cnt > 0) + break; + else + Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + Exynos_OSAL_SleepMillisec(0); + } + } + + pVideoDec->exynos_codec_bufferProcessRun(pOMXComponent, nPortIndex); + Exynos_OSAL_MutexLock(flushPortBuffer[0]->bufferMutex); + + pVideoDec->exynos_codec_stop(pOMXComponent, nPortIndex); + + if (flushPortBuffer[1] != NULL) + Exynos_OSAL_MutexLock(flushPortBuffer[1]->bufferMutex); + + if (nPortIndex == INPUT_PORT_INDEX) { + /* try to find a CSD buffer and parse it */ + Exynos_OMX_ForceHeaderParsing(pOMXComponent, flushPortBuffer[0], &(pExynosPort->processData)); + } + + ret = Exynos_OMX_FlushPort(pOMXComponent, nPortIndex); + + if ((ePortState == EXYNOS_OMX_PortStateFlushingForDisable) && + (pVideoDec->bReconfigDPB == OMX_TRUE)) { + ret = pVideoDec->exynos_codec_reconfigAllBuffers(pOMXComponent, nPortIndex); + if (ret != OMX_ErrorNone) + goto EXIT; + } else if (pExynosComponent->pExynosPort[nPortIndex].bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + pVideoDec->exynos_codec_enqueueAllBuffer(pOMXComponent, nPortIndex); + } + + Exynos_ResetCodecData(&pExynosPort->processData); + + if (ret == OMX_ErrorNone) { + if (nPortIndex == INPUT_PORT_INDEX) { + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_TRUE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, OMX_FALSE, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + pExynosComponent->reInputData = OMX_FALSE; + + pVideoDec->exynos_codec_start(pOMXComponent, nPortIndex); + } else { + if (pVideoDec->bReconfigDPB != OMX_TRUE) + pVideoDec->exynos_codec_start(pOMXComponent, nPortIndex); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_CountReset(pExynosPort->hBufferCount); +#endif + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] OMX_CommandFlush end, port:%d, event:%d", + pExynosComponent, __FUNCTION__, nPortIndex, bEvent); + +EXIT: + if (flushPortBuffer[1] != NULL) + Exynos_OSAL_MutexUnlock(flushPortBuffer[1]->bufferMutex); + + if (flushPortBuffer[0] != NULL) + Exynos_OSAL_MutexUnlock(flushPortBuffer[0]->bufferMutex); + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_InputBufferReturn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATABUFFER *pDataBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + OMX_BUFFERHEADERTYPE *pBufferHdr = NULL; + + FunctionIn(); + + if ((pOMXComponent == NULL) || + (pDataBuffer == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pInputPort = &(pExynosComponent->pExynosPort[INPUT_PORT_INDEX]); + + pBufferHdr = pDataBuffer->bufferHeader; + + if (pBufferHdr != NULL) { + if (pInputPort->markType.hMarkTargetComponent != NULL) { + pBufferHdr->hMarkTargetComponent = pInputPort->markType.hMarkTargetComponent; + pBufferHdr->pMarkData = pInputPort->markType.pMarkData; + pInputPort->markType.hMarkTargetComponent = NULL; + pInputPort->markType.pMarkData = NULL; + } + + if (pBufferHdr->hMarkTargetComponent != NULL) { + if (pBufferHdr->hMarkTargetComponent == pOMXComponent) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventMark, + 0, 0, pBufferHdr->pMarkData); + } else { + pExynosComponent->propagateMarkType.hMarkTargetComponent = pBufferHdr->hMarkTargetComponent; + pExynosComponent->propagateMarkType.pMarkData = pBufferHdr->pMarkData; + } + } + + pBufferHdr->nFilledLen = 0; + pBufferHdr->nOffset = 0; + + Exynos_OMX_InputBufferReturn(pOMXComponent, pBufferHdr); + } + + /* reset dataBuffer */ + Exynos_ResetDataBuffer(pDataBuffer); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_InputBufferGetQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorUndefined; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + EXYNOS_OMX_DATABUFFER *inputUseBuffer = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + inputUseBuffer = &(pExynosPort->way.port2WayDataBuffer.inputDataBuffer); + + if (pExynosComponent->currentState != OMX_StateExecuting) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorUndefined; + goto EXIT; + } else if (((pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (!CHECK_PORT_BEING_FLUSHED(pExynosPort))) || + (pVideoDec->bForceHeaderParsing == OMX_TRUE)) { + if (pVideoDec->bForceHeaderParsing != OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> wait(bufferSemID)", + pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> post(bufferSemID)", + pExynosComponent, __FUNCTION__); + } + + if (inputUseBuffer->dataValid != OMX_TRUE) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + if (message->type == EXYNOS_OMX_CommandFakeBuffer) { + Exynos_OSAL_Free(message); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecFlush; + goto EXIT; + } + + inputUseBuffer->bufferHeader = (OMX_BUFFERHEADERTYPE *)(message->pCmdData); + inputUseBuffer->allocSize = inputUseBuffer->bufferHeader->nAllocLen; + inputUseBuffer->dataLen = inputUseBuffer->bufferHeader->nFilledLen; + inputUseBuffer->remainDataLen = inputUseBuffer->dataLen; + inputUseBuffer->usedDataLen = 0; + inputUseBuffer->dataValid = OMX_TRUE; + inputUseBuffer->nFlags = inputUseBuffer->bufferHeader->nFlags; + inputUseBuffer->timeStamp = inputUseBuffer->bufferHeader->nTimeStamp; + + Exynos_OSAL_Free(message); + + if (inputUseBuffer->allocSize < inputUseBuffer->dataLen) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] buffer size(%d) is smaller than dataLen(%d)", + pExynosComponent, __FUNCTION__, + inputUseBuffer->allocSize, inputUseBuffer->dataLen); + } + } + + ret = OMX_ErrorNone; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OutputBufferReturn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATABUFFER *pDataBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + OMX_BUFFERHEADERTYPE *pBufferHdr = pDataBuffer->bufferHeader; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pOutputPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + + if (pBufferHdr != NULL) { + pBufferHdr->nFilledLen = pDataBuffer->remainDataLen; + pBufferHdr->nOffset = 0; + pBufferHdr->nFlags = pDataBuffer->nFlags; + pBufferHdr->nTimeStamp = pDataBuffer->timeStamp; + + if ((pOutputPort->eMetaDataType & METADATA_TYPE_DATA) && + (pBufferHdr->nFilledLen > 0)) + pBufferHdr->nFilledLen = pBufferHdr->nAllocLen; + + if (pExynosComponent->propagateMarkType.hMarkTargetComponent != NULL) { + pBufferHdr->hMarkTargetComponent = pExynosComponent->propagateMarkType.hMarkTargetComponent; + pBufferHdr->pMarkData = pExynosComponent->propagateMarkType.pMarkData; + + pExynosComponent->propagateMarkType.hMarkTargetComponent = NULL; + pExynosComponent->propagateMarkType.pMarkData = NULL; + } + + if ((pBufferHdr->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] send event(OMX_EventBufferFlag)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventBufferFlag, + OUTPUT_PORT_INDEX, + pBufferHdr->nFlags, NULL); + } + + Exynos_OMX_OutputBufferReturn(pOMXComponent, pBufferHdr); + } + + /* reset dataBuffer */ + Exynos_ResetDataBuffer(pDataBuffer); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OutputBufferGetQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorUndefined; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + EXYNOS_OMX_DATABUFFER *outputUseBuffer = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + + if (pExynosPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + outputUseBuffer = &(pExynosPort->way.port2WayDataBuffer.outputDataBuffer); + } else if (pExynosPort->bufferProcessType == BUFFER_SHARE) { + outputUseBuffer = &(pExynosPort->way.port2WayDataBuffer.inputDataBuffer); + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if (pExynosComponent->currentState != OMX_StateExecuting) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorUndefined; + goto EXIT; + } else if ((pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (!CHECK_PORT_BEING_FLUSHED(pExynosPort))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> wait(bufferSemID)", + pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> post(bufferSemID)", + pExynosComponent, __FUNCTION__); + if (outputUseBuffer->dataValid != OMX_TRUE) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + if (message->type == EXYNOS_OMX_CommandFakeBuffer) { + Exynos_OSAL_Free(message); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecFlush; + goto EXIT; + } + + outputUseBuffer->bufferHeader = (OMX_BUFFERHEADERTYPE *)(message->pCmdData); + outputUseBuffer->allocSize = outputUseBuffer->bufferHeader->nAllocLen; + outputUseBuffer->dataLen = 0; //dataBuffer->bufferHeader->nFilledLen; + outputUseBuffer->remainDataLen = outputUseBuffer->dataLen; + outputUseBuffer->usedDataLen = 0; //dataBuffer->bufferHeader->nOffset; + outputUseBuffer->dataValid = OMX_TRUE; + /* dataBuffer->nFlags = dataBuffer->bufferHeader->nFlags; */ + /* dataBuffer->nTimeStamp = dataBuffer->bufferHeader->nTimeStamp; */ +/* + if (pExynosPort->bufferProcessType == BUFFER_SHARE) + outputUseBuffer->pPrivate = outputUseBuffer->bufferHeader->pOutputPortPrivate; + else if (pExynosPort->bufferProcessType & BUFFER_COPY) { + pExynosPort->processData.dataBuffer = outputUseBuffer->bufferHeader->pBuffer; + pExynosPort->processData.allocSize = outputUseBuffer->bufferHeader->nAllocLen; + } +*/ + Exynos_OSAL_Free(message); + } + + ret = OMX_ErrorNone; + } +EXIT: + FunctionOut(); + + return ret; + +} + +OMX_BUFFERHEADERTYPE *Exynos_OutputBufferGetQueue_Direct(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_BUFFERHEADERTYPE *retBuffer = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *message = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + retBuffer = NULL; + goto EXIT; + } + pExynosPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + + if (pExynosComponent->currentState != OMX_StateExecuting) { + retBuffer = NULL; + goto EXIT; + } else if ((pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (!CHECK_PORT_BEING_FLUSHED(pExynosPort))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> wait(bufferSemID)", + pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> post(bufferSemID)", + pExynosComponent, __FUNCTION__); + + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message == NULL) { + retBuffer = NULL; + goto EXIT; + } + + if (message->type == EXYNOS_OMX_CommandFakeBuffer) { + Exynos_OSAL_Free(message); + retBuffer = NULL; + goto EXIT; + } + + retBuffer = (OMX_BUFFERHEADERTYPE *)(message->pCmdData); + Exynos_OSAL_Free(message); + } + +EXIT: + FunctionOut(); + + return retBuffer; +} + +OMX_ERRORTYPE Exynos_CodecBufferEnQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 PortIndex, OMX_PTR data) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (PortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &(pExynosComponent->pExynosPort[PortIndex]); + + if (data == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = Exynos_OSAL_Queue(&pExynosPort->codecBufferQ, (void *)data); + if (ret != 0) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + Exynos_OSAL_SemaphorePost(pExynosPort->codecSemID); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_CodecBufferDeQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 PortIndex, OMX_PTR *data) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_PTR tempData = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (PortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &(pExynosComponent->pExynosPort[PortIndex]); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port -> wait(codecSemID)", + pExynosComponent, __FUNCTION__, + (PortIndex == INPUT_PORT_INDEX)? "input":"output"); + Exynos_OSAL_SemaphoreWait(pExynosPort->codecSemID); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port -> wait(codecSemID)", + pExynosComponent, __FUNCTION__, + (PortIndex == INPUT_PORT_INDEX)? "input":"output"); + + tempData = (OMX_PTR)Exynos_OSAL_Dequeue(&pExynosPort->codecBufferQ); + if (tempData == NULL) { + *data = NULL; + ret = OMX_ErrorUndefined; + goto EXIT; + } + *data = tempData; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_CodecBufferReset(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 PortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (PortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &(pExynosComponent->pExynosPort[PortIndex]); + + ret = Exynos_OSAL_ResetQueue(&pExynosPort->codecBufferQ); + if (ret != 0) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + while (1) { + OMX_S32 cnt = 0; + Exynos_OSAL_Get_SemaphoreCount(pExynosPort->codecSemID, &cnt); + if (cnt > 0) + Exynos_OSAL_SemaphoreWait(pExynosPort->codecSemID); + else + break; + } + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoDecodeGetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR ComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (ComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParam = (OMX_PORT_PARAM_TYPE *)ComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(portParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + portParam->nPorts = pExynosComponent->portParam.nPorts; + portParam->nStartPortNumber = pExynosComponent->portParam.nStartPortNumber; + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *pPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)ComponentParameterStructure; + OMX_U32 nPortIndex = pPortFormat->nPortIndex; + OMX_U32 nIndex = pPortFormat->nIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + OMX_BOOL bFormatSupport = OMX_FALSE; + + ret = Exynos_OMX_Check_SizeVersion(pPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((nPortIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + + if (nPortIndex == INPUT_PORT_INDEX) { + if (nIndex > (INPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pPortDef = &pExynosPort->portDefinition; + + pPortFormat->eCompressionFormat = pPortDef->format.video.eCompressionFormat; + pPortFormat->xFramerate = pPortDef->format.video.xFramerate; + pPortFormat->eColorFormat = pPortDef->format.video.eColorFormat; + } else if (nPortIndex == OUTPUT_PORT_INDEX) { + if (nIndex > (OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pPortDef = &pExynosPort->portDefinition; + pPortFormat->eCompressionFormat = OMX_VIDEO_CodingUnused; + pPortFormat->xFramerate = pPortDef->format.video.xFramerate; + + if (pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED) { + if (pExynosPort->supportFormat[nIndex] == OMX_COLOR_FormatUnused) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + pPortFormat->eColorFormat = pExynosPort->supportFormat[nIndex]; + } else { + if (nIndex > 0) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + bFormatSupport = pVideoDec->exynos_codec_checkFormatSupport(pExynosComponent, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled); + if (bFormatSupport == OMX_TRUE) + pPortFormat->eColorFormat = Exynos_OSAL_OMX2HALPixelFormat((OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled, pExynosPort->ePlaneType); + else + pPortFormat->eColorFormat = Exynos_OSAL_OMX2HALPixelFormat(OMX_COLOR_FormatYUV420SemiPlanar, pExynosPort->ePlaneType); + } + } + + ret = OMX_ErrorNone; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamDescribeColorFormat: + case OMX_IndexParamGetAndroidNativeBuffer: + { + ret = Exynos_OSAL_GetParameter(hComponent, nParamIndex, ComponentParameterStructure); + } + break; +#endif + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)ComponentParameterStructure; + OMX_U32 nPortIndex = portDefinition->nPortIndex; + + ret = Exynos_OMX_GetParameter(hComponent, nParamIndex, ComponentParameterStructure); + if (ret != OMX_ErrorNone) { + goto EXIT; + } +#ifdef USE_ANDROID + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC) || + (pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC_HANDLE)) { + switch (pVideoDec->eDataType) { + case DATA_TYPE_8BIT_WITH_2BIT: + portDefinition->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)Exynos_OSAL_OMX2HALPixelFormat((OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatS10bitYUV420SemiPlanar, + pExynosPort->ePlaneType); + break; + case DATA_TYPE_10BIT: + portDefinition->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)Exynos_OSAL_OMX2HALPixelFormat((OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatYUV420Planar16, + pExynosPort->ePlaneType); + break; + case DATA_TYPE_8BIT_SBWC: + portDefinition->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)Exynos_OSAL_OMX2HALPixelFormat((OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC, + pExynosPort->ePlaneType); + break; + case DATA_TYPE_10BIT_SBWC: + portDefinition->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)Exynos_OSAL_OMX2HALPixelFormat((OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC, + pExynosPort->ePlaneType); + break; + default: + portDefinition->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)Exynos_OSAL_OMX2HALPixelFormat(portDefinition->format.video.eColorFormat, pExynosPort->ePlaneType); + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] portDefinition->format.video.eColorFormat: 0x%x", + pExynosComponent, __FUNCTION__, portDefinition->format.video.eColorFormat); + } +#endif + ret = Exynos_OSAL_GetParameter(hComponent, nParamIndex, ComponentParameterStructure); + if (ret != OMX_ErrorNone) + goto EXIT; + } + break; + case OMX_IndexVendorNeedContigMemory: + { + EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *pPortMemType = (EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *)ComponentParameterStructure; + OMX_U32 nPortIndex = pPortMemType->nPortIndex; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortMemType, sizeof(EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + pPortMemType->bNeedContigMem = pExynosPort->bNeedContigMem; + } + break; + case OMX_IndexExynosParamCorruptedHeader: + { + EXYNOS_OMX_VIDEO_PARAM_CORRUPTEDHEADER *pCorruptedHeader = (EXYNOS_OMX_VIDEO_PARAM_CORRUPTEDHEADER *)ComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pCorruptedHeader, sizeof(EXYNOS_OMX_VIDEO_PARAM_CORRUPTEDHEADER)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pCorruptedHeader->bDiscardEvent = pVideoDec->bDiscardCSDError; + } + break; + case OMX_IndexParamVideoCompressedColorFormat: + { + OMX_PARAM_U32TYPE *pColorFormat = (OMX_PARAM_U32TYPE *)ComponentParameterStructure; + + if (pColorFormat->nPortIndex != OUTPUT_PORT_INDEX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid port index", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pColorFormat, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pColorFormat->nU32 = pVideoDec->nCompColorFormat; + + ret = OMX_ErrorNone; + } + break; + default: + { + ret = Exynos_OMX_GetParameter(hComponent, nParamIndex, ComponentParameterStructure); + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} +OMX_ERRORTYPE Exynos_OMX_VideoDecodeSetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR ComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (ComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *pPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)ComponentParameterStructure; + OMX_U32 nPortIndex = pPortFormat->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((nPortIndex >= pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pPortDef = &pExynosPort->portDefinition; + + pPortDef->format.video.eColorFormat = pPortFormat->eColorFormat; + pPortDef->format.video.eCompressionFormat = pPortFormat->eCompressionFormat; + pPortDef->format.video.xFramerate = pPortFormat->xFramerate; + + if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pExynosPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + pPortDef->format.video.eColorFormat = Exynos_OSAL_HAL2OMXColorFormat(pPortFormat->eColorFormat); + } + + Exynos_UpdateFrameSize(pOMXComponent); + } + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *pPortDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)ComponentParameterStructure; + OMX_U32 portIndex = pPortDefinition->nPortIndex; + OMX_U32 size; + OMX_U32 realWidth, realHeight; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(pPortDefinition, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + if (pPortDefinition->nBufferCountActual < pExynosPort->portDefinition.nBufferCountMin) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + /* to prevent a over-allocation about reserved memory */ + if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) && + (portIndex == OUTPUT_PORT_INDEX)) { + int nDisExtBufCnt = Exynos_OSAL_GetDisplayExtraBufferCount(); + + if (pPortDefinition->nBufferCountActual > (pExynosPort->portDefinition.nBufferCountMin + nDisExtBufCnt)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } +#endif + + Exynos_OSAL_Memcpy(((char *)&pExynosPort->portDefinition) + nOffset, + ((char *)pPortDefinition) + nOffset, + pPortDefinition->nSize - nOffset); + +#ifdef USE_ANDROID // Modified by Google engineer + /* should not affect the format since in ANB case, the caller + * is providing us a HAL format */ + if ((pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC) || + (pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC_HANDLE)) { + pExynosPort->portDefinition.format.video.eColorFormat = + Exynos_OSAL_HAL2OMXColorFormat(pExynosPort->portDefinition.format.video.eColorFormat); + } +#endif + + realWidth = pExynosPort->portDefinition.format.video.nFrameWidth; + realHeight = pExynosPort->portDefinition.format.video.nFrameHeight; + size = (ALIGN(realWidth, 16) * ALIGN(realHeight, 16) * 3) / 2; + pExynosPort->portDefinition.format.video.nStride = realWidth; + pExynosPort->portDefinition.format.video.nSliceHeight = realHeight; + pExynosPort->portDefinition.nBufferSize = (size > pExynosPort->portDefinition.nBufferSize) ? size : pExynosPort->portDefinition.nBufferSize; + + if (portIndex == INPUT_PORT_INDEX) { + if (pExynosPort->portDefinition.nBufferSize < pVideoDec->nMinInBufSize) + pExynosPort->portDefinition.nBufferSize = pVideoDec->nMinInBufSize; + + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { + if ((realWidth * realHeight) > (4096 * 2160)) { + pExynosPort->portDefinition.nBufferSize = CUSTOM_OVER_4K_VIDEO_INPUT_BUFFER_SIZE; + } else { + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + } +#ifdef USE_SMALL_SECURE_MEMORY + if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) && + (pExynosPort->portDefinition.nBufferSize > CUSTOM_LIMITED_DRM_INPUT_BUFFER_SIZE)) { + pExynosPort->portDefinition.nBufferSize = CUSTOM_LIMITED_DRM_INPUT_BUFFER_SIZE; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] use limited input size(%d) for DRM", + pExynosComponent, __FUNCTION__, pExynosPort->portDefinition.nBufferSize); + } +#endif + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] the size of input buffer is %d", + pExynosComponent, __FUNCTION__, pExynosPort->portDefinition.nBufferSize); + + Exynos_UpdateFrameSize(pOMXComponent); + } + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamEnableAndroidBuffers: + case OMX_IndexParamStoreMetaDataBuffer: + case OMX_IndexParamAllocateNativeHandle: + case OMX_IndexParamAndroidNatvieBufferConsumerUsage: + { + ret = Exynos_OSAL_SetParameter(hComponent, nIndex, ComponentParameterStructure); + } + break; +#endif + case OMX_IndexVendorNeedContigMemory: + { + EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *pPortMemType = (EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *)ComponentParameterStructure; + OMX_U32 nPortIndex = pPortMemType->nPortIndex; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortMemType, sizeof(EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + pExynosPort->bNeedContigMem = pPortMemType->bNeedContigMem; + } + break; + case OMX_IndexVendorSetDTSMode: + { + EXYNOS_OMX_VIDEO_PARAM_DTSMODE *pDTSParam = (EXYNOS_OMX_VIDEO_PARAM_DTSMODE *)ComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDTSParam, sizeof(EXYNOS_OMX_VIDEO_PARAM_DTSMODE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoDec->bDTSMode = pDTSParam->bDTSMode; + } + break; + case OMX_IndexParamEnableThumbnailMode: + { + EXYNOS_OMX_VIDEO_THUMBNAILMODE *pThumbnailMode = (EXYNOS_OMX_VIDEO_THUMBNAILMODE *)ComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pThumbnailMode, sizeof(EXYNOS_OMX_VIDEO_THUMBNAILMODE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoDec->bThumbnailMode = pThumbnailMode->bEnable; + if (pVideoDec->bThumbnailMode == OMX_TRUE) { + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosOutputPort->portDefinition.nBufferCountMin = 1; + pExynosOutputPort->portDefinition.nBufferCountActual = 1; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexExynosParamCorruptedHeader: + { + EXYNOS_OMX_VIDEO_PARAM_CORRUPTEDHEADER *pCorruptedHeader = (EXYNOS_OMX_VIDEO_PARAM_CORRUPTEDHEADER *)ComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pCorruptedHeader, sizeof(EXYNOS_OMX_VIDEO_PARAM_CORRUPTEDHEADER)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoDec->bDiscardCSDError = pCorruptedHeader->bDiscardEvent; + ret = OMX_ErrorNone; + } + break; + case OMX_IndexExynosParamImageCrop: + { + EXYNOS_OMX_VIDEO_PARAM_IMAGE_CROP *pImageCrop = (EXYNOS_OMX_VIDEO_PARAM_IMAGE_CROP *)ComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pImageCrop, sizeof(EXYNOS_OMX_VIDEO_PARAM_IMAGE_CROP)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pExynosComponent->bUseImgCrop = pImageCrop->bEnabled; + + if (pExynosComponent->bUseImgCrop == OMX_TRUE) { + pExynosPort->bufferProcessType |= BUFFER_COPY_FORCE; + } else { + pExynosPort->bufferProcessType &= (~BUFFER_COPY_FORCE); + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoCompressedColorFormat: + { + OMX_PARAM_U32TYPE *pColorFormat = (OMX_PARAM_U32TYPE *)ComponentParameterStructure; + + if (pColorFormat->nPortIndex != OUTPUT_PORT_INDEX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid port index", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pColorFormat, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + +#ifndef USE_COMPRESSED_COLOR + if ((pColorFormat->nU32 < OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC) && + (pColorFormat->nU32 > OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L80)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, pColorFormat->nU32); + ret = OMX_ErrorBadParameter; + goto EXIT; + } +#endif + + pVideoDec->nCompColorFormat = (OMX_COLOR_FORMATTYPE)pColorFormat->nU32; + + ret = OMX_ErrorNone; + } + break; + default: + { + ret = Exynos_OMX_SetParameter(hComponent, nIndex, ComponentParameterStructure); + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoDecodeGetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexVendorGetBufferFD: + { + EXYNOS_OMX_VIDEO_CONFIG_BUFFERINFO *pBufferInfo = (EXYNOS_OMX_VIDEO_CONFIG_BUFFERINFO *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pBufferInfo, sizeof(EXYNOS_OMX_VIDEO_CONFIG_BUFFERINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pBufferInfo->fd = Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, pBufferInfo->pVirAddr); + } + break; + case OMX_IndexExynosConfigPTSMode: /* MSRND */ + { + *((OMX_BOOL *)pComponentConfigStructure) = (pVideoDec->bDTSMode == OMX_TRUE)? OMX_FALSE:OMX_TRUE; + } + break; + case OMX_IndexConfigBlackBarCrop: + { + OMX_CONFIG_RECTTYPE *pBlackBarCropRect = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pBlackBarCropRect, sizeof(OMX_CONFIG_RECTTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pBlackBarCropRect->nPortIndex != OUTPUT_PORT_INDEX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] This config is vaild at Output port only", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + Exynos_OSAL_Memcpy(pBlackBarCropRect, &pVideoDec->blackBarCropRect, sizeof(OMX_CONFIG_RECTTYPE)); + } + break; + case OMX_IndexConfigCommonInputCrop: + { + OMX_CONFIG_RECTTYPE *pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pSrcRectType = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].cropRectangle[IMG_CROP_INPUT_PORT]); + + if (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + break; + case OMX_IndexConfigCommonOutputCrop: + { + OMX_CONFIG_RECTTYPE *pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pSrcRectType = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].cropRectangle[IMG_CROP_OUTPUT_PORT]); + + if (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] image cropping is not enabled.", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigVideoColorAspects: + { + ret = Exynos_OSAL_GetConfig(hComponent, nIndex, pComponentConfigStructure); + } + break; + case OMX_IndexConfigAndroidVendorExtension: + { + ret = Exynos_OSAL_GetVendorExt(hComponent, pComponentConfigStructure); + } + break; +#endif + default: + ret = Exynos_OMX_GetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoDecodeSetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigOperatingRate: /* since M version */ + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pComponentConfigStructure; + OMX_U32 xFramerate = 0; + + ret = Exynos_OMX_Check_SizeVersion(pConfigRate, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + pVideoDec->nQosRatio = pConfigRate->nU32 >> 16; + + if (pVideoDec->nQosRatio == (((OMX_U32)INT_MAX) >> 16)) { + pVideoDec->nOperatingRate = (OMX_U32)INT_MAX; + pVideoDec->nQosRatio = 1000; + } else { + pVideoDec->nOperatingRate = (pConfigRate->nU32 >> 16) * 1000; + pVideoDec->nQosRatio = ((xFramerate >> 16) == 0)? 100:(OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + } + + pVideoDec->bQosChanged = OMX_TRUE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] set operating rate(0x%x), qos ratio(0x%x)", + pExynosComponent, __FUNCTION__, pVideoDec->nOperatingRate, pVideoDec->nQosRatio); + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexConfigPriority: + { + OMX_PARAM_U32TYPE *pPriority = (OMX_PARAM_U32TYPE *)pComponentConfigStructure; + OMX_U32 priority = 0; + + ret = Exynos_OMX_Check_SizeVersion(pPriority, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoDec->nPriority = pPriority->nU32;; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] priority : 0x%x", pExynosComponent, __FUNCTION__, pVideoDec->nPriority); + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexExynosConfigPTSMode: /* MSRND */ + { + pVideoDec->bDTSMode = ((*((OMX_BOOL *)pComponentConfigStructure)) == OMX_TRUE)? OMX_FALSE:OMX_TRUE; + ret = OMX_ErrorNone; + } + break; + case OMX_IndexConfigSearchBlackBar: + { + OMX_CONFIG_BOOLEANTYPE *pConfigSearchBlackBar = (OMX_CONFIG_BOOLEANTYPE *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pConfigSearchBlackBar, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoDec->bSearchBlackBar = pConfigSearchBlackBar->bEnabled; + pVideoDec->bSearchBlackBarChanged = OMX_TRUE; + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexConfigCommonInputCrop: + { + OMX_CONFIG_RECTTYPE *pSrcRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pDstRectType = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].cropRectangle[IMG_CROP_INPUT_PORT]); + + if (pSrcRectType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] image cropping is not enabled.", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bUseImgCrop[IMG_CROP_INPUT_PORT] = OMX_TRUE; + } + break; + case OMX_IndexConfigCommonOutputCrop: + { + OMX_CONFIG_RECTTYPE *pSrcRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pDstRectType = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].cropRectangle[IMG_CROP_OUTPUT_PORT]); + + if (pSrcRectType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + ret = OMX_ErrorIncorrectStateOperation; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] image cropping is not enabled.", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bUseImgCrop[IMG_CROP_OUTPUT_PORT] = OMX_TRUE; + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigVideoColorAspects: + { + ret = Exynos_OSAL_SetConfig(hComponent, nIndex, pComponentConfigStructure); + } + break; + case OMX_IndexConfigAndroidVendorExtension: + { + ret = Exynos_OSAL_SetVendorExt(hComponent, pComponentConfigStructure); + } + break; + case OMX_IndexConfigLowLatency: + { + OMX_CONFIG_BOOLEANTYPE *pConfigLowLatency = (OMX_CONFIG_BOOLEANTYPE *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pConfigLowLatency, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + /* nothing to do */ + + ret = OMX_ErrorNone; + } + break; +#endif + default: + ret = Exynos_OMX_SetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoDecodeGetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_NEED_CONTIG_MEMORY) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorNeedContigMemory; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_GET_BUFFER_FD) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorGetBufferFD; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_SET_DTS_MODE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorSetDTSMode; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_THUMBNAIL) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamEnableThumbnailMode; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_BLACK_BAR_CROP_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigBlackBarCrop; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_SEARCH_BLACK_BAR) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigSearchBlackBar; + goto EXIT; + } + +#ifdef USE_ANDROID + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_USE_ANB2) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamUseAndroidNativeBuffer2; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_GET_ANB) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamGetAndroidNativeBuffer; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_ANB) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamEnableAndroidBuffers; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_STORE_METADATA_BUFFER) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamStoreMetaDataBuffer; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ALLOCATE_NATIVE_HANDLE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamAllocateNativeHandle; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_DESCRIBE_COLOR_FORMAT) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamDescribeColorFormat; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_COLOR_ASPECTS_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoColorAspects; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_HDR_STATIC_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoHdrStaticInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_SET_ANB_CONSUMER_USAGE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamAndroidNatvieBufferConsumerUsage; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_CONFIG_PTS_MODE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosConfigPTSMode; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_CORRUPTEDHEADER) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamCorruptedHeader; + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_OMX_GetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Shared_BufferToData( + EXYNOS_OMX_BASEPORT *pExynosPort, + EXYNOS_OMX_DATABUFFER *pUseBuffer, + EXYNOS_OMX_DATA *pData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((pExynosPort == NULL) || + (pUseBuffer == NULL) || + (pData == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((pUseBuffer->bufferHeader == NULL) || + (pUseBuffer->bufferHeader->pBuffer == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pExynosPort->exceptionFlag != GENERAL_STATE) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if (pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED) { + pData->buffer.addr[0] = pUseBuffer->bufferHeader->pBuffer; + } else { + /* metadata type */ + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + + if (pExynosPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) { + EXYNOS_OMX_LOCK_RANGE range; + OMX_U32 stride; + + range.nWidth = pExynosPort->portDefinition.format.video.nFrameWidth; + range.nHeight = pExynosPort->portDefinition.format.video.nFrameHeight; + range.eColorFormat = pExynosPort->portDefinition.format.video.eColorFormat; + stride = range.nWidth; + + ret = Exynos_OSAL_LockMetaData(pUseBuffer->bufferHeader->pBuffer, + range, + &stride, &bufferInfo, + pExynosPort->eMetaDataType); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s]: Failed to Exynos_OSAL_LockMetaData (err:0x%x)", + __FUNCTION__, ret); + goto EXIT; + } + } else { + ret = Exynos_OSAL_GetInfoFromMetaData(pUseBuffer->bufferHeader->pBuffer, + &bufferInfo, pExynosPort->eMetaDataType); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s]: Failed to Exynos_OSAL_GetInfoFromMetaData (err:0x%x)", + __FUNCTION__, ret); + goto EXIT; + } + } + + pData->buffer.addr[0] = bufferInfo.addr[0]; + pData->buffer.addr[1] = bufferInfo.addr[1]; + pData->buffer.addr[2] = bufferInfo.addr[2]; + + pData->buffer.fd[0] = bufferInfo.fd[0]; + pData->buffer.fd[1] = bufferInfo.fd[1]; + pData->buffer.fd[2] = bufferInfo.fd[2]; + } + + pData->allocSize = pUseBuffer->allocSize; + pData->dataLen = pUseBuffer->dataLen; + pData->usedDataLen = pUseBuffer->usedDataLen; + pData->remainDataLen = pUseBuffer->remainDataLen; + pData->timeStamp = pUseBuffer->timeStamp; + pData->nFlags = pUseBuffer->nFlags; + pData->pPrivate = pUseBuffer->pPrivate; + pData->bufferHeader = pUseBuffer->bufferHeader; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Shared_DataToBuffer( + EXYNOS_OMX_BASEPORT *pExynosPort, + EXYNOS_OMX_DATABUFFER *pUseBuffer, + EXYNOS_OMX_DATA *pData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((pExynosPort == NULL) || + (pUseBuffer == NULL) || + (pData == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((pData->bufferHeader == NULL) || + (pData->bufferHeader->pBuffer == NULL)) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pUseBuffer->bufferHeader = pData->bufferHeader; + pUseBuffer->allocSize = pData->allocSize; + pUseBuffer->dataLen = pData->dataLen; + pUseBuffer->usedDataLen = pData->usedDataLen; + pUseBuffer->remainDataLen = pData->remainDataLen; + pUseBuffer->timeStamp = pData->timeStamp; + pUseBuffer->nFlags = pData->nFlags; + pUseBuffer->pPrivate = pData->pPrivate; + + if (pExynosPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) + Exynos_OSAL_UnlockMetaData(pUseBuffer->bufferHeader->pBuffer, pExynosPort->eMetaDataType); + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/dec/Exynos_OMX_VdecControl.h b/openmax/component/video/dec/Exynos_OMX_VdecControl.h new file mode 100644 index 0000000..e5f22a3 --- /dev/null +++ b/openmax/component/video/dec/Exynos_OMX_VdecControl.h @@ -0,0 +1,117 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_VdecControl.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.5.0 + * @history + * 2012.02.20 : Create + * 2017.08.03 : Change event handling + */ + +#ifndef EXYNOS_OMX_VIDEO_DECODECONTROL +#define EXYNOS_OMX_VIDEO_DECODECONTROL + +#include "OMX_Component.h" +#include "Exynos_OMX_Def.h" +#include "Exynos_OSAL_Queue.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Basecomponent.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer); +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes); +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr); + +#ifdef TUNNELING_SUPPORT +OMX_ERRORTYPE Exynos_OMX_AllocateTunnelBuffer( + EXYNOS_OMX_BASEPORT *pOMXBasePort, + OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_FreeTunnelBuffer( + EXYNOS_OMX_BASEPORT *pOMXBasePort, + OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_ComponentTunnelRequest( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 nPort, + OMX_IN OMX_HANDLETYPE hTunneledComp, + OMX_IN OMX_U32 nTunneledPort, + OMX_INOUT OMX_TUNNELSETUPTYPE *pTunnelSetup); +#endif + +OMX_ERRORTYPE Exynos_OMX_VideoDecodeGetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR ComponentParameterStructure); +OMX_ERRORTYPE Exynos_OMX_VideoDecodeSetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR ComponentParameterStructure); +OMX_ERRORTYPE Exynos_OMX_VideoDecodeGetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure); +OMX_ERRORTYPE Exynos_OMX_VideoDecodeSetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure); +OMX_ERRORTYPE Exynos_OMX_VideoDecodeGetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType); + +OMX_ERRORTYPE Exynos_InputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATABUFFER *pDataBuffer); +OMX_ERRORTYPE Exynos_OutputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATABUFFER *pDataBuffer); +OMX_ERRORTYPE Exynos_OMX_BufferFlush(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex, OMX_BOOL bEvent); + +OMX_BUFFERHEADERTYPE *Exynos_OutputBufferGetQueue_Direct(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +OMX_ERRORTYPE Exynos_InputBufferGetQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +OMX_ERRORTYPE Exynos_OutputBufferGetQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); + +OMX_ERRORTYPE Exynos_CodecBufferEnQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 PortIndex, OMX_PTR data); +OMX_ERRORTYPE Exynos_CodecBufferDeQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 PortIndex, OMX_PTR *data); +OMX_ERRORTYPE Exynos_CodecBufferReset(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 PortIndex); + +OMX_ERRORTYPE Exynos_Shared_BufferToData(EXYNOS_OMX_BASEPORT *pExynosPort, EXYNOS_OMX_DATABUFFER *pUseBuffer, EXYNOS_OMX_DATA *pData); +OMX_ERRORTYPE Exynos_Shared_DataToBuffer(EXYNOS_OMX_BASEPORT *pExynosPort, EXYNOS_OMX_DATABUFFER *pUseBuffer, EXYNOS_OMX_DATA *pData); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/openmax/component/video/dec/NOTICE b/openmax/component/video/dec/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/dec/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/dec/h264/Android.mk b/openmax/component/video/dec/h264/Android.mk new file mode 100644 index 0000000..08bc301 --- /dev/null +++ b/openmax/component/video/dec/h264/Android.mk @@ -0,0 +1,97 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_H264dec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.AVC.Decoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_S3D_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_S3D_SUPPORT +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/dec \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_SKYPE_HD), true) +LOCAL_CFLAGS += -DUSE_SKYPE_HD +LOCAL_CFLAGS += -DBUILD_DEC +LOCAL_STATIC_LIBRARIES += libExynosOMX_SkypeHD_Dec +endif + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_SMALL_SECURE_MEMORY), true) +LOCAL_CFLAGS += -DUSE_SMALL_SECURE_MEMORY +endif + +ifeq ($(BOARD_USE_COMPRESSED_COLOR), true) +LOCAL_CFLAGS += -DUSE_COMPRESSED_COLOR +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/dec/h264/Exynos_OMX_H264dec.c b/openmax/component/video/dec/h264/Exynos_OMX_H264dec.c new file mode 100644 index 0000000..b2c8daf --- /dev/null +++ b/openmax/component/video/dec/h264/Exynos_OMX_H264dec.c @@ -0,0 +1,3865 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_H264dec.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Vdec.h" +#include "Exynos_OMX_VdecControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OMX_H264dec.h" +#include "ExynosVideoApi.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" + +#include "Exynos_OSAL_Platform.h" + +#include "VendorVideoAPI.h" + +#ifdef USE_SKYPE_HD +#include "Exynos_OSAL_SkypeHD.h" +#endif + +/* To use CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */ +/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_H264_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pH264Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Dec->hMFCH264Handle.profiles[nProfileCnt++] = OMX_VIDEO_AVCProfileBaseline; + pH264Dec->hMFCH264Handle.profiles[nProfileCnt++] = OMX_VIDEO_AVCProfileMain; + pH264Dec->hMFCH264Handle.profiles[nProfileCnt++] = OMX_VIDEO_AVCProfileHigh; + pH264Dec->hMFCH264Handle.profiles[nProfileCnt++] = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedBaseline; + pH264Dec->hMFCH264Handle.profiles[nProfileCnt++] = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedHigh; + pH264Dec->hMFCH264Handle.nProfileCnt = nProfileCnt; + + switch (pH264Dec->hMFCH264Handle.videoInstInfo.HwVersion) { + case MFC_1501: + case MFC_150: + pH264Dec->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel6; + break; + case MFC_1400: + case MFC_1410: + case MFC_140: + case MFC_130: + case MFC_120: + case MFC_1220: + case MFC_110: + case MFC_100: + case MFC_101: + pH264Dec->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel52; + break; + case MFC_80: + case MFC_90: + case MFC_1010: + case MFC_1120: + pH264Dec->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel51; + break; + case MFC_61: + case MFC_65: + case MFC_72: + case MFC_723: + case MFC_77: + case MFC_1011: + case MFC_1021: + pH264Dec->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel42; + break; + case MFC_51: + case MFC_78: + case MFC_78D: + case MFC_92: + case MFC_1020: + default: + pH264Dec->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel4; + break; + } + +EXIT: + + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + int nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pH264Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pH264Dec->hMFCH264Handle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pH264Dec->hMFCH264Handle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pH264Dec->hMFCH264Handle.maxLevel; +#else + while ((pH264Dec->hMFCH264Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pH264Dec->hMFCH264Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pH264Dec->hMFCH264Handle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pH264Dec->hMFCH264Handle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pH264Dec == NULL) + goto EXIT; + + while ((pH264Dec->hMFCH264Handle.maxLevel >> nLevelCnt++) > 0); + + if ((pH264Dec->hMFCH264Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pH264Dec->hMFCH264Handle.nProfileCnt; i++) { + if (pH264Dec->hMFCH264Handle.profiles[i] == pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + FunctionOut(); + + return (bProfileSupport && bLevelSupport); +} + +static OMX_ERRORTYPE GetCodecOutputPrivateData(OMX_PTR codecBuffer, OMX_PTR addr[], OMX_U32 size[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pCodecBuffer = NULL; + + if (codecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pCodecBuffer = (ExynosVideoBuffer *)codecBuffer; + + if (addr != NULL) { + addr[0] = pCodecBuffer->planes[0].addr; + addr[1] = pCodecBuffer->planes[1].addr; + addr[2] = pCodecBuffer->planes[2].addr; + } + + if (size != NULL) { + size[0] = pCodecBuffer->planes[0].allocSize; + size[1] = pCodecBuffer->planes[1].allocSize; + size[2] = pCodecBuffer->planes[2].allocSize; + } + +EXIT: + return ret; +} + +static OMX_BOOL Check_H264_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize) +{ + OMX_BOOL ret = OMX_FALSE; + + FunctionIn(); + + if (streamSize < 4) { + ret = OMX_FALSE; + goto EXIT; + } + + if ((pInputStream[0] == 0x00) && + (pInputStream[1] == 0x00) && + (pInputStream[2] == 0x00) && + (pInputStream[3] != 0x00) && + ((pInputStream[4] & 0x1F) != 0xB) && // F/W constraint : in case of EOS data, can't return a buffer + ((pInputStream[3] >> 3) == 0x00)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] NaluType : %d, 0x%x, 0x%x, 0x%x", __FUNCTION__, + (pInputStream[4] & 0x1F), pInputStream[3], pInputStream[4], pInputStream[5]); + ret = OMX_TRUE; + } else if ((pInputStream[0] == 0x00) && + (pInputStream[1] == 0x00) && + (pInputStream[2] != 0x00) && + ((pInputStream[3] & 0x1F) != 0xB) && // F/W constraint : in case of EOS data, can't return a buffer + ((pInputStream[2] >> 3) == 0x00)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] NaluType : %d, 0x%x, 0x%x, 0x%x", __FUNCTION__, + (pInputStream[3] & 0x1F), pInputStream[2], pInputStream[3], pInputStream[4]); + ret = OMX_TRUE; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pH264Dec == NULL) + goto EXIT; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pOutputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pH264Dec->hMFCH264Handle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pH264Dec->hMFCH264Handle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE H264CodecOpen(EXYNOS_H264DEC_HANDLE *pH264Dec, ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pH264Dec == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pDecOps = (ExynosVideoDecOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecOps)); + pInbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + pOutbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + + if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pH264Dec->hMFCH264Handle.pDecOps = pDecOps; + pH264Dec->hMFCH264Handle.pInbufOps = pInbufOps; + pH264Dec->hMFCH264Handle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pDecOps->nSize = sizeof(ExynosVideoDecOps); + pInbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + + if (Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for decoder ops */ + if ((pDecOps->Init == NULL) || (pDecOps->Finalize == NULL) || + (pDecOps->Get_ActualBufferCount == NULL) || +#ifdef USE_S3D_SUPPORT + (pDecOps->Enable_SEIParsing == NULL) || (pDecOps->Get_FramePackingInfo == NULL) || +#endif + (pDecOps->Set_FrameTag == NULL) || (pDecOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pH264Dec->hMFCH264Handle.hMFCHandle = pH264Dec->hMFCH264Handle.pDecOps->Init(pVideoInstInfo); + if (pH264Dec->hMFCH264Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + +#ifdef USE_S3D_SUPPORT + /* S3D: Enable SEI parsing to check Frame Packing */ + if (pDecOps->Enable_SEIParsing(pH264Dec->hMFCH264Handle.hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Enable SEI Parsing", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } +#endif + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pH264Dec->hMFCH264Handle.pDecOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pH264Dec->hMFCH264Handle.pInbufOps = NULL; + } + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pH264Dec->hMFCH264Handle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecClose(EXYNOS_H264DEC_HANDLE *pH264Dec) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pH264Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + + if (hMFCHandle != NULL) { + pDecOps->Finalize(hMFCHandle); + pH264Dec->hMFCH264Handle.hMFCHandle = NULL; + pH264Dec->hMFCH264Handle.bConfiguredMFCSrc = OMX_FALSE; + pH264Dec->hMFCH264Handle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Decoder(pDecOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pH264Dec->hMFCH264Handle.pOutbufOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pH264Dec->hMFCH264Handle.pInbufOps = NULL; + } + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pH264Dec->hMFCH264Handle.pDecOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecStart(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pH264Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pH264Dec->hMFCH264Handle.bConfiguredMFCSrc == OMX_TRUE)) { + pInbufOps->Run(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pH264Dec->hMFCH264Handle.bConfiguredMFCDst == OMX_TRUE)) { + pOutbufOps->Run(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecStop(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pH264Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) { + pInbufOps->Stop(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) { + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pOutbufOps->Stop(hMFCHandle); + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) + pOutbufOps->Clear_RegisteredBuffer(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecOutputBufferProcessRun(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pH264Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pH264Dec->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pH264Dec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pH264Dec->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pH264Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pH264Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pH264Dec->hMFCH264Handle.bConfiguredMFCDst == OMX_FALSE) { + Exynos_OSAL_SignalSet(pH264Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecReconfigAllBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + ExynosVideoDecBufferOps *pBufferOps = NULL; + + FunctionIn(); + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pH264Dec->bSourceStart == OMX_TRUE)) { + ret = OMX_ErrorNotImplemented; + goto EXIT; + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pH264Dec->bDestinationStart == OMX_TRUE)) { + pBufferOps = pH264Dec->hMFCH264Handle.pOutbufOps; + + if (pExynosPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /**********************************/ + /* Codec Buffer Free & Unregister */ + /**********************************/ + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pH264Dec->hMFCH264Handle.bConfiguredMFCDst = OMX_FALSE; + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = H264CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to H264CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType == BUFFER_SHARE) { + /***************************/ + /* Codec Buffer Unregister */ + /***************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pH264Dec->hMFCH264Handle.bConfiguredMFCDst = OMX_FALSE; + } + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecEnQueueAllBuffer(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + + int i; + + ExynosVideoDecBufferOps *pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecInputBuffer[i]->fd[0], pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pH264Dec->hMFCH264Handle.bConfiguredMFCDst == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pH264Dec->hMFCH264Handle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecOutputBuffer[i]->fd[0], pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + +#ifdef USE_S3D_SUPPORT +OMX_BOOL H264CodecCheckFramePacking(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoFramePacking framePacking; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + OMX_BOOL ret = OMX_FALSE; + + FunctionIn(); + + /* Get Frame packing information*/ + if (pDecOps->Get_FramePackingInfo(pH264Dec->hMFCH264Handle.hMFCHandle, &framePacking) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Get Frame Packing Information", pExynosComponent, __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + + if (framePacking.available) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] arrangement ID: 0x%08x", + pExynosComponent, __FUNCTION__, framePacking.arrangement_id); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] arrangement_type: %d", + pExynosComponent, __FUNCTION__, framePacking.arrangement_type); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] content_interpretation_type: %d", + pExynosComponent, __FUNCTION__, framePacking.content_interpretation_type); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] current_frame_is_frame0_flag: %d", + pExynosComponent, __FUNCTION__, framePacking.current_frame_is_frame0_flag); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] spatial_flipping_flag: %d", + pExynosComponent, __FUNCTION__, framePacking.spatial_flipping_flag); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] fr0X:%d fr0Y:%d fr0X:%d fr0Y:%d", + pExynosComponent, __FUNCTION__, framePacking.frame0_grid_pos_x, + framePacking.frame0_grid_pos_y, framePacking.frame1_grid_pos_x, framePacking.frame1_grid_pos_y); + + pH264Dec->hMFCH264Handle.S3DFPArgmtType = (EXYNOS_OMX_FPARGMT_TYPE) framePacking.arrangement_type; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventS3DInformation)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back - output color format change */ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + (OMX_EVENTTYPE)OMX_EventS3DInformation, /* The command was completed */ + OMX_TRUE, /* S3D is enabled */ + (OMX_S32)pH264Dec->hMFCH264Handle.S3DFPArgmtType, /* S3D FPArgmtType */ + NULL); + + Exynos_OSAL_SleepMillisec(0); + } else { + pH264Dec->hMFCH264Handle.S3DFPArgmtType = OMX_SEC_FPARGMT_NONE; + } + + ret = OMX_TRUE; + +EXIT: + FunctionOut(); + + return ret; +} +#endif + +void H264CodecUpdateHdrInfo(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoHdrInfo *pHdrInfo = &(pH264Dec->hMFCH264Handle.sHdrInfo); + + if (pDecOps->Get_HDRInfo(hMFCHandle, pHdrInfo) == VIDEO_ERROR_NONE) { + /* update bitstream's info to input port */ + EXYNOS_OMX_VIDEO_HDRSTATICINFO *pHDRStaticInfo = &(pOutputPort->HDRStaticInfo); + EXYNOS_OMX_VIDEO_COLORASPECTS *pColorAspects = &(pInputPort->ColorAspects); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eType(0x%x) is changed", pExynosComponent, __FUNCTION__, pHdrInfo->eChangedType); + + /* color aspects */ + if (pHdrInfo->eValidType & (HDR_INFO_COLOR_ASPECTS | HDR_INFO_RANGE)) { + /* HDR_INFO_COLOR_ASPECTS (8) */ + pColorAspects->nCoeffType = pHdrInfo->sColorAspects.eCoeffType; + pColorAspects->nPrimaryType = pHdrInfo->sColorAspects.ePrimariesType; + pColorAspects->nTransferType = pHdrInfo->sColorAspects.eTransferType; + + /* HDR_INFO_RANGE (16) */ + pColorAspects->nRangeType = pHdrInfo->sColorAspects.eRangeType; + + if (pOutputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) { + /* update dataspace in output port from input port */ + Exynos_OSAL_UpdateDataSpaceFromBitstream(pExynosComponent); + } + } + + /* hdr static info */ + if (pHdrInfo->eValidType & (HDR_INFO_LIGHT | HDR_INFO_LUMINANCE)) { + /* HDR_INFO_LIGHT (1) */ + pHDRStaticInfo->nMaxPicAverageLight = pHdrInfo->sHdrStatic.max_pic_average_light; + pHDRStaticInfo->nMaxContentLight = pHdrInfo->sHdrStatic.max_content_light; + + /* HDR_INFO_LUMINANCE (2) */ + pHDRStaticInfo->nMaxDisplayLuminance = pHdrInfo->sHdrStatic.max_display_luminance; + pHDRStaticInfo->nMinDisplayLuminance = pHdrInfo->sHdrStatic.min_display_luminance; + + pHDRStaticInfo->red.x = pHdrInfo->sHdrStatic.red.x; + pHDRStaticInfo->red.y = pHdrInfo->sHdrStatic.red.y; + + pHDRStaticInfo->green.x = pHdrInfo->sHdrStatic.green.x; + pHDRStaticInfo->green.y = pHdrInfo->sHdrStatic.green.y; + + pHDRStaticInfo->blue.x = pHdrInfo->sHdrStatic.blue.x; + pHDRStaticInfo->blue.y = pHdrInfo->sHdrStatic.blue.y; + + pHDRStaticInfo->white.x = pHdrInfo->sHdrStatic.white.x; + pHDRStaticInfo->white.y = pHdrInfo->sHdrStatic.white.y; + } + +#ifdef USE_ANDROID + /* if both have changed, should send an event once */ + if (pHdrInfo->eChangedType & (HDR_INFO_COLOR_ASPECTS | HDR_INFO_RANGE)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_IndexConfigVideoColorAspects)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigVideoColorAspects, + NULL); + } +#if 0 /* OMX_IndexConfigVideoHdrStaticInfo is not supported yet */ + else if (pHdrInfo->eChangedType & (HDR_INFO_LIGHT | HDR_INFO_LUMINANCE)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_IndexConfigVideoHdrStaticInfo)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigVideoHdrStaticInfo, + NULL); + } +#endif +#endif + } + +EXIT: + return; +} + +OMX_ERRORTYPE H264CodecUpdateExtraInfo( + OMX_COMPONENTTYPE *pOMXComponent, + ExynosVideoMeta *pMeta) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + + if (pMeta == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMeta->eType = VIDEO_INFO_TYPE_INVALID; + + /* interlace */ + { + if (pH264Dec->hMFCH264Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] interlace type = %x", + pExynosComponent, __FUNCTION__, pH264Dec->hMFCH264Handle.interlacedType); + pMeta->eType |= VIDEO_INFO_TYPE_INTERLACED; + pMeta->data.dec.nInterlacedType = pH264Dec->hMFCH264Handle.interlacedType; + } + } + + /* HDR */ + { + ExynosType1 *pMetaHDR = &(pMeta->sHdrStaticInfo.sType1); + ExynosColorAspects *pMetaCA = &(pMeta->sColorAspects); + + if (pH264Dec->hMFCH264Handle.sHdrInfo.eValidType & (HDR_INFO_COLOR_ASPECTS | HDR_INFO_RANGE)) { + ExynosVideoColorAspects *pColorAspects = &(pH264Dec->hMFCH264Handle.sHdrInfo.sColorAspects); + + pMetaCA->mMatrixCoeffs = pColorAspects->eCoeffType; + pMetaCA->mPrimaries = pColorAspects->ePrimariesType; + pMetaCA->mTransfer = pColorAspects->eTransferType; + pMetaCA->mRange = pColorAspects->eRangeType; + + //pMeta->eType |= VIDEO_INFO_TYPE_COLOR_ASPECTS; + } + + if (pH264Dec->hMFCH264Handle.sHdrInfo.eValidType & (HDR_INFO_LIGHT | HDR_INFO_LUMINANCE)) { + ExynosVideoHdrStatic *pHDRStaticInfo = &(pH264Dec->hMFCH264Handle.sHdrInfo.sHdrStatic); + + /* HDR_INFO_LIGHT (1) */ + pMetaHDR->mMaxFrameAverageLightLevel = pHDRStaticInfo->max_pic_average_light; + pMetaHDR->mMaxContentLightLevel = pHDRStaticInfo->max_content_light; + + /* HDR_INFO_LUMINANCE (2) */ + pMetaHDR->mMaxDisplayLuminance = pHDRStaticInfo->max_display_luminance; + pMetaHDR->mMinDisplayLuminance = pHDRStaticInfo->min_display_luminance; + + pMetaHDR->mR.x = pHDRStaticInfo->red.x; + pMetaHDR->mR.y = pHDRStaticInfo->red.y; + + pMetaHDR->mG.x = pHDRStaticInfo->green.x; + pMetaHDR->mG.y = pHDRStaticInfo->green.y; + + pMetaHDR->mB.x = pHDRStaticInfo->blue.x; + pMetaHDR->mB.y = pHDRStaticInfo->blue.y; + + pMetaHDR->mW.x = pHDRStaticInfo->white.x; + pMetaHDR->mW.y = pHDRStaticInfo->white.y; + + pMeta->eType |= VIDEO_INFO_TYPE_HDR_STATIC; + } + } + + /* Normal format for SBWC black bar */ + { + if (pH264Dec->hMFCH264Handle.nActualFormat != 0) { + pMeta->nPixelFormat = pH264Dec->hMFCH264Handle.nActualFormat; + pMeta->eType |= VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT; + + pH264Dec->hMFCH264Handle.nActualFormat = 0; + } else { + pMeta->nPixelFormat = 0; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE H264CodecUpdateBlackBarCrop(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + OMX_CONFIG_RECTTYPE *pBlackBarCropRect = &pVideoDec->blackBarCropRect; + + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + ExynosVideoRect CropRect; + + FunctionIn(); + + Exynos_OSAL_Memset(&CropRect, 0, sizeof(ExynosVideoRect)); + if (pOutbufOps->Get_BlackBarCrop(hMFCHandle, &CropRect) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get crop info", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + + pBlackBarCropRect->nLeft = CropRect.nLeft; + pBlackBarCropRect->nTop = CropRect.nTop; + pBlackBarCropRect->nWidth = CropRect.nWidth; + pBlackBarCropRect->nHeight = CropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Black Bar Info: LEFT(%d) TOP(%d) WIDTH(%d) HEIGHT(%d)", + pExynosComponent, __FUNCTION__, + pBlackBarCropRect->nLeft, pBlackBarCropRect->nTop, + pBlackBarCropRect->nWidth, pBlackBarCropRect->nHeight); + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + (OMX_INDEXTYPE)OMX_IndexConfigBlackBarCrop, + NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecCheckResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_EXCEPTION_STATE eOutputExcepState = pOutputPort->exceptionFlag; + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + + OMX_CONFIG_RECTTYPE *pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = &(pInputPort->portDefinition); + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = &(pOutputPort->portDefinition); + + int maxDPBNum = 0; + + FunctionIn(); + + /* get geometry */ + Exynos_OSAL_Memset(&codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to get geometry"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + maxDPBNum += EXTRA_DPB_NUM; + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + } + + /* resolution is changed */ + if ((codecOutbufConf.nFrameWidth != pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth) || + (codecOutbufConf.nFrameHeight != pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight) || + (codecOutbufConf.nStride != pH264Dec->hMFCH264Handle.codecOutbufConf.nStride) || +#if 0 // TODO: check posibility + (codecOutbufConf.eColorFormat != pH264Dec->hMFCH264Handle.codecOutbufConf.eColorFormat) || + (codecOutbufConf.eFilledDataType != pH264Dec->hMFCH264Handle.codecOutbufConf.eFilledDataType) || +#endif + (maxDPBNum != pH264Dec->hMFCH264Handle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth, + pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] DPB(%d), FORMAT(0x%x), TYPE(0x%x) -> DPB(%d), FORMAT(0x%x), TYPE(0x%x)", + pExynosComponent, __FUNCTION__, + pH264Dec->hMFCH264Handle.maxDPBNum, + pH264Dec->hMFCH264Handle.codecOutbufConf.eColorFormat, + pH264Dec->hMFCH264Handle.codecOutbufConf.eFilledDataType, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType); + + pInputPortDefinition->format.video.nFrameWidth = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = codecOutbufConf.nFrameHeight; + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = maxDPBNum; + pOutputPortDefinition->nBufferCountMin = maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* crop info of contents is changed */ + if ((codecOutbufConf.cropRect.nTop != pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nTop) || + (codecOutbufConf.cropRect.nLeft != pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nLeft) || + (codecOutbufConf.cropRect.nWidth != pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nWidth) || + (codecOutbufConf.cropRect.nHeight != pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nHeight)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nWidth, + pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nHeight, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + Exynos_OSAL_Memcpy(&pH264Dec->hMFCH264Handle.codecOutbufConf, &codecOutbufConf, sizeof(codecOutbufConf)); + pH264Dec->hMFCH264Handle.maxDPBNum = maxDPBNum; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + + OMX_CONFIG_RECTTYPE *pCropRectangle = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = NULL; + + OMX_BOOL bFormatChanged = OMX_FALSE; + + FunctionIn(); + + /* get geometry for output */ + Exynos_OSAL_Memset(&pH264Dec->hMFCH264Handle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pH264Dec->hMFCH264Handle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + pH264Dec->hMFCH264Handle.maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + pH264Dec->hMFCH264Handle.maxDPBNum += EXTRA_DPB_NUM; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] maxDPBNum: %d", pExynosComponent, __FUNCTION__, pH264Dec->hMFCH264Handle.maxDPBNum); + + /* get interlace info */ + if (pH264Dec->hMFCH264Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] contents is interlaced type", pExynosComponent, __FUNCTION__); + + pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] past info: width(%d) height(%d)", + pExynosComponent, __FUNCTION__, + pInputPortDefinition->format.video.nFrameWidth, + pInputPortDefinition->format.video.nFrameHeight); + + /* output format is changed internally (8bit <> 10bit) */ + if (pH264Dec->hMFCH264Handle.MFCOutputColorType != pH264Dec->hMFCH264Handle.codecOutbufConf.eColorFormat) { + OMX_COLOR_FORMATTYPE eOutputFormat = Exynos_OSAL_Video2OMXFormat(pH264Dec->hMFCH264Handle.codecOutbufConf.eColorFormat); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] The format(%x) is changed to %x by H/W Codec", + pExynosComponent, __FUNCTION__, + pH264Dec->hMFCH264Handle.MFCOutputColorType, + pH264Dec->hMFCH264Handle.codecOutbufConf.eColorFormat); + + pH264Dec->hMFCH264Handle.MFCOutputColorType = pH264Dec->hMFCH264Handle.codecOutbufConf.eColorFormat; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pOutputPort->ePlaneType)); + + bFormatChanged = OMX_TRUE; + + if (!(pH264Dec->hMFCH264Handle.codecOutbufConf.eFilledDataType & DATA_TYPE_8BIT_SBWC)) { + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* SBWC to non SBWC : must update eColorFormat */ + pOutputPort->portDefinition.format.video.eColorFormat = eOutputFormat; + } + + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } else { + pVideoDec->nCompColorFormat = eOutputFormat; + } + } + + switch (pH264Dec->hMFCH264Handle.codecOutbufConf.eFilledDataType) { + case DATA_8BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_8BIT_SBWC; + break; + case DATA_10BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_10BIT_SBWC; + break; + default: + pVideoDec->eDataType = DATA_TYPE_8BIT; + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] resolution info: width(%d / %d), height(%d / %d)", + pExynosComponent, __FUNCTION__, + pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth, + pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nWidth, + pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight, + pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nHeight); + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nHeight; + } + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight; +#if 0 + /* don't need to change */ + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; +#endif + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } else if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPortDefinition->nBufferCountActual != pH264Dec->hMFCH264Handle.maxDPBNum) || + ((OMX_S32)pOutputPortDefinition->nBufferCountMin < pH264Dec->hMFCH264Handle.maxDPBNum)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight; + + pOutputPortDefinition->nBufferCountActual = pH264Dec->hMFCH264Handle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pH264Dec->hMFCH264Handle.maxDPBNum; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* contents has crop info */ + if ((pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth != pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nWidth) || + (pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight != pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nHeight)) { + + if ((pOutputPort->bufferProcessType & BUFFER_COPY) && + (pExynosComponent->bUseImgCrop == OMX_TRUE)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + } + + pInputPortDefinition->format.video.nFrameWidth = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged) with crop", + pExynosComponent, __FUNCTION__); + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecHeaderDecoding(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecBufferOps *pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + + FunctionIn(); + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + nAllocLen[0] = pSrcInputData->allocSize; + } + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enqueue input buffer for header parsing", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* start header parsing */ + if (pInbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run input buffer for header parsing", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* get geometry for output */ + Exynos_OSAL_Memset(&pH264Dec->hMFCH264Handle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pH264Dec->hMFCH264Handle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedHeader; + + if ((pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", pExynosComponent, __FUNCTION__, + *((OMX_U8 *)pSrcInputData->buffer.addr[0]) , *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 1), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 2), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 3), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 4), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 5), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 6), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 7)); + } + + pInbufOps->Stop(hMFCHandle); + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecSrcSetup(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 allocFrameSize = 0; + OMX_COLOR_FORMATTYPE eOutputFormat = pExynosOutputPort->portDefinition.format.video.eColorFormat; + + EXYNOS_OMX_VIDEO_HDRSTATICINFO *pHDRStaticInfo = &(pExynosOutputPort->HDRStaticInfo); + EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA = &(pExynosOutputPort->ColorAspects); + EXYNOS_OMX_VIDEO_COLORASPECTS *pBSCA = &(pExynosInputPort->ColorAspects); + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + + FunctionIn(); + + if ((pSrcInputData->dataLen <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pH264Dec->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pH264Dec->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SignalSet(pH264Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pVideoDec->bThumbnailMode == OMX_TRUE) + pDecOps->Set_IFrameDecoding(hMFCHandle); + else if ((IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) && + (pH264Dec->hMFCH264Handle.nDisplayDelay <= MAX_H264_DISPLAYDELAY_VALIDNUM)) { + pDecOps->Set_DisplayDelay(hMFCHandle, (int)pH264Dec->hMFCH264Handle.nDisplayDelay); + } + +#ifdef USE_SKYPE_HD + if (pH264Dec->hMFCH264Handle.bLowLatency == OMX_TRUE) + pDecOps->Set_DisplayDelay(hMFCHandle, 0); +#endif + + if ((pDecOps->Enable_DTSMode != NULL) && + (pVideoDec->bDTSMode == OMX_TRUE)) + pDecOps->Enable_DTSMode(hMFCHandle); + + if (pH264Dec->hMFCH264Handle.videoInstInfo.supportInfo.dec.bPrioritySupport == VIDEO_TRUE) + pDecOps->Set_Priority(hMFCHandle, pVideoDec->nPriority); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eCompressionFormat = VIDEO_CODING_AVC; + pInbufOps->Set_Shareable(hMFCHandle); + + allocFrameSize = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + allocFrameSize = pSrcInputData->allocSize; + } + + bufferConf.nSizeImage = allocFrameSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + nInBufferCnt = MAX_INPUTBUFFER_NUM_DYNAMIC; + + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + +#ifdef USE_COMPRESSED_COLOR + if ((pExynosOutputPort->eMetaDataType != METADATA_TYPE_GRAPHIC) || + (pExynosOutputPort->bForceUseNonCompFormat == OMX_TRUE)) { + /* use SBWC format only ANB scenario */ + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } +#endif + + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* For SBWC format setting */ + bSupportFormat = CheckFormatHWSupport(pExynosComponent, pVideoDec->nCompColorFormat); + if (bSupportFormat == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] set compressed color format(0x%x)", + pExynosComponent, __FUNCTION__, (OMX_U32)pVideoDec->nCompColorFormat); + + eOutputFormat = pVideoDec->nCompColorFormat; + } + } + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] omx format(0x%x) is %s by h/w", + pExynosComponent, __FUNCTION__, eOutputFormat, + (bSupportFormat == OMX_TRUE)? "supported":"not supported"); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eOutputFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pExynosOutputPort->ePlaneType)); + } else { + OMX_COLOR_FORMATTYPE eCheckFormat = OMX_SEC_COLOR_FormatNV12Tiled; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + if (bSupportFormat != OMX_TRUE) { + eCheckFormat = OMX_COLOR_FormatYUV420SemiPlanar; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + } + if (bSupportFormat == OMX_TRUE) { /* supported by CSC(NV12T/NV12 -> format) */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eCheckFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eCheckFormat, pExynosOutputPort->ePlaneType)); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not support this format (0x%x)", pExynosComponent, __FUNCTION__, eOutputFormat); + ret = OMX_ErrorNotImplemented; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + } + + pH264Dec->hMFCH264Handle.MFCOutputColorType = bufferConf.eColorFormat; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output video format is 0x%x", + pExynosComponent, __FUNCTION__, bufferConf.eColorFormat); + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + ret = H264CodecHeaderDecoding(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + pH264Dec->hMFCH264Handle.bConfiguredMFCSrc = OMX_TRUE; + + H264CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + ret = H264CodecUpdateResolution(pOMXComponent); + if (ret != OMX_ErrorNone) { + pH264Dec->hMFCH264Handle.bConfiguredMFCSrc = OMX_FALSE; + H264CodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] first frame will be re-pushed to input", pExynosComponent, __FUNCTION__); + + H264CodecStop(pOMXComponent, INPUT_PORT_INDEX); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nOutbufs, nPlaneCnt; + + FunctionIn(); + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = pH264Dec->hMFCH264Handle.codecOutbufConf.nAlignPlaneSize[i]; + + H264CodecStop(pOMXComponent, OUTPUT_PORT_INDEX); + + /* for adaptive playback */ + if (pH264Dec->hMFCH264Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enable Dynamic DPB", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* get dpb count */ + nOutbufs = pH264Dec->hMFCH264Handle.maxDPBNum; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + + pH264Dec->hMFCH264Handle.bConfiguredMFCDst = OMX_TRUE; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->eMetaDataType == METADATA_TYPE_DISABLED) { + /*************/ + /* TBD */ + /*************/ + /* data buffer : user buffer + * H/W can't accept user buffer directly + */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pH264Dec->hMFCH264Handle.bConfiguredMFCDst = OMX_TRUE; + } + + if (H264CodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = (OMX_VIDEO_PARAM_AVCTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCTYPE *pSrcAVCComponent = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstAVCComponent, sizeof(OMX_VIDEO_PARAM_AVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstAVCComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcAVCComponent = &pH264Dec->AVCComponent[pDstAVCComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstAVCComponent) + nOffset, + ((char *)pSrcAVCComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_AVCTYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H264_DEC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCTYPE *pSrcAVCComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcAVCComponent = &pH264Dec->AVCComponent[pDstProfileLevel->nPortIndex]; + + pDstProfileLevel->eProfile = pSrcAVCComponent->eProfile; + pDstProfileLevel->eLevel = pSrcAVCComponent->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pH264Dec->errorCorrectionType[INPUT_PORT_INDEX]; + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexExynosParamDisplayDelay: /* MSRND */ + { + OMX_PARAM_U32TYPE *pDisplayDelay = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDisplayDelay, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDisplayDelay->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDisplayDelay->nU32 = pH264Dec->hMFCH264Handle.nDisplayDelay; + } + break; + case OMX_IndexExynosParamReorderMode: + { + EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *pReorderParam = (EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pReorderParam, sizeof(EXYNOS_OMX_VIDEO_PARAM_REORDERMODE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pReorderParam->bReorderMode = pVideoDec->bReorderMode; + } + break; + default: +#ifdef USE_SKYPE_HD + ret = Exynos_H264Dec_GetParameter_SkypeHD(hComponent, nParamIndex, pComponentParameterStructure); + if (ret != OMX_ErrorNone) +#endif + ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = NULL; + OMX_VIDEO_PARAM_AVCTYPE *pSrcAVCComponent = (OMX_VIDEO_PARAM_AVCTYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcAVCComponent, sizeof(OMX_VIDEO_PARAM_AVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcAVCComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstAVCComponent = &pH264Dec->AVCComponent[pSrcAVCComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstAVCComponent) + nOffset, + ((char *)pSrcAVCComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_AVCTYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H264_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstAVCComponent = &pH264Dec->AVCComponent[pSrcProfileLevel->nPortIndex]; + + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstAVCComponent->eProfile = pSrcProfileLevel->eProfile; + pDstAVCComponent->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pH264Dec->errorCorrectionType[INPUT_PORT_INDEX]; + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexExynosParamDisplayDelay: /* MSRND */ + { + OMX_PARAM_U32TYPE *pDisplayDelay = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDisplayDelay, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDisplayDelay->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + if (pDisplayDelay->nU32 > MAX_H264_DISPLAYDELAY_VALIDNUM) { + ret = OMX_ErrorBadParameter; + break; + } + + pH264Dec->hMFCH264Handle.nDisplayDelay = pDisplayDelay->nU32; + } + break; + case OMX_IndexExynosParamReorderMode: + { + EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *pReorderParam = (EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pReorderParam, sizeof(EXYNOS_OMX_VIDEO_PARAM_REORDERMODE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoDec->bReorderMode = pReorderParam->bReorderMode; + } + break; + default: +#ifdef USE_SKYPE_HD + ret = Exynos_H264Dec_SetParameter_SkypeHD(hComponent, nIndex, pComponentParameterStructure); + if (ret != OMX_ErrorNone) +#endif + ret = Exynos_OMX_VideoDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigCommonOutputCrop: + { + if (pExynosComponent->bUseImgCrop == OMX_TRUE) { + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + } else { + /* query crop information on bitstream */ + OMX_CONFIG_RECTTYPE *pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + + if (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pH264Dec->hMFCH264Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + goto EXIT; + } + + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pSrcRectType = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + } + break; +#ifdef USE_S3D_SUPPORT + case OMX_IndexVendorS3DMode: + { + OMX_U32 *pS3DMode = NULL; + + pS3DMode = (OMX_U32 *)pComponentConfigStructure; + *pS3DMode = (OMX_U32) pH264Dec->hMFCH264Handle.S3DFPArgmtType; + } + break; +#endif + case OMX_IndexExynosConfigDisplayDelay: /* MSRND */ + { + (*((OMX_U32 *)pComponentConfigStructure)) = pH264Dec->hMFCH264Handle.nDisplayDelay; + } + break; + default: + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexExynosConfigDisplayDelay: /* MSRND */ + { + OMX_U32 nDisplayDelay = (*((OMX_U32 *)pComponentConfigStructure)); + + if (pH264Dec->hMFCH264Handle.bConfiguredMFCSrc == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + break; + } + + if (nDisplayDelay > MAX_H264_DISPLAYDELAY_VALIDNUM) { + ret = OMX_ErrorBadParameter; + break; + } + + pH264Dec->hMFCH264Handle.nDisplayDelay = nDisplayDelay; + } + break; + default: + ret = Exynos_OMX_VideoDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + +#ifdef USE_S3D_SUPPORT + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_GET_S3D) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorS3DMode; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_REORDER_MODE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamReorderMode; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_CONFIG_DISPLAY_DELAY) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosConfigDisplayDelay; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_DISPLAY_DELAY) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamDisplayDelay; + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_OMX_VideoDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_H264_DEC_ROLE); + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_H264Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + + ExynosVideoInstInfo *pVideoInstInfo = &(pH264Dec->hMFCH264Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i; + + FunctionIn(); + + pH264Dec->hMFCH264Handle.bConfiguredMFCSrc = OMX_FALSE; + pH264Dec->hMFCH264Handle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pExynosInputPort->portDefinition.format.video.nFrameWidth, + pExynosInputPort->portDefinition.format.video.nFrameHeight, + pExynosInputPort->portDefinition.format.video.nBitrate, + pExynosInputPort->portDefinition.format.video.xFramerate); + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pExynosInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pExynosInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pExynosInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pExynosInputPort->portDefinition.format.video.xFramerate; + + /* H.264 Codec Open */ + ret = H264CodecOpen(pH264Dec, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + nAllocLen[0] = ALIGN(pExynosInputPort->portDefinition.format.video.nFrameWidth * + pExynosInputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + if (nAllocLen[0] < pVideoDec->nMinInBufSize) + nAllocLen[0] = pVideoDec->nMinInBufSize; + + Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX, MFC_INPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_SetPlaneToPort(pExynosOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SemaphoreCreate(&pExynosOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pH264Dec->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pH264Dec->hSourceStartEvent); + pH264Dec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pH264Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pH264Dec->hDestinationOutStartEvent); + + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pH264Dec->hMFCH264Handle.indexTimestamp = 0; + pH264Dec->hMFCH264Handle.outputIndexTimestamp = 0; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pH264Dec->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) { + pVideoDec->csc_handle = csc_init(CSC_METHOD_HW); + csc_set_hw_property(pVideoDec->csc_handle, CSC_HW_PROPERTY_FIXED_NODE, 2); + csc_set_hw_property(pVideoDec->csc_handle, CSC_HW_PROPERTY_MODE_DRM, 1); + } else { + pVideoDec->csc_handle = csc_init(csc_method); + } + + if (pVideoDec->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pVideoDec->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_H264Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoDec != NULL) { + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + if (pH264Dec != NULL) { + Exynos_OSAL_QueueTerminate(&pH264Dec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pH264Dec->hDestinationInStartEvent); + pH264Dec->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pH264Dec->hDestinationOutStartEvent); + pH264Dec->hDestinationOutStartEvent = NULL; + pH264Dec->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pH264Dec->hSourceStartEvent); + pH264Dec->hSourceStartEvent = NULL; + pH264Dec->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pH264Dec != NULL) { + H264CodecClose(pH264Dec); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_SrcIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + + OMX_BOOL bInStartCode = OMX_FALSE; + + FunctionIn(); + + if (pH264Dec->hMFCH264Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = H264CodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (pH264Dec->bDestinationStart == OMX_FALSE) && + (pH264Dec->hMFCH264Handle.bConfiguredMFCDst == OMX_FALSE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = H264CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to H264CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + } + + if (((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) || + ((bInStartCode = Check_H264_StartCode(pSrcInputData->buffer.addr[0], oneFrameSize)) == OMX_TRUE)) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + + if (pVideoDec->bReorderMode == OMX_FALSE) { + /* next slot will be used like as circular queue */ + pExynosComponent->timeStamp[pH264Dec->hMFCH264Handle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->nFlags[pH264Dec->hMFCH264Handle.indexTimestamp] = pSrcInputData->nFlags; + } else { /* MSRND */ + Exynos_SetReorderTimestamp(pExynosComponent, &(pH264Dec->hMFCH264Handle.indexTimestamp), pSrcInputData->timeStamp, pSrcInputData->nFlags); + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), dataLen(%d), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, oneFrameSize, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pH264Dec->hMFCH264Handle.indexTimestamp); + + pDecOps->Set_FrameTag(hMFCHandle, pH264Dec->hMFCH264Handle.indexTimestamp); + pH264Dec->hMFCH264Handle.indexTimestamp++; + pH264Dec->hMFCH264Handle.indexTimestamp %= MAX_TIMESTAMP; + + if (pVideoDec->bQosChanged == OMX_TRUE) { + if (pH264Dec->hMFCH264Handle.videoInstInfo.supportInfo.dec.bOperatingRateSupport == VIDEO_TRUE) { + if (pDecOps->Set_OperatingRate != NULL) + pDecOps->Set_OperatingRate(hMFCHandle, (pVideoDec->nOperatingRate)); + } else if (pDecOps->Set_QosRatio != NULL) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + } + + pVideoDec->bQosChanged = OMX_FALSE; + } + + if (pVideoDec->bSearchBlackBarChanged == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] BlackBar searching mode : %s", + pExynosComponent, __FUNCTION__, + (pVideoDec->bSearchBlackBar == OMX_TRUE) ? "enable" : "disable"); + pDecOps->Set_SearchBlackBar(hMFCHandle, (ExynosVideoBoolType)pVideoDec->bSearchBlackBar); + pVideoDec->bSearchBlackBarChanged = OMX_FALSE; + } + + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + pPrivate = (void *)pSrcInputData->bufferHeader; + } else { + nAllocLen[0] = pSrcInputData->allocSize; + + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + goto EXIT; + } + + H264CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + if (pH264Dec->bSourceStart == OMX_FALSE) { + pH264Dec->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pH264Dec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + if ((pH264Dec->bDestinationStart == OMX_FALSE) && + (pH264Dec->hMFCH264Handle.bConfiguredMFCDst == OMX_TRUE)) { + pH264Dec->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pH264Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pH264Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] can't find a start code", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedFrame; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_SrcOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + if (pH264Dec->hMFCH264Handle.bConfiguredMFCSrc == OMX_TRUE) { + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + else + pVideoBuffer = NULL; + } else { + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + pSrcOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]) { + pVideoDec->pMFCDecInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoDec->pMFCDecInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pExynosInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_DstIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) { + nAllocLen[i] = pH264Dec->hMFCH264Handle.codecOutbufConf.nAlignPlaneSize[i]; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] ADDR[%d]: 0x%x, size[%d]: %d", pExynosComponent, __FUNCTION__, + i, pDstInputData->buffer.addr[i], i, nAllocLen[i]); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + } + + goto EXIT; + } + + H264CodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_DstOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + ExynosVideoGeometry *bufferGeometry = NULL; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + ExynosVideoColorFormatType nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + OMX_COLOR_FORMATTYPE nOMXFormat = OMX_COLOR_FormatUnused; + OMX_U32 nPixelFormat = 0; + + FunctionIn(); + + if (pH264Dec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + Exynos_OSAL_Memset(&videoBuffer, 0, sizeof(ExynosVideoBuffer)); + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO) at ExtensionDequeue", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + displayStatus = pVideoBuffer->displayStatus; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus: 0x%x", pExynosComponent, __FUNCTION__, displayStatus); + + if ((displayStatus == VIDEO_FRAME_STATUS_DISPLAY_DECODING) || + (displayStatus == VIDEO_FRAME_STATUS_DISPLAY_ONLY) || + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_ENABLED_S3D) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + (CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + +#ifdef USE_S3D_SUPPORT + /* Check Whether frame packing information is available */ + if ((pH264Dec->hMFCH264Handle.S3DFPArgmtType == OMX_SEC_FPARGMT_INVALID) && + (pVideoDec->bThumbnailMode == OMX_FALSE) && + ((displayStatus == VIDEO_FRAME_STATUS_DISPLAY_ONLY) || + (displayStatus == VIDEO_FRAME_STATUS_DISPLAY_DECODING) || + (displayStatus == VIDEO_FRAME_STATUS_ENABLED_S3D))) { + if (H264CodecCheckFramePacking(pOMXComponent) != OMX_TRUE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } +#endif + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + ((displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (displayStatus == VIDEO_FRAME_STATUS_ENABLED_S3D))) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pOutputPort->exceptionFlag = NEED_PORT_FLUSH; + pVideoDec->bReconfigDPB = OMX_TRUE; + H264CodecUpdateResolution(pOMXComponent); + pVideoDec->csc_set_format = OMX_FALSE; +#ifdef USE_S3D_SUPPORT + pH264Dec->hMFCH264Handle.S3DFPArgmtType = OMX_SEC_FPARGMT_INVALID; +#endif + } + ret = OMX_ErrorNone; + goto EXIT; + } + + pH264Dec->hMFCH264Handle.outputIndexTimestamp++; + pH264Dec->hMFCH264Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->allocSize = pDstOutputData->dataLen = 0; + nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + + nDataLen[plane] = pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pH264Dec->hMFCH264Handle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->cropRect.nLeft = bufferGeometry->cropRect.nLeft; + pBufferInfo->cropRect.nTop = bufferGeometry->cropRect.nTop; + pBufferInfo->cropRect.nWidth = bufferGeometry->cropRect.nWidth; + pBufferInfo->cropRect.nHeight = bufferGeometry->cropRect.nHeight; + pBufferInfo->colorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + + /* calculate each plane info for the application */ + Exynos_OSAL_GetPlaneSize(pOutputPort->portDefinition.format.video.eColorFormat, + PLANE_SINGLE, pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + nDataLen, nAllocLen); + + pDstOutputData->allocSize = nAllocLen[0] + nAllocLen[1] + nAllocLen[2]; + pDstOutputData->dataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + /* update extra info */ + { + /* interlace */ + pH264Dec->hMFCH264Handle.interlacedType = pVideoBuffer->interlacedType; + + /* HDR */ + if (pVideoBuffer->frameType & VIDEO_FRAME_WITH_HDR_INFO) + H264CodecUpdateHdrInfo(pOMXComponent); + + /* SBWC Normal format */ + if (pVideoBuffer->frameType & VIDEO_FRAME_NEED_ACTUAL_FORMAT) { + nVideoFormat = pDecOps->Get_ActualFormat(hMFCHandle); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + nOMXFormat = Exynos_OSAL_Video2OMXFormat((int)nVideoFormat); + + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nPixelFormat = Exynos_OSAL_OMX2HALPixelFormat(nOMXFormat, pOutputPort->ePlaneType); + + if (nPixelFormat != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Normal format at SBWC is 0x%x", + pExynosComponent, __FUNCTION__, nPixelFormat); + pH264Dec->hMFCH264Handle.nActualFormat = nPixelFormat; + } + } + } + } + } + + /* update extra information to vendor path for renderer + * if BUFFER_COPY_FORCE is used, it will be updated at Exynos_CSC_OutputData() + */ + if ((pOutputPort->bufferProcessType == BUFFER_SHARE) && + (pVideoBuffer->planes[2].addr != NULL)) { + H264CodecUpdateExtraInfo(pOMXComponent, pVideoBuffer->planes[2].addr); + } + + indexTimestamp = pDecOps->Get_FrameTag(hMFCHandle); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + + if (pVideoDec->bReorderMode == OMX_FALSE) { + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if ((pExynosComponent->checkTimeStamp.needSetStartTimeStamp != OMX_TRUE) && + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp != OMX_TRUE)) { + if (indexTimestamp == INDEX_AFTER_EOS) { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } else { + pDstOutputData->timeStamp = pExynosComponent->timeStamp[pH264Dec->hMFCH264Handle.outputIndexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[pH264Dec->hMFCH264Handle.outputIndexTimestamp]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] missing out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + } + } else { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } + } else { + /* For timestamp correction. if mfc support frametype detect */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] disp_pic_frame_type: %d", pExynosComponent, __FUNCTION__, pVideoBuffer->frameType); + + /* NEED TIMESTAMP REORDER */ + if (pVideoDec->bDTSMode == OMX_TRUE) { + if ((pVideoBuffer->frameType & VIDEO_FRAME_I) || + ((pVideoBuffer->frameType & VIDEO_FRAME_OTHERS) && + ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) || + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE)) + pH264Dec->hMFCH264Handle.outputIndexTimestamp = indexTimestamp; + else + indexTimestamp = pH264Dec->hMFCH264Handle.outputIndexTimestamp; + } + + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp] | OMX_BUFFERFLAG_ENDOFFRAME; + + if (pVideoBuffer->frameType & VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + } else { /* MSRND */ + EXYNOS_OMX_CURRENT_FRAME_TIMESTAMP sCurrentTimestamp; + + Exynos_GetReorderTimestamp(pExynosComponent, &sCurrentTimestamp, indexTimestamp, pVideoBuffer->frameType); + + pDstOutputData->timeStamp = sCurrentTimestamp.timeStamp; + pDstOutputData->nFlags = sCurrentTimestamp.nFlags | OMX_BUFFERFLAG_ENDOFFRAME; + + pExynosComponent->nFlags[sCurrentTimestamp.nIndex] = 0x00; + pExynosComponent->bTimestampSlotUsed[sCurrentTimestamp.nIndex] = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), reordered tag: %d, original tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + sCurrentTimestamp.nIndex, + indexTimestamp); + } + + if (pVideoBuffer->frameType & VIDEO_FRAME_WITH_BLACK_BAR) { + if (H264CodecUpdateBlackBarCrop(pOMXComponent) != OMX_ErrorNone) + goto EXIT; + } + + if (pVideoBuffer->frameType & VIDEO_FRAME_CONCEALMENT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + if (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) { + pDstOutputData->remainDataLen = 0; + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp != INDEX_AFTER_EOS) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] tag(%d) is wrong", pExynosComponent, __FUNCTION__, indexTimestamp); + + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + goto EXIT; + } + + if ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) || + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->nFlags[indexTimestamp] &= (~OMX_BUFFERFLAG_EOS); + } + } else if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + pDstOutputData->remainDataLen = 0; + + if (pExynosComponent->bBehaviorEOS == OMX_TRUE) { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_srcInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + ret = Exynos_H264Dec_SrcIn(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorInputDataDecodeYet) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorCorruptedFrame)) { + + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pVideoDec->bDiscardCSDError == OMX_TRUE)) { + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_srcOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if ((pH264Dec->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosInputPort))) { + Exynos_OSAL_SignalWait(pH264Dec->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pH264Dec->hSourceStartEvent); + } + + ret = Exynos_H264Dec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_dstInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + if (pExynosComponent->currentState == OMX_StatePause) + ret = (OMX_ERRORTYPE)OMX_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pH264Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pH264Dec->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pH264Dec->hDestinationInStartEvent); + } + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pH264Dec->bypassBufferInfoQ) > 0) { + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pH264Dec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = H264CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to H264CodecDstSetup(0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + Exynos_OSAL_SignalSet(pH264Dec->hDestinationOutStartEvent); + } + } + + if (pH264Dec->hMFCH264Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_H264Dec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + if ((pH264Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_dstOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (((pH264Dec->bDestinationStart == OMX_FALSE) || + (pH264Dec->hMFCH264Handle.bConfiguredMFCDst == OMX_FALSE)) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pH264Dec->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pH264Dec->hDestinationOutStartEvent); + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if (Exynos_OSAL_GetElemNum(&pH264Dec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pH264Dec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_H264Dec_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && + (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + OMX_BOOL bSecureMode = OMX_FALSE; + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H264_DEC, componentName) == 0) { + bSecureMode = OMX_FALSE; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H264_DRM_DEC, componentName) == 0) { + bSecureMode = OMX_TRUE; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = (bSecureMode == OMX_TRUE)? HW_VIDEO_DEC_SECURE_CODEC:HW_VIDEO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pH264Dec = Exynos_OSAL_Malloc(sizeof(EXYNOS_H264DEC_HANDLE)); + if (pH264Dec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pH264Dec, 0, sizeof(EXYNOS_H264DEC_HANDLE)); + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoDec->hCodecHandle = (OMX_HANDLETYPE)pH264Dec; + + Exynos_OSAL_Strcpy(pExynosComponent->componentName, componentName); + +#ifdef USE_S3D_SUPPORT + pH264Dec->hMFCH264Handle.S3DFPArgmtType = OMX_SEC_FPARGMT_INVALID; +#endif + pH264Dec->hMFCH264Handle.nDisplayDelay = MAX_H264_DISPLAYDELAY_VALIDNUM + 1; + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pExynosPort->portDefinition.nBufferSize = CUSTOM_LIMITED_DRM_INPUT_BUFFER_SIZE; + else +#endif + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + } + + pVideoDec->nMinInBufSize = DEFAULT_VIDEO_MIN_INPUT_BUFFER_SIZE; /* for DRC */ + + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/avc"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + +#ifdef USE_SINGLE_PLANE_IN_DRM + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pExynosPort->ePlaneType = PLANE_SINGLE; +#endif + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pH264Dec->AVCComponent[i], OMX_VIDEO_PARAM_AVCTYPE); + pH264Dec->AVCComponent[i].nPortIndex = i; + pH264Dec->AVCComponent[i].eProfile = OMX_VIDEO_AVCProfileBaseline; + pH264Dec->AVCComponent[i].eLevel = OMX_VIDEO_AVCLevel4; + } + + pOMXComponent->GetParameter = &Exynos_H264Dec_GetParameter; + pOMXComponent->SetParameter = &Exynos_H264Dec_SetParameter; + pOMXComponent->GetConfig = &Exynos_H264Dec_GetConfig; + pOMXComponent->SetConfig = &Exynos_H264Dec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_H264Dec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_H264Dec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_H264Dec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_H264Dec_Terminate; + + pVideoDec->exynos_codec_srcInputProcess = &Exynos_H264Dec_srcInputBufferProcess; + pVideoDec->exynos_codec_srcOutputProcess = &Exynos_H264Dec_srcOutputBufferProcess; + pVideoDec->exynos_codec_dstInputProcess = &Exynos_H264Dec_dstInputBufferProcess; + pVideoDec->exynos_codec_dstOutputProcess = &Exynos_H264Dec_dstOutputBufferProcess; + + pVideoDec->exynos_codec_start = &H264CodecStart; + pVideoDec->exynos_codec_stop = &H264CodecStop; + pVideoDec->exynos_codec_bufferProcessRun = &H264CodecOutputBufferProcessRun; + pVideoDec->exynos_codec_enqueueAllBuffer = &H264CodecEnQueueAllBuffer; + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &H264CodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &H264CodecCheckResolution; + + pVideoDec->exynos_codec_updateExtraInfo = &H264CodecUpdateExtraInfo; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pH264Dec); + pH264Dec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pH264Dec->hMFCH264Handle.videoInstInfo.eCodecType = VIDEO_CODING_AVC; + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pH264Dec->hMFCH264Handle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pH264Dec->hMFCH264Handle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + if (Exynos_Video_GetInstInfo(&(pH264Dec->hMFCH264Handle.videoInstInfo), VIDEO_TRUE /* dec */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pH264Dec); + pH264Dec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pH264Dec->hMFCH264Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport == VIDEO_TRUE) + pVideoDec->bDrvDPBManaging = OMX_TRUE; + else + pVideoDec->hRefHandle = Exynos_OSAL_RefCount_Create(); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec skype(%d), DrvDPBManaging(%d)", pExynosComponent, __FUNCTION__, + (pH264Dec->hMFCH264Handle.videoInstInfo.supportInfo.dec.bSkypeSupport), + (pH264Dec->hMFCH264Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport)); + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID +#ifdef USE_SKYPE_HD + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-dec-caps-vt-driver-version", (OMX_INDEXTYPE)OMX_IndexSkypeParamDriverVersion); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-dec-low-latency", (OMX_INDEXTYPE)OMX_IndexSkypeParamLowLatency); +#endif + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-dec-compressed-color-format", (OMX_INDEXTYPE)OMX_IndexParamVideoCompressedColorFormat); +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoDec->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pH264Dec != NULL) { + Exynos_OSAL_Free(pH264Dec); + pH264Dec = pVideoDec->hCodecHandle = NULL; + } + +#ifdef USE_ANDROID + Exynos_OSAL_DelVendorExts(hComponent); +#endif + + ret = Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/dec/h264/Exynos_OMX_H264dec.h b/openmax/component/video/dec/h264/Exynos_OMX_H264dec.h new file mode 100644 index 0000000..a5efe63 --- /dev/null +++ b/openmax/component/video/dec/h264/Exynos_OMX_H264dec.h @@ -0,0 +1,105 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_H264dec.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_H264_DEC_COMPONENT +#define EXYNOS_OMX_H264_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" +#include "ExynosVideoApi.h" +#include "library_register.h" + + +typedef struct _EXYNOS_MFC_H264DEC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + OMX_S32 maxDPBNum; + + /* for custom component(MSRND) */ + #define MAX_H264_DISPLAYDELAY_VALIDNUM 8 + OMX_U32 nDisplayDelay; + + /* skype */ + OMX_BOOL bLowLatency; + + /* extra info which will be shared with renderer */ + int interlacedType; + ExynosVideoHdrInfo sHdrInfo; + OMX_U32 nActualFormat; + +#ifdef USE_S3D_SUPPORT + EXYNOS_OMX_FPARGMT_TYPE S3DFPArgmtType; +#endif + + ExynosVideoColorFormatType MFCOutputColorType; + ExynosVideoDecOps *pDecOps; + ExynosVideoDecBufferOps *pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 5 + OMX_VIDEO_AVCPROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_AVCLEVELTYPE maxLevel; +} EXYNOS_MFC_H264DEC_HANDLE; + +typedef struct _EXYNOS_H264DEC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_AVCTYPE AVCComponent[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + + /* EXYNOS MFC Codec specific */ + EXYNOS_MFC_H264DEC_HANDLE hMFCH264Handle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_H264DEC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE H264CodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/h264/NOTICE b/openmax/component/video/dec/h264/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/dec/h264/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/dec/h264/library_register.c b/openmax/component/video/dec/h264/library_register.c new file mode 100644 index 0000000..7fe26e8 --- /dev/null +++ b/openmax/component/video/dec/h264/library_register.c @@ -0,0 +1,59 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents) +{ + FunctionIn(); + + if (exynosComponents == NULL) + goto EXIT; + + /* component 1 - video decoder H.264 */ + Exynos_OSAL_Strcpy(exynosComponents[0]->componentName, EXYNOS_OMX_COMPONENT_H264_DEC); + Exynos_OSAL_Strcpy(exynosComponents[0]->roles[0], EXYNOS_OMX_COMPONENT_H264_DEC_ROLE); + exynosComponents[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 2 - video decoder H.264 for DRM */ + Exynos_OSAL_Strcpy(exynosComponents[1]->componentName, EXYNOS_OMX_COMPONENT_H264_DRM_DEC); + Exynos_OSAL_Strcpy(exynosComponents[1]->roles[0], EXYNOS_OMX_COMPONENT_H264_DEC_ROLE); + exynosComponents[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/openmax/component/video/dec/h264/library_register.h b/openmax/component/video/dec/h264/library_register.h new file mode 100644 index 0000000..48f3f44 --- /dev/null +++ b/openmax/component/video/dec/h264/library_register.h @@ -0,0 +1,62 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_H264_REG +#define EXYNOS_OMX_H264_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 2 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* H.264 */ +#ifndef USE_CUSTOM_COMPONENT_SUPPORT +#define EXYNOS_OMX_COMPONENT_H264_DEC "OMX.Exynos.AVC.Decoder" +#define EXYNOS_OMX_COMPONENT_H264_DRM_DEC "OMX.Exynos.AVC.Decoder.secure" +#else +#define EXYNOS_OMX_COMPONENT_H264_DEC "OMX.Exynos.avc.dec" +#define EXYNOS_OMX_COMPONENT_H264_DRM_DEC "OMX.Exynos.avc.dec.secure" +#endif + +#define EXYNOS_OMX_COMPONENT_H264_DEC_ROLE "video_decoder.avc" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/openmax/component/video/dec/hevc/Android.mk b/openmax/component/video/dec/hevc/Android.mk new file mode 100644 index 0000000..da9fa83 --- /dev/null +++ b/openmax/component/video/dec/hevc/Android.mk @@ -0,0 +1,96 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_HEVCdec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.HEVC.Decoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := +LOCAL_CFLAGS += -DUSE_HEVC_SUPPORT + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_S3D_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_S3D_SUPPORT +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifeq ($(BOARD_USE_FULL_ST2094_40), true) +LOCAL_CFLAGS += -DUSE_FULL_ST2094_40 +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/dec \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_SMALL_SECURE_MEMORY), true) +LOCAL_CFLAGS += -DUSE_SMALL_SECURE_MEMORY +endif + +ifeq ($(BOARD_USE_COMPRESSED_COLOR), true) +LOCAL_CFLAGS += -DUSE_COMPRESSED_COLOR +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/dec/hevc/Exynos_OMX_HEVCdec.c b/openmax/component/video/dec/hevc/Exynos_OMX_HEVCdec.c new file mode 100644 index 0000000..4c0adcb --- /dev/null +++ b/openmax/component/video/dec/hevc/Exynos_OMX_HEVCdec.c @@ -0,0 +1,4278 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_HEVCdec.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2013.07.26 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Vdec.h" +#include "Exynos_OMX_VdecControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_HEVCdec.h" +#include "ExynosVideoApi.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" + +#include "Exynos_OSAL_Platform.h" + +#include "VendorVideoAPI.h" + +/* To use CSC_METHOD_HW in EXYNOS OMX */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_HEVC_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pHevcDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcDec->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain; + pHevcDec->hMFCHevcHandle.nProfileCnt = nProfileCnt; + + switch (pHevcDec->hMFCHevcHandle.videoInstInfo.HwVersion) { + case MFC_1501: + case MFC_150: + pHevcDec->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10; + pHevcDec->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10HDR10; + pHevcDec->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10HDR10Plus; + pHevcDec->hMFCHevcHandle.nProfileCnt = nProfileCnt; + + pHevcDec->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel61; + break; + case MFC_1400: + case MFC_1410: + case MFC_140: + pHevcDec->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10; + pHevcDec->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10HDR10; + pHevcDec->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10HDR10Plus; + pHevcDec->hMFCHevcHandle.nProfileCnt = nProfileCnt; + + pHevcDec->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel6; + break; + case MFC_130: + case MFC_120: + case MFC_1220: + case MFC_110: + pHevcDec->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10; + pHevcDec->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10HDR10; + pHevcDec->hMFCHevcHandle.nProfileCnt = nProfileCnt; + + pHevcDec->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel6; + break; + case MFC_101: + case MFC_100: + pHevcDec->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10; + pHevcDec->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10HDR10; + pHevcDec->hMFCHevcHandle.nProfileCnt = nProfileCnt; + + pHevcDec->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel51; + break; + case HEVC_10: + case MFC_90: + case MFC_1010: + case MFC_1120: + pHevcDec->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel5; + break; + case MFC_1011: + case MFC_1020: + case MFC_1021: + pHevcDec->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel41; + break; + case MFC_92: + default: + pHevcDec->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel4; + break; + } + +EXIT: + + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + int nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pHevcDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pHevcDec->hMFCHevcHandle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pHevcDec->hMFCHevcHandle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pHevcDec->hMFCHevcHandle.maxLevel; +#else + while ((pHevcDec->hMFCHevcHandle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pHevcDec->hMFCHevcHandle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pHevcDec->hMFCHevcHandle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pHevcDec->hMFCHevcHandle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pHevcDec == NULL) + goto EXIT; + + while ((pHevcDec->hMFCHevcHandle.maxLevel >> nLevelCnt++) > 0); + + if ((pHevcDec->hMFCHevcHandle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pHevcDec->hMFCHevcHandle.nProfileCnt; i++) { + if (pHevcDec->hMFCHevcHandle.profiles[i] == pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + FunctionOut(); + + return (bProfileSupport && bLevelSupport); +} + +static OMX_ERRORTYPE GetCodecOutputPrivateData( + OMX_PTR codecBuffer, + OMX_PTR addr[], + OMX_U32 size[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pCodecBuffer = NULL; + + if (codecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pCodecBuffer = (ExynosVideoBuffer *)codecBuffer; + + if (addr != NULL) { + addr[0] = pCodecBuffer->planes[0].addr; + addr[1] = pCodecBuffer->planes[1].addr; + addr[2] = pCodecBuffer->planes[2].addr; + } + + if (size != NULL) { + size[0] = pCodecBuffer->planes[0].allocSize; + size[1] = pCodecBuffer->planes[1].allocSize; + size[2] = pCodecBuffer->planes[2].allocSize; + } + +EXIT: + return ret; +} + +static OMX_BOOL Check_HEVC_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize) +{ + OMX_BOOL ret = OMX_FALSE; + + FunctionIn(); + + if (streamSize < 4) { + ret = OMX_FALSE; + goto EXIT; + } + + if ((pInputStream[0] == 0x00) && + (pInputStream[1] == 0x00) && + (pInputStream[2] == 0x01)) + ret = OMX_TRUE; + + if ((pInputStream[0] == 0x00) && + (pInputStream[1] == 0x00) && + (pInputStream[2] == 0x00) && + (pInputStream[3] == 0x01)) + ret = OMX_TRUE; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pHevcDec == NULL) + goto EXIT; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pOutputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pHevcDec->hMFCHevcHandle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pHevcDec->hMFCHevcHandle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + + return ret; +} + +OMX_ERRORTYPE HevcCodecOpen( + EXYNOS_HEVCDEC_HANDLE *pHevcDec, + ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pHevcDec == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pDecOps = (ExynosVideoDecOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecOps)); + pInbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + pOutbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + + if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pHevcDec->hMFCHevcHandle.pDecOps = pDecOps; + pHevcDec->hMFCHevcHandle.pInbufOps = pInbufOps; + pHevcDec->hMFCHevcHandle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pDecOps->nSize = sizeof(ExynosVideoDecOps); + pInbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + + if (Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for decoder ops */ + if ((pDecOps->Init == NULL) || (pDecOps->Finalize == NULL) || + (pDecOps->Get_ActualBufferCount == NULL) || +#ifdef USE_S3D_SUPPORT + (pDecOps->Enable_SEIParsing == NULL) || (pDecOps->Get_FramePackingInfo == NULL) || +#endif + (pDecOps->Set_FrameTag == NULL) || (pDecOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pHevcDec->hMFCHevcHandle.hMFCHandle = pHevcDec->hMFCHevcHandle.pDecOps->Init(pVideoInstInfo); + + if (pHevcDec->hMFCHevcHandle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + +#ifdef USE_S3D_SUPPORT + /* S3D: Enable SEI parsing to check Frame Packing */ + if (pDecOps->Enable_SEIParsing(pHevcDec->hMFCHevcHandle.hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Enable SEI Parsing", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } +#endif + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pHevcDec->hMFCHevcHandle.pDecOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pHevcDec->hMFCHevcHandle.pInbufOps = NULL; + } + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pHevcDec->hMFCHevcHandle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HevcCodecClose(EXYNOS_HEVCDEC_HANDLE *pHevcDec) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pHevcDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + pDecOps = pHevcDec->hMFCHevcHandle.pDecOps; + pInbufOps = pHevcDec->hMFCHevcHandle.pInbufOps; + pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + + if (hMFCHandle != NULL) { + pDecOps->Finalize(hMFCHandle); + pHevcDec->hMFCHevcHandle.hMFCHandle = NULL; + pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc = OMX_FALSE; + pHevcDec->hMFCHevcHandle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Decoder(pDecOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pHevcDec->hMFCHevcHandle.pOutbufOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pHevcDec->hMFCHevcHandle.pInbufOps = NULL; + } + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pHevcDec->hMFCHevcHandle.pDecOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HevcCodecStart( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pHevcDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + pInbufOps = pHevcDec->hMFCHevcHandle.pInbufOps; + pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc == OMX_TRUE)) { + pInbufOps->Run(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_TRUE)) { + pOutbufOps->Run(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HevcCodecStop( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pHevcDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + pInbufOps = pHevcDec->hMFCHevcHandle.pInbufOps; + pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) { + pInbufOps->Stop(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) { + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pOutbufOps->Stop(hMFCHandle); + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) + pOutbufOps->Clear_RegisteredBuffer(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HevcCodecOutputBufferProcessRun( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pHevcDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pHevcDec->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pHevcDec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pHevcDec->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pHevcDec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pHevcDec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_FALSE) { + Exynos_OSAL_SignalSet(pHevcDec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HevcCodecReconfigAllBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + ExynosVideoDecBufferOps *pBufferOps = NULL; + + FunctionIn(); + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pHevcDec->bSourceStart == OMX_TRUE)) { + ret = OMX_ErrorNotImplemented; + goto EXIT; + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pHevcDec->bDestinationStart == OMX_TRUE)) { + pBufferOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + + if (pExynosPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /**********************************/ + /* Codec Buffer Free & Unregister */ + /**********************************/ + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pHevcDec->hMFCHevcHandle.bConfiguredMFCDst = OMX_FALSE; + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = HevcCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to HevcCodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType == BUFFER_SHARE) { + /***************************/ + /* Codec Buffer Unregister */ + /***************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pHevcDec->hMFCHevcHandle.bConfiguredMFCDst = OMX_FALSE; + } + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HevcCodecEnQueueAllBuffer( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + int i; + + ExynosVideoDecBufferOps *pInbufOps = pHevcDec->hMFCHevcHandle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecInputBuffer[i]->fd[0], pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pHevcDec->hMFCHevcHandle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecOutputBuffer[i]->fd[0], pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + +#ifdef USE_S3D_SUPPORT +OMX_BOOL HevcCodecCheckFramePacking(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + ExynosVideoDecOps *pDecOps = pHevcDec->hMFCHevcHandle.pDecOps; + ExynosVideoFramePacking framePacking; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + OMX_BOOL ret = OMX_FALSE; + + FunctionIn(); + + /* Get Frame packing information*/ + if (pDecOps->Get_FramePackingInfo(pHevcDec->hMFCHevcHandle.hMFCHandle, &framePacking) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Get Frame Packing Information", pExynosComponent, __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + + if (framePacking.available) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] arrangement ID: 0x%08x", + pExynosComponent, __FUNCTION__, framePacking.arrangement_id); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] arrangement_type: %d", + pExynosComponent, __FUNCTION__, framePacking.arrangement_type); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] content_interpretation_type: %d", + pExynosComponent, __FUNCTION__, framePacking.content_interpretation_type); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] current_frame_is_frame0_flag: %d", + pExynosComponent, __FUNCTION__, framePacking.current_frame_is_frame0_flag); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] spatial_flipping_flag: %d", + pExynosComponent, __FUNCTION__, framePacking.spatial_flipping_flag); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] fr0X:%d fr0Y:%d fr0X:%d fr0Y:%d", + pExynosComponent, __FUNCTION__, framePacking.frame0_grid_pos_x, + framePacking.frame0_grid_pos_y, framePacking.frame1_grid_pos_x, framePacking.frame1_grid_pos_y); + + pHevcDec->hMFCHevcHandle.S3DFPArgmtType = (EXYNOS_OMX_FPARGMT_TYPE) framePacking.arrangement_type; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventS3DInformation)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back - output color format change */ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + (OMX_EVENTTYPE)OMX_EventS3DInformation, /* The command was completed */ + OMX_TRUE, /* S3D is enabled */ + (OMX_S32)pHevcDec->hMFCHevcHandle.S3DFPArgmtType, /* S3D FPArgmtType */ + NULL); + + Exynos_OSAL_SleepMillisec(0); + } else { + pHevcDec->hMFCHevcHandle.S3DFPArgmtType = OMX_SEC_FPARGMT_NONE; + } + + ret = OMX_TRUE; + +EXIT: + FunctionOut(); + + return ret; +} +#endif + +void HevcCodecUpdateHdrInfo( + OMX_COMPONENTTYPE *pOMXComponent, + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = pHevcDec->hMFCHevcHandle.pDecOps; + ExynosVideoHdrInfo *pHdrInfo = &(pHevcDec->hMFCHevcHandle.sHdrInfo); + + if (pDecOps->Get_HDRInfo(hMFCHandle, pHdrInfo) == VIDEO_ERROR_NONE) { + /* update bitstream's info to input port */ + EXYNOS_OMX_VIDEO_HDRSTATICINFO *pHDRStaticInfo = &(pOutputPort->HDRStaticInfo); + EXYNOS_OMX_VIDEO_COLORASPECTS *pColorAspects = &(pInputPort->ColorAspects); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eType(0x%x) is changed", pExynosComponent, __FUNCTION__, pHdrInfo->eChangedType); + + /* color aspects */ + if (pHdrInfo->eValidType & (HDR_INFO_COLOR_ASPECTS | HDR_INFO_RANGE)) { + /* HDR_INFO_COLOR_ASPECTS (8) */ + pColorAspects->nCoeffType = pHdrInfo->sColorAspects.eCoeffType; + pColorAspects->nPrimaryType = pHdrInfo->sColorAspects.ePrimariesType; + pColorAspects->nTransferType = pHdrInfo->sColorAspects.eTransferType; + + /* HDR_INFO_RANGE (16) */ + pColorAspects->nRangeType = pHdrInfo->sColorAspects.eRangeType; + + if (pOutputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) { + /* update dataspace in output port from input port */ + Exynos_OSAL_UpdateDataSpaceFromBitstream(pExynosComponent); + } + } + + /* hdr static info */ + if (pHdrInfo->eValidType & (HDR_INFO_LIGHT | HDR_INFO_LUMINANCE)) { + /* HDR_INFO_LIGHT (1) */ + pHDRStaticInfo->nMaxPicAverageLight = pHdrInfo->sHdrStatic.max_pic_average_light; + pHDRStaticInfo->nMaxContentLight = pHdrInfo->sHdrStatic.max_content_light; + + /* HDR_INFO_LUMINANCE (2) */ + pHDRStaticInfo->nMaxDisplayLuminance = pHdrInfo->sHdrStatic.max_display_luminance; + pHDRStaticInfo->nMinDisplayLuminance = pHdrInfo->sHdrStatic.min_display_luminance; + + pHDRStaticInfo->red.x = pHdrInfo->sHdrStatic.red.x; + pHDRStaticInfo->red.y = pHdrInfo->sHdrStatic.red.y; + + pHDRStaticInfo->green.x = pHdrInfo->sHdrStatic.green.x; + pHDRStaticInfo->green.y = pHdrInfo->sHdrStatic.green.y; + + pHDRStaticInfo->blue.x = pHdrInfo->sHdrStatic.blue.x; + pHDRStaticInfo->blue.y = pHdrInfo->sHdrStatic.blue.y; + + pHDRStaticInfo->white.x = pHdrInfo->sHdrStatic.white.x; + pHDRStaticInfo->white.y = pHdrInfo->sHdrStatic.white.y; + } + + /* hdr dynamic info */ + if (pHdrInfo->eValidType & HDR_INFO_DYNAMIC_META) { + ExynosHdrDynamicInfo *pMetaHDRDynamic = &(pBufferInfo->HDRDynamic); /* HDR Dynamic info(HDR10+) to extra info */ + ExynosVideoHdrDynamic *pHDRDynamicInfo = &(pHdrInfo->sHdrDynamic); + + /* actual validity in bitstream */ + pMetaHDRDynamic->valid = (pHdrInfo->eValidType & HDR_INFO_DYNAMIC_META)? 1:0; + + pMetaHDRDynamic->data.country_code = pHDRDynamicInfo->itu_t_t35_country_code; + pMetaHDRDynamic->data.provider_code = pHDRDynamicInfo->itu_t_t35_terminal_provider_code; + pMetaHDRDynamic->data.provider_oriented_code = pHDRDynamicInfo->itu_t_t35_terminal_provider_oriented_code; + pMetaHDRDynamic->data.application_identifier = pHDRDynamicInfo->application_identifier; + pMetaHDRDynamic->data.application_version = pHDRDynamicInfo->application_version; +#ifdef USE_FULL_ST2094_40 + pMetaHDRDynamic->data.targeted_system_display_maximum_luminance = pHDRDynamicInfo->targeted_system_display_maximum_luminance; + + if (pHDRDynamicInfo->num_windows > 0) { + /* save information on window-0 only */ + ExynosVideoHdrWindowInfo *pWindowInfo = &(pHDRDynamicInfo->window_info[0]); + int i; + + /* maxscl */ + for (i = 0; i < (int)(sizeof(pMetaHDRDynamic->data.maxscl)/sizeof(pMetaHDRDynamic->data.maxscl[0])); i++) + pMetaHDRDynamic->data.maxscl[0][i] = pWindowInfo->maxscl[i]; + + /* distribution maxrgb */ + pMetaHDRDynamic->data.num_maxrgb_percentiles[0] = pWindowInfo->num_distribution_maxrgb_percentiles; + for (i = 0; i < pWindowInfo->num_distribution_maxrgb_percentiles; i++) { + pMetaHDRDynamic->data.maxrgb_percentages[0][i] = pWindowInfo->distribution_maxrgb_percentages[i]; + pMetaHDRDynamic->data.maxrgb_percentiles[0][i] = pWindowInfo->distribution_maxrgb_percentiles[i]; + } + + /* tone mapping curve */ + pMetaHDRDynamic->data.tone_mapping.tone_mapping_flag[0] = pWindowInfo->tone_mapping_flag; + if (pWindowInfo->tone_mapping_flag != 0) { + pMetaHDRDynamic->data.tone_mapping.knee_point_x[0] = pWindowInfo->knee_point_x; + pMetaHDRDynamic->data.tone_mapping.knee_point_y[0] = pWindowInfo->knee_point_y; + + pMetaHDRDynamic->data.tone_mapping.num_bezier_curve_anchors[0] = pWindowInfo->num_bezier_curve_anchors; + for (i = 0; i < pWindowInfo->num_bezier_curve_anchors; i++) + pMetaHDRDynamic->data.tone_mapping.bezier_curve_anchors[0][i] = pWindowInfo->bezier_curve_anchors[i]; + } + } +#else // USE_FULL_ST2094_40 + pMetaHDRDynamic->data.display_maximum_luminance = pHDRDynamicInfo->targeted_system_display_maximum_luminance; + + if (pHDRDynamicInfo->num_windows > 0) { + /* save information on window-0 only */ + ExynosVideoHdrWindowInfo *pWindowInfo = &(pHDRDynamicInfo->window_info[0]); + int i; + + /* maxscl */ + for (i = 0; i < (int)(sizeof(pMetaHDRDynamic->data.maxscl)/sizeof(pMetaHDRDynamic->data.maxscl[0])); i++) + pMetaHDRDynamic->data.maxscl[i] = pWindowInfo->maxscl[i]; + + /* distribution maxrgb */ + pMetaHDRDynamic->data.num_maxrgb_percentiles = pWindowInfo->num_distribution_maxrgb_percentiles; + for (i = 0; i < pWindowInfo->num_distribution_maxrgb_percentiles; i++) { + pMetaHDRDynamic->data.maxrgb_percentages[i] = pWindowInfo->distribution_maxrgb_percentages[i]; + pMetaHDRDynamic->data.maxrgb_percentiles[i] = pWindowInfo->distribution_maxrgb_percentiles[i]; + } + + /* tone mapping curve */ + pMetaHDRDynamic->data.tone_mapping.tone_mapping_flag = pWindowInfo->tone_mapping_flag; + if (pWindowInfo->tone_mapping_flag != 0) { + pMetaHDRDynamic->data.tone_mapping.knee_point_x = pWindowInfo->knee_point_x; + pMetaHDRDynamic->data.tone_mapping.knee_point_y = pWindowInfo->knee_point_y; + + pMetaHDRDynamic->data.tone_mapping.num_bezier_curve_anchors = pWindowInfo->num_bezier_curve_anchors; + for (i = 0; i < pWindowInfo->num_bezier_curve_anchors; i++) + pMetaHDRDynamic->data.tone_mapping.bezier_curve_anchors[i] = pWindowInfo->bezier_curve_anchors[i]; + } + } +#endif + } + +#ifdef USE_ANDROID + /* if both have changed, should send an event once */ + if (pHdrInfo->eChangedType & (HDR_INFO_COLOR_ASPECTS | HDR_INFO_RANGE)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_IndexConfigVideoColorAspects)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigVideoColorAspects, + NULL); + } else if (pHdrInfo->eChangedType & (HDR_INFO_LIGHT | HDR_INFO_LUMINANCE)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_IndexConfigVideoHdrStaticInfo)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigVideoHdrStaticInfo, + NULL); + } +#endif + } + +EXIT: + + return; +} + +OMX_ERRORTYPE HevcCodecUpdateExtraInfo( + OMX_COMPONENTTYPE *pOMXComponent, + ExynosVideoMeta *pMeta) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + + if (pMeta == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMeta->eType = VIDEO_INFO_TYPE_INVALID; + + /* HDR */ + { + ExynosType1 *pMetaHDR = &(pMeta->sHdrStaticInfo.sType1); + ExynosColorAspects *pMetaCA = &(pMeta->sColorAspects); + + if (pHevcDec->hMFCHevcHandle.sHdrInfo.eValidType & (HDR_INFO_COLOR_ASPECTS | HDR_INFO_RANGE)) { + ExynosVideoColorAspects *pColorAspects = &(pHevcDec->hMFCHevcHandle.sHdrInfo.sColorAspects); + + pMetaCA->mMatrixCoeffs = pColorAspects->eCoeffType; + pMetaCA->mPrimaries = pColorAspects->ePrimariesType; + pMetaCA->mTransfer = pColorAspects->eTransferType; + pMetaCA->mRange = pColorAspects->eRangeType; + + //pMeta->eType |= VIDEO_INFO_TYPE_COLOR_ASPECTS; + } + + if (pHevcDec->hMFCHevcHandle.sHdrInfo.eValidType & (HDR_INFO_LIGHT | HDR_INFO_LUMINANCE)) { + ExynosVideoHdrStatic *pHDRStaticInfo = &(pHevcDec->hMFCHevcHandle.sHdrInfo.sHdrStatic); + + /* HDR_INFO_LIGHT (1) */ + pMetaHDR->mMaxFrameAverageLightLevel = pHDRStaticInfo->max_pic_average_light; + pMetaHDR->mMaxContentLightLevel = pHDRStaticInfo->max_content_light; + + /* HDR_INFO_LUMINANCE (2) */ + pMetaHDR->mMaxDisplayLuminance = pHDRStaticInfo->max_display_luminance; + pMetaHDR->mMinDisplayLuminance = pHDRStaticInfo->min_display_luminance; + + pMetaHDR->mR.x = pHDRStaticInfo->red.x; + pMetaHDR->mR.y = pHDRStaticInfo->red.y; + + pMetaHDR->mG.x = pHDRStaticInfo->green.x; + pMetaHDR->mG.y = pHDRStaticInfo->green.y; + + pMetaHDR->mB.x = pHDRStaticInfo->blue.x; + pMetaHDR->mB.y = pHDRStaticInfo->blue.y; + + pMetaHDR->mW.x = pHDRStaticInfo->white.x; + pMetaHDR->mW.y = pHDRStaticInfo->white.y; + + pMeta->eType |= VIDEO_INFO_TYPE_HDR_STATIC; + } + + /* hdr dynamic info */ + if (pHevcDec->hMFCHevcHandle.sHdrInfo.sHdrDynamic.valid != 0) { /* once dynamic info is set, it will be always true */ + ExynosHdrDynamicInfo *pMetaHDRDynamic = &(pMeta->sHdrDynamicInfo); /* HDR Dynamic info(HDR10+) to private buffer */ + ExynosVideoHdrDynamic *pHDRDynamicInfo = &(pHevcDec->hMFCHevcHandle.sHdrInfo.sHdrDynamic); + + /* actual validity in bitstream */ + pMetaHDRDynamic->valid = (pHevcDec->hMFCHevcHandle.sHdrInfo.eValidType & HDR_INFO_DYNAMIC_META)? 1:0; + + pMetaHDRDynamic->data.country_code = pHDRDynamicInfo->itu_t_t35_country_code; + pMetaHDRDynamic->data.provider_code = pHDRDynamicInfo->itu_t_t35_terminal_provider_code; + pMetaHDRDynamic->data.provider_oriented_code = pHDRDynamicInfo->itu_t_t35_terminal_provider_oriented_code; + pMetaHDRDynamic->data.application_identifier = pHDRDynamicInfo->application_identifier; + pMetaHDRDynamic->data.application_version = pHDRDynamicInfo->application_version; + +#ifdef USE_FULL_ST2094_40 + pMetaHDRDynamic->data.targeted_system_display_maximum_luminance = pHDRDynamicInfo->targeted_system_display_maximum_luminance; + + pMetaHDRDynamic->data.num_windows = pHDRDynamicInfo->num_windows; + + if (pHDRDynamicInfo->num_windows > 0) { + /* save information on window-0 only */ + ExynosVideoHdrWindowInfo *pWindowInfo = &(pHDRDynamicInfo->window_info[0]); + int i; + + /* maxscl */ + for (i = 0; i < (int)(sizeof(pMetaHDRDynamic->data.maxscl)/sizeof(pMetaHDRDynamic->data.maxscl[0])); i++) + pMetaHDRDynamic->data.maxscl[0][i] = pWindowInfo->maxscl[i]; + + /* average_maxrgb */ + pMetaHDRDynamic->data.average_maxrgb[0] = pWindowInfo->average_maxrgb; + + /* distribution maxrgb */ + pMetaHDRDynamic->data.num_maxrgb_percentiles[0] = pWindowInfo->num_distribution_maxrgb_percentiles; + for (i = 0; i < pWindowInfo->num_distribution_maxrgb_percentiles; i++) { + pMetaHDRDynamic->data.maxrgb_percentages[0][i] = pWindowInfo->distribution_maxrgb_percentages[i]; + pMetaHDRDynamic->data.maxrgb_percentiles[0][i] = pWindowInfo->distribution_maxrgb_percentiles[i]; + } + + /* fraction_bright_pixels */ + pMetaHDRDynamic->data.fraction_bright_pixels[0] = pWindowInfo->fraction_bright_pixels; + + /* tone mapping curve */ + pMetaHDRDynamic->data.tone_mapping.tone_mapping_flag[0] = pWindowInfo->tone_mapping_flag; + if (pWindowInfo->tone_mapping_flag != 0) { + pMetaHDRDynamic->data.tone_mapping.knee_point_x[0] = pWindowInfo->knee_point_x; + pMetaHDRDynamic->data.tone_mapping.knee_point_y[0] = pWindowInfo->knee_point_y; + + pMetaHDRDynamic->data.tone_mapping.num_bezier_curve_anchors[0] = pWindowInfo->num_bezier_curve_anchors; + for (i = 0; i < pWindowInfo->num_bezier_curve_anchors; i++) + pMetaHDRDynamic->data.tone_mapping.bezier_curve_anchors[0][i] = pWindowInfo->bezier_curve_anchors[i]; + } + + /* color_saturation info */ + pMetaHDRDynamic->data.color_saturation_mapping_flag[0] = pWindowInfo->color_saturation_mapping_flag; + if (pWindowInfo->color_saturation_mapping_flag != 0) { + pMetaHDRDynamic->data.color_saturation_weight[0] = pWindowInfo->color_saturation_weight; + } + } +#else // USE_FULL_ST2094_40 + pMetaHDRDynamic->data.display_maximum_luminance = pHDRDynamicInfo->targeted_system_display_maximum_luminance; + + if (pHDRDynamicInfo->num_windows > 0) { + /* save information on window-0 only */ + ExynosVideoHdrWindowInfo *pWindowInfo = &(pHDRDynamicInfo->window_info[0]); + int i; + + /* maxscl */ + for (i = 0; i < (int)(sizeof(pMetaHDRDynamic->data.maxscl)/sizeof(pMetaHDRDynamic->data.maxscl[0])); i++) + pMetaHDRDynamic->data.maxscl[i] = pWindowInfo->maxscl[i]; + + /* distribution maxrgb */ + pMetaHDRDynamic->data.num_maxrgb_percentiles = pWindowInfo->num_distribution_maxrgb_percentiles; + for (i = 0; i < pWindowInfo->num_distribution_maxrgb_percentiles; i++) { + pMetaHDRDynamic->data.maxrgb_percentages[i] = pWindowInfo->distribution_maxrgb_percentages[i]; + pMetaHDRDynamic->data.maxrgb_percentiles[i] = pWindowInfo->distribution_maxrgb_percentiles[i]; + } + + /* tone mapping curve */ + pMetaHDRDynamic->data.tone_mapping.tone_mapping_flag = pWindowInfo->tone_mapping_flag; + if (pWindowInfo->tone_mapping_flag != 0) { + pMetaHDRDynamic->data.tone_mapping.knee_point_x = pWindowInfo->knee_point_x; + pMetaHDRDynamic->data.tone_mapping.knee_point_y = pWindowInfo->knee_point_y; + + pMetaHDRDynamic->data.tone_mapping.num_bezier_curve_anchors = pWindowInfo->num_bezier_curve_anchors; + for (i = 0; i < pWindowInfo->num_bezier_curve_anchors; i++) + pMetaHDRDynamic->data.tone_mapping.bezier_curve_anchors[i] = pWindowInfo->bezier_curve_anchors[i]; + } + } +#endif + + pMeta->eType |= VIDEO_INFO_TYPE_HDR_DYNAMIC; + +#ifdef USE_ANDROID + if (pHevcDec->hMFCHevcHandle.sHdrInfo.eChangedType & HDR_INFO_DYNAMIC_META) { + ret = setHDR10PlusInfoForFramework(pOMXComponent, pMetaHDRDynamic); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Failed to set HDR10+ info for framework(ret: 0x%x)", pExynosComponent, __FUNCTION__, ret); + } + } +#endif + } + } + + /* Normal format for SBWC black bar */ + { + if (pHevcDec->hMFCHevcHandle.nActualFormat != 0) { + pMeta->nPixelFormat = pHevcDec->hMFCHevcHandle.nActualFormat; + pMeta->eType |= VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT; + + pHevcDec->hMFCHevcHandle.nActualFormat = 0; + } else { + pMeta->nPixelFormat = 0; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE HevcCodecUpdateBlackBarCrop(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + OMX_CONFIG_RECTTYPE *pBlackBarCropRect = &pVideoDec->blackBarCropRect; + + ExynosVideoDecBufferOps *pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + ExynosVideoRect CropRect; + + FunctionIn(); + + Exynos_OSAL_Memset(&CropRect, 0, sizeof(ExynosVideoRect)); + if (pOutbufOps->Get_BlackBarCrop(hMFCHandle, &CropRect) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get crop info", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + + pBlackBarCropRect->nLeft = CropRect.nLeft; + pBlackBarCropRect->nTop = CropRect.nTop; + pBlackBarCropRect->nWidth = CropRect.nWidth; + pBlackBarCropRect->nHeight = CropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Black Bar Info: LEFT(%d) TOP(%d) WIDTH(%d) HEIGHT(%d)", + pExynosComponent, __FUNCTION__, + pBlackBarCropRect->nLeft, pBlackBarCropRect->nTop, + pBlackBarCropRect->nWidth, pBlackBarCropRect->nHeight); + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + (OMX_INDEXTYPE)OMX_IndexConfigBlackBarCrop, + NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HevcCodecCheckResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_EXCEPTION_STATE eOutputExcepState = pOutputPort->exceptionFlag; + + ExynosVideoDecOps *pDecOps = pHevcDec->hMFCHevcHandle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + + OMX_CONFIG_RECTTYPE *pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = &(pInputPort->portDefinition); + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = &(pOutputPort->portDefinition); + + int maxDPBNum = 0; + + FunctionIn(); + + /* get geometry for output */ + Exynos_OSAL_Memset(&codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to get geometry"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + maxDPBNum += EXTRA_DPB_NUM; + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + } + + /* resolution is changed */ + if ((codecOutbufConf.nFrameWidth != pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth) || + (codecOutbufConf.nFrameHeight != pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight) || + (codecOutbufConf.nStride != pHevcDec->hMFCHevcHandle.codecOutbufConf.nStride) || +#if 0 // TODO: check posibility + (codecOutbufConf.eColorFormat != pHevcDec->hMFCHevcHandle.codecOutbufConf.eColorFormat) || + (codecOutbufConf.eFilledDataType != pHevcDec->hMFCHevcHandle.codecOutbufConf.eFilledDataType) || +#endif + (maxDPBNum != pHevcDec->hMFCHevcHandle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth, + pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] DPB(%d), FORMAT(0x%x), TYPE(0x%x) -> DPB(%d), FORMAT(0x%x), TYPE(0x%x)", + pExynosComponent, __FUNCTION__, + pHevcDec->hMFCHevcHandle.maxDPBNum, + pHevcDec->hMFCHevcHandle.codecOutbufConf.eColorFormat, + pHevcDec->hMFCHevcHandle.codecOutbufConf.eFilledDataType, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType); + + pInputPortDefinition->format.video.nFrameWidth = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = codecOutbufConf.nFrameHeight; + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = maxDPBNum; + pOutputPortDefinition->nBufferCountMin = maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* crop info of contents is changed */ + if ((codecOutbufConf.cropRect.nTop != pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nTop) || + (codecOutbufConf.cropRect.nLeft != pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nLeft) || + (codecOutbufConf.cropRect.nWidth != pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nWidth) || + (codecOutbufConf.cropRect.nHeight != pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nHeight)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nWidth, + pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nHeight, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + Exynos_OSAL_Memcpy(&pHevcDec->hMFCHevcHandle.codecOutbufConf, &codecOutbufConf, sizeof(codecOutbufConf)); + pHevcDec->hMFCHevcHandle.maxDPBNum = maxDPBNum; + + ret = OMX_ErrorNone; + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HevcCodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pHevcDec->hMFCHevcHandle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + ExynosVideoErrorType codecRet = VIDEO_ERROR_NONE; + + OMX_CONFIG_RECTTYPE *pCropRectangle = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = NULL; + + OMX_BOOL bFormatChanged = OMX_FALSE; + + FunctionIn(); + + /* get geometry for output */ + Exynos_OSAL_Memset(&pHevcDec->hMFCHevcHandle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + codecRet = pOutbufOps->Get_Geometry(hMFCHandle, &pHevcDec->hMFCHevcHandle.codecOutbufConf); + if (codecRet == VIDEO_ERROR_HEADERINFO) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] parsed header info has only VPS", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorNeedNextHeaderInfo; + goto EXIT; + } else if (codecRet != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + pHevcDec->hMFCHevcHandle.maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + pHevcDec->hMFCHevcHandle.maxDPBNum += EXTRA_DPB_NUM; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] maxDPBNum: %d", pExynosComponent, __FUNCTION__, pHevcDec->hMFCHevcHandle.maxDPBNum); + + pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] past info: width(%d) height(%d)", + pExynosComponent, __FUNCTION__, + pInputPortDefinition->format.video.nFrameWidth, + pInputPortDefinition->format.video.nFrameHeight); + + /* output format is changed internally (8bit <> 10bit) */ + if (pHevcDec->hMFCHevcHandle.MFCOutputColorType != pHevcDec->hMFCHevcHandle.codecOutbufConf.eColorFormat) { + OMX_COLOR_FORMATTYPE eOutputFormat = Exynos_OSAL_Video2OMXFormat(pHevcDec->hMFCHevcHandle.codecOutbufConf.eColorFormat); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] The format(%x) is changed to %x by H/W Codec", + pExynosComponent, __FUNCTION__, + pHevcDec->hMFCHevcHandle.MFCOutputColorType, + pHevcDec->hMFCHevcHandle.codecOutbufConf.eColorFormat); + + pHevcDec->hMFCHevcHandle.MFCOutputColorType = pHevcDec->hMFCHevcHandle.codecOutbufConf.eColorFormat; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pOutputPort->ePlaneType)); + + bFormatChanged = OMX_TRUE; + + if (!(pHevcDec->hMFCHevcHandle.codecOutbufConf.eFilledDataType & DATA_TYPE_8BIT_SBWC)) { + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* SBWC to non SBWC : must update eColorFormat */ + pOutputPort->portDefinition.format.video.eColorFormat = eOutputFormat; + } + + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } else { + pVideoDec->nCompColorFormat = eOutputFormat; + } + } + + switch (pHevcDec->hMFCHevcHandle.codecOutbufConf.eFilledDataType) { + case DATA_8BIT_WITH_2BIT: + pVideoDec->eDataType = DATA_TYPE_8BIT_WITH_2BIT; + break; + case DATA_10BIT: + pVideoDec->eDataType = DATA_TYPE_10BIT; + break; + case DATA_8BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_8BIT_SBWC; + break; + case DATA_10BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_10BIT_SBWC; + break; + default: + pVideoDec->eDataType = DATA_TYPE_8BIT; + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] resolution info: width(%d / %d), height(%d / %d)", + pExynosComponent, __FUNCTION__, + pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth, + pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nWidth, + pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight, + pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nHeight); + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nHeight; + } + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight; +#if 0 + /* don't need to change */ + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; +#endif + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } else if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPortDefinition->nBufferCountActual != pHevcDec->hMFCHevcHandle.maxDPBNum) || + ((OMX_S32)pOutputPortDefinition->nBufferCountMin < pHevcDec->hMFCHevcHandle.maxDPBNum)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight; + + pOutputPortDefinition->nBufferCountActual = pHevcDec->hMFCHevcHandle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pHevcDec->hMFCHevcHandle.maxDPBNum; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* contents has crop info */ + if ((pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth != pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nWidth) || + (pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight != pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nHeight)) { + + if ((pOutputPort->bufferProcessType & BUFFER_COPY) && + (pExynosComponent->bUseImgCrop == OMX_TRUE)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + } + pInputPortDefinition->format.video.nFrameWidth = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged) with crop", + pExynosComponent, __FUNCTION__); + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HevcCodecHeaderDecoding(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecBufferOps *pInbufOps = pHevcDec->hMFCHevcHandle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + ExynosVideoErrorType codecRet = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + + FunctionIn(); + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + nAllocLen[0] = pSrcInputData->allocSize; + } + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enqueue input buffer for header parsing", pExynosComponent, __FUNCTION__); +// ret = OMX_ErrorInsufficientResources; + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* start header parsing */ + if (pInbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run input buffer for header parsing", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* get geometry for output */ + Exynos_OSAL_Memset(&pHevcDec->hMFCHevcHandle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + codecRet = pOutbufOps->Get_Geometry(hMFCHandle, &pHevcDec->hMFCHevcHandle.codecOutbufConf); + if (codecRet == VIDEO_ERROR_HEADERINFO) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] parsed header info has only VPS", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorNeedNextHeaderInfo; + goto EXIT; + } else if (codecRet != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedHeader; + + if ((pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", pExynosComponent, __FUNCTION__, + *((OMX_U8 *)pSrcInputData->buffer.addr[0]) , *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 1), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 2), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 3), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 4), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 5), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 6), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 7)); + } + + goto EXIT; + } + +EXIT: + FunctionOut(); + + if (ret != OMX_ErrorNone) { + if ((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorNeedNextHeaderInfo) { + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + EXYNOS_OMX_DATABUFFER directReturnUseBuffer; + + Exynos_Shared_DataToBuffer(pExynosInputPort, &directReturnUseBuffer, pSrcInputData); + Exynos_InputBufferReturn(pOMXComponent, &directReturnUseBuffer); + } else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + OMX_PTR codecBuffer = pSrcInputData->pPrivate; + + if (codecBuffer != NULL) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, codecBuffer); + } + } + pInbufOps->Stop(hMFCHandle); + } + + return ret; +} + +OMX_ERRORTYPE HevcCodecSrcSetup( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 allocFrameSize = 0; + OMX_COLOR_FORMATTYPE eOutputFormat = pExynosOutputPort->portDefinition.format.video.eColorFormat; + + EXYNOS_OMX_VIDEO_HDRSTATICINFO *pHDRStaticInfo = &(pExynosOutputPort->HDRStaticInfo); + EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA = &(pExynosOutputPort->ColorAspects); + EXYNOS_OMX_VIDEO_COLORASPECTS *pBSCA = &(pExynosInputPort->ColorAspects); + + ExynosVideoDecOps *pDecOps = pHevcDec->hMFCHevcHandle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pHevcDec->hMFCHevcHandle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + + FunctionIn(); + + if ((pSrcInputData->dataLen <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pHevcDec->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pHevcDec->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SignalSet(pHevcDec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pVideoDec->bThumbnailMode == OMX_TRUE) + pDecOps->Set_IFrameDecoding(hMFCHandle); + else if ((IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) && + (pHevcDec->hMFCHevcHandle.nDisplayDelay <= MAX_HEVC_DISPLAYDELAY_VALIDNUM)) { + pDecOps->Set_DisplayDelay(hMFCHandle, (int)pHevcDec->hMFCHevcHandle.nDisplayDelay); + } + + if ((pDecOps->Enable_DTSMode != NULL) && + (pVideoDec->bDTSMode == OMX_TRUE)) + pDecOps->Enable_DTSMode(hMFCHandle); + + if (pHevcDec->hMFCHevcHandle.videoInstInfo.supportInfo.dec.bPrioritySupport == VIDEO_TRUE) + pDecOps->Set_Priority(hMFCHandle, pVideoDec->nPriority); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eCompressionFormat = VIDEO_CODING_HEVC; + pInbufOps->Set_Shareable(hMFCHandle); + + allocFrameSize = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + allocFrameSize = pSrcInputData->allocSize; + } + + bufferConf.nSizeImage = allocFrameSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + nInBufferCnt = MAX_INPUTBUFFER_NUM_DYNAMIC; + + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + +#ifdef USE_COMPRESSED_COLOR + if ((pExynosOutputPort->eMetaDataType != METADATA_TYPE_GRAPHIC) || + (pExynosOutputPort->bForceUseNonCompFormat == OMX_TRUE)) { + /* use SBWC format only ANB scenario */ + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } +#endif + + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* For SBWC format setting */ + bSupportFormat = CheckFormatHWSupport(pExynosComponent, pVideoDec->nCompColorFormat); + if (bSupportFormat == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] set compressed color format(0x%x)", + pExynosComponent, __FUNCTION__, (OMX_U32)pVideoDec->nCompColorFormat); + + eOutputFormat = pVideoDec->nCompColorFormat; + } + } + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] omx format(0x%x) is %s by h/w", + pExynosComponent, __FUNCTION__, eOutputFormat, + (bSupportFormat == OMX_TRUE)? "supported":"not supported"); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eOutputFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pExynosOutputPort->ePlaneType)); + } else { + OMX_COLOR_FORMATTYPE eCheckFormat = OMX_COLOR_FormatYUV420SemiPlanar; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + + if (bSupportFormat == OMX_TRUE) { /* supported by CSC(NV12 -> format) */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eCheckFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eCheckFormat, pExynosOutputPort->ePlaneType)); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not support this format (0x%x)", pExynosComponent, __FUNCTION__, eOutputFormat); + ret = OMX_ErrorNotImplemented; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + } + + pHevcDec->hMFCHevcHandle.MFCOutputColorType = bufferConf.eColorFormat; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output video format is 0x%x", + pExynosComponent, __FUNCTION__, bufferConf.eColorFormat); + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + if (pVideoDec->bReorderMode == OMX_TRUE) + Exynos_SetReorderTimestamp(pExynosComponent, &(pHevcDec->hMFCHevcHandle.indexTimestamp), pSrcInputData->timeStamp, pSrcInputData->nFlags); + + ret = HevcCodecHeaderDecoding(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc = OMX_TRUE; + + HevcCodecStart(pOMXComponent, INPUT_PORT_INDEX); + + ret = HevcCodecUpdateResolution(pOMXComponent); + if (ret != OMX_ErrorNone) { + pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc = OMX_FALSE; + HevcCodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); +#if 1 /* enable re-input scheme */ + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + HevcCodecStop(pOMXComponent, INPUT_PORT_INDEX); +#else + ret = (OMX_ERRORTYPE)OMX_ErrorNoneSrcSetupFinish; +#endif + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HevcCodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pHevcDec->hMFCHevcHandle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nOutbufs, nPlaneCnt; + + FunctionIn(); + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = pHevcDec->hMFCHevcHandle.codecOutbufConf.nAlignPlaneSize[i]; + + HevcCodecStop(pOMXComponent, OUTPUT_PORT_INDEX); + + /* for adaptive playback */ + if (pHevcDec->hMFCHevcHandle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enable Dynamic DPB", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* get dpb count */ + nOutbufs = pHevcDec->hMFCHevcHandle.maxDPBNum; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + + pHevcDec->hMFCHevcHandle.bConfiguredMFCDst = OMX_TRUE; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->eMetaDataType == METADATA_TYPE_DISABLED) { + /*************/ + /* TBD */ + /*************/ + /* data buffer : user buffer + * H/W can't accept user buffer directly + */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pHevcDec->hMFCHevcHandle.bConfiguredMFCDst = OMX_TRUE; + } + + if (HevcCodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoHevc: + { + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = (OMX_VIDEO_PARAM_HEVCTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_HEVCTYPE *pSrcHevcComponent = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstHevcComponent, sizeof(OMX_VIDEO_PARAM_HEVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstHevcComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcHevcComponent = &pHevcDec->HevcComponent[pDstHevcComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstHevcComponent) + nOffset, + ((char *)pSrcHevcComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_HEVCTYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_HEVC_DEC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_HEVCTYPE *pSrcHevcComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcHevcComponent = &pHevcDec->HevcComponent[pDstProfileLevel->nPortIndex]; + + pDstProfileLevel->eProfile = pSrcHevcComponent->eProfile; + pDstProfileLevel->eLevel = pSrcHevcComponent->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pHevcDec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexExynosParamDisplayDelay: /* MSRND */ + { + OMX_PARAM_U32TYPE *pDisplayDelay = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDisplayDelay, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDisplayDelay->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + pDisplayDelay->nU32 = pHevcDec->hMFCHevcHandle.nDisplayDelay; + } + break; + case OMX_IndexExynosParamReorderMode: + { + EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *pReorderParam = (EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pReorderParam, sizeof(EXYNOS_OMX_VIDEO_PARAM_REORDERMODE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pReorderParam->bReorderMode = pVideoDec->bReorderMode; + } + break; + case OMX_IndexExynosParamBufferCopy: + { + OMX_PARAM_U32TYPE *pBufferCopy = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pBufferCopy, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pBufferCopy->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[pBufferCopy->nPortIndex]; + + pBufferCopy->nU32 = (pExynosPort->bufferProcessType & BUFFER_COPY_FORCE)? 1:0; + } + break; +#ifdef USE_ANDROID + case OMX_IndexExynosParamImageConvertMode: + { + OMX_PARAM_U32TYPE *pImgConvMode = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pImgConvMode, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pImgConvMode->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pImgConvMode->nU32 = pVideoDec->nImageConvMode; + } + break; +#endif + default: + ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoHevc: + { + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = NULL; + OMX_VIDEO_PARAM_HEVCTYPE *pSrcHevcComponent = (OMX_VIDEO_PARAM_HEVCTYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcHevcComponent, sizeof(OMX_VIDEO_PARAM_HEVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcHevcComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstHevcComponent = &pHevcDec->HevcComponent[pSrcHevcComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstHevcComponent) + nOffset, + ((char *)pSrcHevcComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_HEVCTYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_HEVC_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)OMX_VIDEO_CodingHEVC; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstHevcComponent = &pHevcDec->HevcComponent[pSrcProfileLevel->nPortIndex]; + + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstHevcComponent->eProfile = pSrcProfileLevel->eProfile; + pDstHevcComponent->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pHevcDec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexExynosParamDisplayDelay: /* MSRND */ + { + OMX_PARAM_U32TYPE *pDisplayDelay = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDisplayDelay, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDisplayDelay->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + if (pDisplayDelay->nU32 > MAX_HEVC_DISPLAYDELAY_VALIDNUM) { + ret = OMX_ErrorBadParameter; + break; + } + + pHevcDec->hMFCHevcHandle.nDisplayDelay = pDisplayDelay->nU32; + } + break; + case OMX_IndexExynosParamReorderMode: + { + EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *pReorderParam = (EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pReorderParam, sizeof(EXYNOS_OMX_VIDEO_PARAM_REORDERMODE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoDec->bReorderMode = pReorderParam->bReorderMode; + } + break; + case OMX_IndexExynosParamBufferCopy: + { + OMX_PARAM_U32TYPE *pBufferCopy = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pBufferCopy, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pBufferCopy->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] can't change a buffer mode", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[pBufferCopy->nPortIndex]; + + if (pBufferCopy->nU32 != 0) { + pExynosPort->bufferProcessType |= BUFFER_COPY_FORCE; + } else { + pExynosPort->bufferProcessType &= (~BUFFER_COPY_FORCE); + } + } + break; +#ifdef USE_ANDROID + case OMX_IndexExynosParamImageConvert: + { + OMX_VIDEO_PARAM_IMG_CONV *pImgConv = (OMX_VIDEO_PARAM_IMG_CONV *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pImgConv, sizeof(OMX_VIDEO_PARAM_IMG_CONV)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pImgConv->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] secure component doesn't support image conversion", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] can't change image conversion mode", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pVideoDec->hImgConv != NULL) { + Exynos_OSAL_ImgConv_Terminate(pVideoDec->hImgConv); + pVideoDec->hImgConv = NULL; + } + + if (pImgConv->bEnable == OMX_TRUE) { + pVideoDec->hImgConv = Exynos_OSAL_ImgConv_Create(pImgConv->nWidth, pImgConv->nHeight, pVideoDec->nImageConvMode); + if (pVideoDec->hImgConv == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Exynos_OSAL_ImgConv_Create()", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] ImageConverter is %s", pExynosComponent, __FUNCTION__, + (pImgConv->bEnable == OMX_TRUE)? "enabled":"disabled"); + } + break; + case OMX_IndexExynosParamImageConvertMode: + { + OMX_PARAM_U32TYPE *pImgConvMode = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pImgConvMode, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pImgConvMode->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] secure component doesn't support image conversion", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_TRUE) || + (pVideoDec->hImgConv != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] can't change image conversion mode", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec->nImageConvMode = pImgConvMode->nU32; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] ImageConverter mode(%d)", pExynosComponent, __FUNCTION__, pVideoDec->nImageConvMode); + } + break; +#endif + default: + ret = Exynos_OMX_VideoDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigCommonOutputCrop: + { + if (pExynosComponent->bUseImgCrop == OMX_TRUE) { + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + } else { + /* query crop information on bitstream */ + OMX_CONFIG_RECTTYPE *pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + + if (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + goto EXIT; + } + + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pSrcRectType = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + } + break; +#ifdef USE_S3D_SUPPORT + case OMX_IndexVendorS3DMode: + { + OMX_U32 *pS3DMode = NULL; + + pS3DMode = (OMX_U32 *)pComponentConfigStructure; + *pS3DMode = (OMX_U32) pHevcDec->hMFCHevcHandle.S3DFPArgmtType; + } + break; +#endif + case OMX_IndexExynosConfigDisplayDelay: /* MSRND */ + { + (*((OMX_U32 *)pComponentConfigStructure)) = pHevcDec->hMFCHevcHandle.nDisplayDelay; + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigVideoHdrStaticInfo: + case OMX_IndexConfigVideoHdr10PlusInfo: + { + ret = Exynos_OSAL_GetConfig(hComponent, nIndex, pComponentConfigStructure); + } + break; +#endif + default: + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexExynosConfigDisplayDelay: /* MSRND */ + { + OMX_U32 nDisplayDelay = (*((OMX_U32 *)pComponentConfigStructure)); + + if (pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + break; + } + + if (nDisplayDelay > MAX_HEVC_DISPLAYDELAY_VALIDNUM) { + ret = OMX_ErrorBadParameter; + break; + } + + pHevcDec->hMFCHevcHandle.nDisplayDelay = nDisplayDelay; + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigVideoHdrStaticInfo: + case OMX_IndexConfigVideoHdr10PlusInfo: + { + ret = Exynos_OSAL_SetConfig(hComponent, nIndex, pComponentConfigStructure); + } + break; +#endif + default: + ret = Exynos_OMX_VideoDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + +#ifdef USE_S3D_SUPPORT + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_GET_S3D) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorS3DMode; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_REORDER_MODE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamReorderMode; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_ANDROID + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_HDR_STATIC_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoHdrStaticInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_HDR10_PLUS_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoHdr10PlusInfo; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_CONFIG_DISPLAY_DELAY) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosConfigDisplayDelay; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_DISPLAY_DELAY) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamDisplayDelay; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_ANDROID + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_USE_IMG_CONV) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamImageConvert; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + } + + ret = Exynos_OMX_VideoDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_HEVC_DEC_ROLE); + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_HevcDec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + + ExynosVideoInstInfo *pVideoInstInfo = &(pHevcDec->hMFCHevcHandle.videoInstInfo); + CSC_METHOD csc_method = CSC_METHOD_SW; + int i; + + FunctionIn(); + + pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc = OMX_FALSE; + pHevcDec->hMFCHevcHandle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pExynosInputPort->portDefinition.format.video.nFrameWidth, + pExynosInputPort->portDefinition.format.video.nFrameHeight, + pExynosInputPort->portDefinition.format.video.nBitrate, + pExynosInputPort->portDefinition.format.video.xFramerate); + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pExynosInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pExynosInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pExynosInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pExynosInputPort->portDefinition.format.video.xFramerate; + + /* HEVC Codec Open */ + ret = HevcCodecOpen(pHevcDec, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + nAllocLen[0] = ALIGN(pExynosInputPort->portDefinition.format.video.nFrameWidth * + pExynosInputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + if (nAllocLen[0] < pVideoDec->nMinInBufSize) + nAllocLen[0] = pVideoDec->nMinInBufSize; + + Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX, MFC_INPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_SetPlaneToPort(pExynosOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SemaphoreCreate(&pExynosOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pHevcDec->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pHevcDec->hSourceStartEvent); + pHevcDec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pHevcDec->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pHevcDec->hDestinationOutStartEvent); + + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pHevcDec->hMFCHevcHandle.indexTimestamp = 0; + pHevcDec->hMFCHevcHandle.outputIndexTimestamp = 0; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pHevcDec->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) { + pVideoDec->csc_handle = csc_init(CSC_METHOD_HW); + csc_set_hw_property(pVideoDec->csc_handle, CSC_HW_PROPERTY_FIXED_NODE, 2); + csc_set_hw_property(pVideoDec->csc_handle, CSC_HW_PROPERTY_MODE_DRM, 1); + } else { + pVideoDec->csc_handle = csc_init(csc_method); + } + + if (pVideoDec->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pVideoDec->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_HevcDec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoDec != NULL) { + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + if (pHevcDec != NULL) { + Exynos_OSAL_QueueTerminate(&pHevcDec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pHevcDec->hDestinationInStartEvent); + pHevcDec->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pHevcDec->hDestinationOutStartEvent); + pHevcDec->hDestinationOutStartEvent = NULL; + pHevcDec->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pHevcDec->hSourceStartEvent); + pHevcDec->hSourceStartEvent = NULL; + pHevcDec->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + if (pHevcDec != NULL) { + HevcCodecClose(pHevcDec); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_SrcIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pHevcDec->hMFCHevcHandle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pHevcDec->hMFCHevcHandle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_BOOL bInStartCode = OMX_FALSE; + + FunctionIn(); + + if (pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc == OMX_FALSE) { + ret = HevcCodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (pHevcDec->bDestinationStart == OMX_FALSE) && + (pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_FALSE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = HevcCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to HevcCodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + } + + if (((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) || + ((bInStartCode = Check_HEVC_StartCode(pSrcInputData->buffer.addr[0], oneFrameSize)) == OMX_TRUE)) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + if (pVideoDec->bReorderMode == OMX_FALSE) { + /* next slot will be used like as circular queue */ + pExynosComponent->timeStamp[pHevcDec->hMFCHevcHandle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->nFlags[pHevcDec->hMFCHevcHandle.indexTimestamp] = pSrcInputData->nFlags; + } else { /* MSRND */ + Exynos_SetReorderTimestamp(pExynosComponent, &(pHevcDec->hMFCHevcHandle.indexTimestamp), pSrcInputData->timeStamp, pSrcInputData->nFlags); + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), dataLen(%d), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, oneFrameSize, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pHevcDec->hMFCHevcHandle.indexTimestamp); + + pDecOps->Set_FrameTag(hMFCHandle, pHevcDec->hMFCHevcHandle.indexTimestamp); + + pHevcDec->hMFCHevcHandle.indexTimestamp++; + pHevcDec->hMFCHevcHandle.indexTimestamp %= MAX_TIMESTAMP; + + if (pVideoDec->bQosChanged == OMX_TRUE) { + if (pHevcDec->hMFCHevcHandle.videoInstInfo.supportInfo.dec.bOperatingRateSupport == VIDEO_TRUE) { + if (pDecOps->Set_OperatingRate != NULL) + pDecOps->Set_OperatingRate(hMFCHandle, pVideoDec->nOperatingRate); + } else if (pDecOps->Set_QosRatio != NULL) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + } + + pVideoDec->bQosChanged = OMX_FALSE; + } + + if (pVideoDec->bSearchBlackBarChanged == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] BlackBar searching mode : %s", + pExynosComponent, __FUNCTION__, + (pVideoDec->bSearchBlackBar == OMX_TRUE) ? "enable" : "disable"); + pDecOps->Set_SearchBlackBar(hMFCHandle, (ExynosVideoBoolType)pVideoDec->bSearchBlackBar); + pVideoDec->bSearchBlackBarChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + pPrivate = (void *)pSrcInputData->bufferHeader; + } else { + nAllocLen[0] = pSrcInputData->allocSize; + + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + goto EXIT; + } + + HevcCodecStart(pOMXComponent, INPUT_PORT_INDEX); + if (pHevcDec->bSourceStart == OMX_FALSE) { + pHevcDec->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pHevcDec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + if ((pHevcDec->bDestinationStart == OMX_FALSE) && + (pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_TRUE)) { + pHevcDec->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pHevcDec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pHevcDec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] can't find a start code", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedFrame; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_SrcOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pInbufOps = pHevcDec->hMFCHevcHandle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc == OMX_TRUE) { + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + else + pVideoBuffer = NULL; + } else { + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + pSrcOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == + pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]) { + pVideoDec->pMFCDecInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoDec->pMFCDecInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pExynosInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_DstIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) { + nAllocLen[i] = pHevcDec->hMFCHevcHandle.codecOutbufConf.nAlignPlaneSize[i]; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] ADDR[%d]: 0x%x, size[%d]: %d", pExynosComponent, __FUNCTION__, + i, pDstInputData->buffer.addr[i], i, nAllocLen[i]); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + } + + goto EXIT; + } + + HevcCodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_DstOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pHevcDec->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + + ExynosVideoDecOps *pDecOps = pHevcDec->hMFCHevcHandle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + ExynosVideoGeometry *bufferGeometry = NULL; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + ExynosVideoColorFormatType nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + OMX_COLOR_FORMATTYPE nOMXFormat = OMX_COLOR_FormatUnused; + OMX_U32 nPixelFormat = 0; + + FunctionIn(); + + if (pHevcDec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + Exynos_OSAL_Memset(&videoBuffer, 0, sizeof(ExynosVideoBuffer)); + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO) at ExtensionDequeue", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + displayStatus = pVideoBuffer->displayStatus; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus: 0x%x", pExynosComponent, __FUNCTION__, displayStatus); + + if ((displayStatus == VIDEO_FRAME_STATUS_DISPLAY_DECODING) || + (displayStatus == VIDEO_FRAME_STATUS_DISPLAY_ONLY) || + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_ENABLED_S3D) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + (CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + +#ifdef USE_S3D_SUPPORT + /* Check Whether frame packing information is available */ + if ((pHevcDec->hMFCHevcHandle.S3DFPArgmtType == OMX_SEC_FPARGMT_INVALID) && + (pVideoDec->bThumbnailMode == OMX_FALSE) && + ((displayStatus == VIDEO_FRAME_STATUS_DISPLAY_ONLY) || + (displayStatus == VIDEO_FRAME_STATUS_DISPLAY_DECODING) || + (displayStatus == VIDEO_FRAME_STATUS_ENABLED_S3D))) { + if (HevcCodecCheckFramePacking(pOMXComponent) != OMX_TRUE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } +#endif + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + ((displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (displayStatus == VIDEO_FRAME_STATUS_ENABLED_S3D))) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pOutputPort->exceptionFlag = NEED_PORT_FLUSH; + pVideoDec->bReconfigDPB = OMX_TRUE; + HevcCodecUpdateResolution(pOMXComponent); + pVideoDec->csc_set_format = OMX_FALSE; +#ifdef USE_S3D_SUPPORT + pHevcDec->hMFCHevcHandle.S3DFPArgmtType = OMX_SEC_FPARGMT_INVALID; +#endif + } + ret = OMX_ErrorNone; + goto EXIT; + } + + pHevcDec->hMFCHevcHandle.outputIndexTimestamp++; + pHevcDec->hMFCHevcHandle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->allocSize = pDstOutputData->dataLen = 0; + nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + nDataLen[plane] = pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pHevcDec->hMFCHevcHandle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->cropRect.nLeft = bufferGeometry->cropRect.nLeft; + pBufferInfo->cropRect.nTop = bufferGeometry->cropRect.nTop; + pBufferInfo->cropRect.nWidth = bufferGeometry->cropRect.nWidth; + pBufferInfo->cropRect.nHeight = bufferGeometry->cropRect.nHeight; + pBufferInfo->colorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + + /* calculate each plane info for the application */ + Exynos_OSAL_GetPlaneSize(pOutputPort->portDefinition.format.video.eColorFormat, + PLANE_SINGLE, pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + nDataLen, nAllocLen); + + pDstOutputData->allocSize = nAllocLen[0] + nAllocLen[1] + nAllocLen[2]; + pDstOutputData->dataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + /* update extra info */ + { + /* HDR */ + if (pVideoBuffer->frameType & VIDEO_FRAME_WITH_HDR_INFO) + HevcCodecUpdateHdrInfo(pOMXComponent, pBufferInfo); + + /* SBWC Normal format */ + if (pVideoBuffer->frameType & VIDEO_FRAME_NEED_ACTUAL_FORMAT) { + nVideoFormat = pDecOps->Get_ActualFormat(hMFCHandle); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + nOMXFormat = Exynos_OSAL_Video2OMXFormat((int)nVideoFormat); + + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nPixelFormat = Exynos_OSAL_OMX2HALPixelFormat(nOMXFormat, pOutputPort->ePlaneType); + + if (nPixelFormat != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Normal format at SBWC is 0x%x", + pExynosComponent, __FUNCTION__, nPixelFormat); + pHevcDec->hMFCHevcHandle.nActualFormat = nPixelFormat; + } + } + } + } + } + + /* update extra information to vendor path for renderer + * if BUFFER_COPY_FORCE is used, it will be updated at Exynos_CSC_OutputData() + */ + if ((pOutputPort->bufferProcessType == BUFFER_SHARE) && + (pVideoBuffer->planes[2].addr != NULL)) { + HevcCodecUpdateExtraInfo(pOMXComponent, pVideoBuffer->planes[2].addr); + } + + indexTimestamp = pDecOps->Get_FrameTag(hMFCHandle); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + + if (pVideoDec->bReorderMode == OMX_FALSE) { + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if ((pExynosComponent->checkTimeStamp.needSetStartTimeStamp != OMX_TRUE) && + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp != OMX_TRUE)) { + if (indexTimestamp == INDEX_AFTER_EOS) { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } else { + pDstOutputData->timeStamp = pExynosComponent->timeStamp[pHevcDec->hMFCHevcHandle.outputIndexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[pHevcDec->hMFCHevcHandle.outputIndexTimestamp]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] missing out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + } + } else { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } + } else { + /* For timestamp correction. if mfc support frametype detect */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] disp_pic_frame_type: %d", pExynosComponent, __FUNCTION__, pVideoBuffer->frameType); + + /* NEED TIMESTAMP REORDER */ + if (pVideoDec->bDTSMode == OMX_TRUE) { + if ((pVideoBuffer->frameType & VIDEO_FRAME_I) || + ((pVideoBuffer->frameType & VIDEO_FRAME_OTHERS) && + ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) || + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE)) + pHevcDec->hMFCHevcHandle.outputIndexTimestamp = indexTimestamp; + else + indexTimestamp = pHevcDec->hMFCHevcHandle.outputIndexTimestamp; + } + + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp] | OMX_BUFFERFLAG_ENDOFFRAME; + + if (pVideoBuffer->frameType & VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + } else { /* MSRND */ + EXYNOS_OMX_CURRENT_FRAME_TIMESTAMP sCurrentTimestamp; + + Exynos_GetReorderTimestamp(pExynosComponent, &sCurrentTimestamp, indexTimestamp, pVideoBuffer->frameType); + + pDstOutputData->timeStamp = sCurrentTimestamp.timeStamp; + pDstOutputData->nFlags = sCurrentTimestamp.nFlags | OMX_BUFFERFLAG_ENDOFFRAME; + + pExynosComponent->nFlags[sCurrentTimestamp.nIndex] = 0x00; + pExynosComponent->bTimestampSlotUsed[sCurrentTimestamp.nIndex] = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), reordered tag: %d, original tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + sCurrentTimestamp.nIndex, + indexTimestamp); + } + + if (pVideoBuffer->frameType & VIDEO_FRAME_WITH_BLACK_BAR) { + if (HevcCodecUpdateBlackBarCrop(pOMXComponent) != OMX_ErrorNone) + goto EXIT; + } + + if (pVideoBuffer->frameType & VIDEO_FRAME_CONCEALMENT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + if (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) { + pDstOutputData->remainDataLen = 0; + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp != INDEX_AFTER_EOS) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] tag(%d) is wrong", pExynosComponent, __FUNCTION__, indexTimestamp); + + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + goto EXIT; + } + + if ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) || + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->nFlags[indexTimestamp] &= (~OMX_BUFFERFLAG_EOS); + } + } else if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + pDstOutputData->remainDataLen = 0; + + if (pExynosComponent->bBehaviorEOS == OMX_TRUE) { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_srcInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + ret = Exynos_HevcDec_SrcIn(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorInputDataDecodeYet) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorNeedNextHeaderInfo) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorNoneSrcSetupFinish) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorCorruptedFrame)) { + + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pVideoDec->bDiscardCSDError == OMX_TRUE)) { + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_srcOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if ((pHevcDec->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosInputPort))) { + Exynos_OSAL_SignalWait(pHevcDec->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pHevcDec->hSourceStartEvent); + } + + ret = Exynos_HevcDec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_dstInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + if (pExynosComponent->currentState == OMX_StatePause) + ret = (OMX_ERRORTYPE)OMX_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pHevcDec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pHevcDec->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pHevcDec->hDestinationInStartEvent); + } + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pHevcDec->bypassBufferInfoQ) > 0) { + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pHevcDec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = HevcCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to HevcCodecDstSetup(0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + Exynos_OSAL_SignalSet(pHevcDec->hDestinationOutStartEvent); + } + } + + if (pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_HevcDec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + if ((pHevcDec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HevcDec_dstOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (((pHevcDec->bDestinationStart == OMX_FALSE) || + (pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_FALSE)) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pHevcDec->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pHevcDec->hDestinationOutStartEvent); + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if (Exynos_OSAL_GetElemNum(&pHevcDec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pHevcDec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_HevcDec_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && + (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + OMX_BOOL bSecureMode = OMX_FALSE; + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_HEVC_DEC, componentName) == 0) { + bSecureMode = OMX_FALSE; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_HEVC_DRM_DEC, componentName) == 0) { + bSecureMode = OMX_TRUE; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = (bSecureMode == OMX_TRUE)? HW_VIDEO_DEC_SECURE_CODEC:HW_VIDEO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pHevcDec = Exynos_OSAL_Malloc(sizeof(EXYNOS_HEVCDEC_HANDLE)); + if (pHevcDec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pHevcDec, 0, sizeof(EXYNOS_HEVCDEC_HANDLE)); + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoDec->hCodecHandle = (OMX_HANDLETYPE)pHevcDec; + pHevcDec->hMFCHevcHandle.nDisplayDelay = MAX_HEVC_DISPLAYDELAY_VALIDNUM + 1; + + Exynos_OSAL_Strcpy(pExynosComponent->componentName, componentName); + +#ifdef USE_S3D_SUPPORT + pHevcDec->hMFCHevcHandle.S3DFPArgmtType = OMX_SEC_FPARGMT_INVALID; +#endif + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pExynosPort->portDefinition.nBufferSize = CUSTOM_LIMITED_DRM_INPUT_BUFFER_SIZE; + else +#endif + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + } + + pVideoDec->nMinInBufSize = DEFAULT_VIDEO_MIN_INPUT_BUFFER_SIZE; /* for DRC */ + + pExynosPort->portDefinition.format.video.eCompressionFormat = (OMX_VIDEO_CODINGTYPE)OMX_VIDEO_CodingHEVC; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/hevc"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + +#ifdef USE_SINGLE_PLANE_IN_DRM + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pExynosPort->ePlaneType = PLANE_SINGLE; +#endif + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pHevcDec->HevcComponent[i], OMX_VIDEO_PARAM_HEVCTYPE); + pHevcDec->HevcComponent[i].nPortIndex = i; + pHevcDec->HevcComponent[i].eProfile = OMX_VIDEO_HEVCProfileMain; + pHevcDec->HevcComponent[i].eLevel = OMX_VIDEO_HEVCMainTierLevel5; + } + + pOMXComponent->GetParameter = &Exynos_HevcDec_GetParameter; + pOMXComponent->SetParameter = &Exynos_HevcDec_SetParameter; + pOMXComponent->GetConfig = &Exynos_HevcDec_GetConfig; + pOMXComponent->SetConfig = &Exynos_HevcDec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_HevcDec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_HevcDec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_HevcDec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_HevcDec_Terminate; + + pVideoDec->exynos_codec_srcInputProcess = &Exynos_HevcDec_srcInputBufferProcess; + pVideoDec->exynos_codec_srcOutputProcess = &Exynos_HevcDec_srcOutputBufferProcess; + pVideoDec->exynos_codec_dstInputProcess = &Exynos_HevcDec_dstInputBufferProcess; + pVideoDec->exynos_codec_dstOutputProcess = &Exynos_HevcDec_dstOutputBufferProcess; + + pVideoDec->exynos_codec_start = &HevcCodecStart; + pVideoDec->exynos_codec_stop = &HevcCodecStop; + pVideoDec->exynos_codec_bufferProcessRun = &HevcCodecOutputBufferProcessRun; + pVideoDec->exynos_codec_enqueueAllBuffer = &HevcCodecEnQueueAllBuffer; + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &HevcCodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &HevcCodecCheckResolution; + + pVideoDec->exynos_codec_updateExtraInfo = &HevcCodecUpdateExtraInfo; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pHevcDec); + pHevcDec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pHevcDec->hMFCHevcHandle.videoInstInfo.eCodecType = VIDEO_CODING_HEVC; + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pHevcDec->hMFCHevcHandle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pHevcDec->hMFCHevcHandle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + if (Exynos_Video_GetInstInfo(&(pHevcDec->hMFCHevcHandle.videoInstInfo), VIDEO_TRUE /* dec */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pHevcDec); + pHevcDec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pHevcDec->hMFCHevcHandle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport == VIDEO_TRUE) + pVideoDec->bDrvDPBManaging = OMX_TRUE; + else + pVideoDec->hRefHandle = Exynos_OSAL_RefCount_Create(); + + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec : skype(%d)/HDR-DY(%d)/DrvDPBManaging(%d)", pExynosComponent, __FUNCTION__, + (pHevcDec->hMFCHevcHandle.videoInstInfo.supportInfo.dec.bSkypeSupport), + (pHevcDec->hMFCHevcHandle.videoInstInfo.supportInfo.dec.bHDRDynamicInfoSupport), + (pHevcDec->hMFCHevcHandle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport)); + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-dec-use-buffer-copy", (OMX_INDEXTYPE)OMX_IndexExynosParamBufferCopy); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-dec-compressed-color-format", (OMX_INDEXTYPE)OMX_IndexParamVideoCompressedColorFormat); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-imageformat-filter-enableInplace", (OMX_INDEXTYPE)OMX_IndexExynosParamImageConvertMode); +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit( + OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoDec->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pHevcDec != NULL) { + Exynos_OSAL_Free(pHevcDec); + pHevcDec = pVideoDec->hCodecHandle = NULL; + } + + ret = Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/dec/hevc/Exynos_OMX_HEVCdec.h b/openmax/component/video/dec/hevc/Exynos_OMX_HEVCdec.h new file mode 100644 index 0000000..df12ad4 --- /dev/null +++ b/openmax/component/video/dec/hevc/Exynos_OMX_HEVCdec.h @@ -0,0 +1,101 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_HEVCdec.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2013.07.26 : Create + */ + +#ifndef EXYNOS_OMX_HEVC_DEC_COMPONENT +#define EXYNOS_OMX_HEVC_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" +#include "ExynosVideoApi.h" + + +typedef struct _EXYNOS_MFC_HEVCDEC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + OMX_S32 maxDPBNum; + + /* for custom component(MSRND) */ + #define MAX_HEVC_DISPLAYDELAY_VALIDNUM 8 + OMX_U32 nDisplayDelay; + + /* extra info which will be shared with renderer */ + ExynosVideoHdrInfo sHdrInfo; + OMX_U32 nActualFormat; + +#ifdef USE_S3D_SUPPORT + EXYNOS_OMX_FPARGMT_TYPE S3DFPArgmtType; +#endif + + ExynosVideoColorFormatType MFCOutputColorType; + ExynosVideoDecOps *pDecOps; + ExynosVideoDecBufferOps *pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 4 + OMX_VIDEO_HEVCPROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_HEVCLEVELTYPE maxLevel; +} EXYNOS_MFC_HEVCDEC_HANDLE; + +typedef struct _EXYNOS_HEVCDEC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_HEVCTYPE HevcComponent[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + + /* EXYNOS MFC Codec specific */ + EXYNOS_MFC_HEVCDEC_HANDLE hMFCHevcHandle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_HEVCDEC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE HevcCodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/hevc/NOTICE b/openmax/component/video/dec/hevc/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/dec/hevc/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/dec/hevc/library_register.c b/openmax/component/video/dec/hevc/library_register.c new file mode 100644 index 0000000..b2fe0ea --- /dev/null +++ b/openmax/component/video/dec/hevc/library_register.c @@ -0,0 +1,65 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2013.07.26 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_HEVC_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register( + ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - video decoder HEVC */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_HEVC_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_HEVC_DEC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 2 - video decoder HEVC for DRM */ + Exynos_OSAL_Strcpy(ppExynosComponent[1]->componentName, EXYNOS_OMX_COMPONENT_HEVC_DRM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[1]->roles[0], EXYNOS_OMX_COMPONENT_HEVC_DEC_ROLE); + ppExynosComponent[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/openmax/component/video/dec/hevc/library_register.h b/openmax/component/video/dec/hevc/library_register.h new file mode 100644 index 0000000..5e3fed0 --- /dev/null +++ b/openmax/component/video/dec/hevc/library_register.h @@ -0,0 +1,62 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2013.07.26 : Create + */ + +#ifndef EXYNOS_OMX_HEVC_DEC_REG +#define EXYNOS_OMX_HEVC_DEC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 2 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* HEVC */ +#ifndef USE_CUSTOM_COMPONENT_SUPPORT +#define EXYNOS_OMX_COMPONENT_HEVC_DEC "OMX.Exynos.HEVC.Decoder" +#define EXYNOS_OMX_COMPONENT_HEVC_DRM_DEC "OMX.Exynos.HEVC.Decoder.secure" +#else +#define EXYNOS_OMX_COMPONENT_HEVC_DEC "OMX.Exynos.hevc.dec" +#define EXYNOS_OMX_COMPONENT_HEVC_DRM_DEC "OMX.Exynos.hevc.dec.secure" +#endif + +#define EXYNOS_OMX_COMPONENT_HEVC_DEC_ROLE "video_decoder.hevc" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/mpeg2/Android.mk b/openmax/component/video/dec/mpeg2/Android.mk new file mode 100644 index 0000000..0ce8110 --- /dev/null +++ b/openmax/component/video/dec/mpeg2/Android.mk @@ -0,0 +1,87 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Mpeg2dec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.MPEG2.Decoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/dec \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_SMALL_SECURE_MEMORY), true) +LOCAL_CFLAGS += -DUSE_SMALL_SECURE_MEMORY +endif + +ifeq ($(BOARD_USE_COMPRESSED_COLOR), true) +LOCAL_CFLAGS += -DUSE_COMPRESSED_COLOR +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.c b/openmax/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.c new file mode 100644 index 0000000..5d48781 --- /dev/null +++ b/openmax/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.c @@ -0,0 +1,3439 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Mpeg2dec.c + * @brief + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @version 2.0.0 + * @history + * 2012.07.10 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Vdec.h" +#include "Exynos_OMX_VdecControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Mpeg2dec.h" +#include "ExynosVideoApi.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" + +#include "Exynos_OSAL_Platform.h" + +#include "VendorVideoAPI.h" + +/* To use CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */ +/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_MPEG2_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg2Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg2Dec->hMFCMpeg2Handle.profiles[nProfileCnt++] = OMX_VIDEO_MPEG2ProfileSimple; + pMpeg2Dec->hMFCMpeg2Handle.profiles[nProfileCnt++] = OMX_VIDEO_MPEG2ProfileMain; + pMpeg2Dec->hMFCMpeg2Handle.nProfileCnt = nProfileCnt; + pMpeg2Dec->hMFCMpeg2Handle.maxLevel = OMX_VIDEO_MPEG2LevelHL; + +EXIT: + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + int nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg2Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pMpeg2Dec->hMFCMpeg2Handle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pMpeg2Dec->hMFCMpeg2Handle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pMpeg2Dec->hMFCMpeg2Handle.maxLevel; +#else + while ((pMpeg2Dec->hMFCMpeg2Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + nLevelCnt += 1; /* OMX_VIDEO_MPEG2LevelLL : 0 */ + + if ((pMpeg2Dec->hMFCMpeg2Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pMpeg2Dec->hMFCMpeg2Handle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pMpeg2Dec->hMFCMpeg2Handle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg2Dec == NULL) + goto EXIT; + + while ((pMpeg2Dec->hMFCMpeg2Handle.maxLevel >> nLevelCnt++) > 0); + nLevelCnt += 1; /* OMX_VIDEO_MPEG2LevelLL : 0 */ + + if ((pMpeg2Dec->hMFCMpeg2Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pMpeg2Dec->hMFCMpeg2Handle.nProfileCnt; i++) { + if (pMpeg2Dec->hMFCMpeg2Handle.profiles[i] == pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + if (pProfileLevelType->eLevel == OMX_VIDEO_MPEG2LevelLL) { + bLevelSupport = OMX_TRUE; + } else { + nLevelCnt--; + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + FunctionOut(); + + return (bProfileSupport && bLevelSupport); +} + +static OMX_ERRORTYPE GetCodecOutputPrivateData(OMX_PTR codecBuffer, OMX_PTR addr[], OMX_U32 size[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pCodecBuffer = NULL; + + if (codecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pCodecBuffer = (ExynosVideoBuffer *)codecBuffer; + + if (addr != NULL) { + addr[0] = pCodecBuffer->planes[0].addr; + addr[1] = pCodecBuffer->planes[1].addr; + addr[2] = pCodecBuffer->planes[2].addr; + } + + if (size != NULL) { + size[0] = pCodecBuffer->planes[0].allocSize; + size[1] = pCodecBuffer->planes[1].allocSize; + size[2] = pCodecBuffer->planes[2].allocSize; + } + +EXIT: + + return ret; +} + +static OMX_BOOL Check_Mpeg2_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize) +{ + OMX_BOOL ret = OMX_FALSE; + + FunctionIn(); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] streamSize: %d", __FUNCTION__, streamSize); + + if (streamSize < 3) { + ret = OMX_FALSE; + goto EXIT; + } + + /* Frame Start code*/ + if (pInputStream[0] != 0x00 || pInputStream[1] != 0x00 || pInputStream[2]!=0x01) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mpeg2 Frame Start Code not Found", __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + + ret = OMX_TRUE; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg2Dec == NULL) + goto EXIT; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pOutputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecOpen(EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec, ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pMpeg2Dec == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pDecOps = (ExynosVideoDecOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecOps)); + pInbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + pOutbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + + if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pMpeg2Dec->hMFCMpeg2Handle.pDecOps = pDecOps; + pMpeg2Dec->hMFCMpeg2Handle.pInbufOps = pInbufOps; + pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pDecOps->nSize = sizeof(ExynosVideoDecOps); + pInbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + + if (Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for decoder ops */ + if ((pDecOps->Init == NULL) || (pDecOps->Finalize == NULL) || + (pDecOps->Get_ActualBufferCount == NULL) || + (pDecOps->Set_FrameTag == NULL) || (pDecOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.pDecOps->Init(pVideoInstInfo); + if (pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pMpeg2Dec->hMFCMpeg2Handle.pDecOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pMpeg2Dec->hMFCMpeg2Handle.pInbufOps = NULL; + } + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecClose(EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pMpeg2Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + + if (hMFCHandle != NULL) { + pDecOps->Finalize(hMFCHandle); + pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle = NULL; + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc = OMX_FALSE; + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Decoder(pDecOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pMpeg2Dec->hMFCMpeg2Handle.pInbufOps = NULL; + } + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pMpeg2Dec->hMFCMpeg2Handle.pDecOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecStart(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg2Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc == OMX_TRUE)) { + pInbufOps->Run(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst == OMX_TRUE)) { + pOutbufOps->Run(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecStop(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg2Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) { + pInbufOps->Stop(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) { + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pOutbufOps->Stop(hMFCHandle); + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) + pOutbufOps->Clear_RegisteredBuffer(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecOutputBufferProcessRun(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg2Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pMpeg2Dec->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pMpeg2Dec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pMpeg2Dec->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pMpeg2Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pMpeg2Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst == OMX_FALSE) { + Exynos_OSAL_SignalSet(pMpeg2Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecReconfigAllBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + ExynosVideoDecBufferOps *pBufferOps = NULL; + + FunctionIn(); + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pMpeg2Dec->bSourceStart == OMX_TRUE)) { + ret = OMX_ErrorNotImplemented; + goto EXIT; + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pMpeg2Dec->bDestinationStart == OMX_TRUE)) { + pBufferOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + + if (pExynosPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /**********************************/ + /* Codec Buffer Free & Unregister */ + /**********************************/ + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst = OMX_FALSE; + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = Mpeg2CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to Mpeg2CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType == BUFFER_SHARE) { + /***************************/ + /* Codec Buffer Unregister */ + /***************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst = OMX_FALSE; + } + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecEnQueueAllBuffer(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + + ExynosVideoDecBufferOps *pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + + int i; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecInputBuffer[i]->fd[0], pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecOutputBuffer[i]->fd[0], pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + +void Mpeg2CodecUpdateHdrInfo(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoHdrInfo *pHdrInfo = &(pMpeg2Dec->hMFCMpeg2Handle.sHdrInfo); + + if (pDecOps->Get_HDRInfo(hMFCHandle, pHdrInfo) == VIDEO_ERROR_NONE) { + /* update bitstream's info to input port */ + EXYNOS_OMX_VIDEO_HDRSTATICINFO *pHDRStaticInfo = &(pOutputPort->HDRStaticInfo); + EXYNOS_OMX_VIDEO_COLORASPECTS *pColorAspects = &(pInputPort->ColorAspects); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eType(0x%x) is changed", pExynosComponent, __FUNCTION__, pHdrInfo->eChangedType); + + /* color aspects */ + if (pHdrInfo->eValidType & (HDR_INFO_COLOR_ASPECTS | HDR_INFO_RANGE)) { + /* HDR_INFO_COLOR_ASPECTS (8) */ + pColorAspects->nCoeffType = pHdrInfo->sColorAspects.eCoeffType; + pColorAspects->nPrimaryType = pHdrInfo->sColorAspects.ePrimariesType; + pColorAspects->nTransferType = pHdrInfo->sColorAspects.eTransferType; + + /* HDR_INFO_RANGE (16) */ + pColorAspects->nRangeType = pHdrInfo->sColorAspects.eRangeType; + + if (pOutputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) { + /* update dataspace in output port from input port */ + Exynos_OSAL_UpdateDataSpaceFromBitstream(pExynosComponent); + } + } + +#ifdef USE_ANDROID + /* if both have changed, should send an event once */ + if (pHdrInfo->eChangedType & (HDR_INFO_COLOR_ASPECTS | HDR_INFO_RANGE)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_IndexConfigVideoColorAspects)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigVideoColorAspects, + NULL); + } +#endif + } + +EXIT: + return; +} + +OMX_ERRORTYPE Mpeg2CodecUpdateExtraInfo( + OMX_COMPONENTTYPE *pOMXComponent, + ExynosVideoMeta *pMeta) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + + if (pMeta == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMeta->eType = VIDEO_INFO_TYPE_INVALID; + + /* interlace */ + { + if (pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] interlace type = %x", + pExynosComponent, __FUNCTION__, pMpeg2Dec->hMFCMpeg2Handle.interlacedType); + pMeta->eType |= VIDEO_INFO_TYPE_INTERLACED; + pMeta->data.dec.nInterlacedType = pMpeg2Dec->hMFCMpeg2Handle.interlacedType; + } + } + + /* Normal format for SBWC black bar */ + { + if (pMpeg2Dec->hMFCMpeg2Handle.nActualFormat != 0) { + pMeta->nPixelFormat = pMpeg2Dec->hMFCMpeg2Handle.nActualFormat; + pMeta->eType |= VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT; + + pMpeg2Dec->hMFCMpeg2Handle.nActualFormat = 0; + } else { + pMeta->nPixelFormat = 0; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecUpdateBlackBarCrop(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + OMX_CONFIG_RECTTYPE *pBlackBarCropRect = &pVideoDec->blackBarCropRect; + + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + ExynosVideoRect CropRect; + + FunctionIn(); + + Exynos_OSAL_Memset(&CropRect, 0, sizeof(ExynosVideoRect)); + if (pOutbufOps->Get_BlackBarCrop(hMFCHandle, &CropRect) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get crop info", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + + pBlackBarCropRect->nLeft = CropRect.nLeft; + pBlackBarCropRect->nTop = CropRect.nTop; + pBlackBarCropRect->nWidth = CropRect.nWidth; + pBlackBarCropRect->nHeight = CropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Black Bar Info: LEFT(%d) TOP(%d) WIDTH(%d) HEIGHT(%d)", + pExynosComponent, __FUNCTION__, + pBlackBarCropRect->nLeft, pBlackBarCropRect->nTop, + pBlackBarCropRect->nWidth, pBlackBarCropRect->nHeight); + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + (OMX_INDEXTYPE)OMX_IndexConfigBlackBarCrop, + NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecCheckResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_EXCEPTION_STATE eOutputExcepState = pOutputPort->exceptionFlag; + + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + + OMX_CONFIG_RECTTYPE *pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = &(pInputPort->portDefinition); + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = &(pOutputPort->portDefinition); + + int maxDPBNum = 0; + + FunctionIn(); + + /* get geometry */ + Exynos_OSAL_Memset(&codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to get geometry"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + maxDPBNum += EXTRA_DPB_NUM; + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + } + + /* resolution is changed */ + if ((codecOutbufConf.nFrameWidth != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth) || + (codecOutbufConf.nFrameHeight != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight) || + (codecOutbufConf.nStride != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nStride) || +#if 0 // TODO: check posibility + (codecOutbufConf.eColorFormat != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eColorFormat) || + (codecOutbufConf.eFilledDataType != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eFilledDataType) || +#endif + (maxDPBNum != pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] DPB(%d), FORMAT(0x%x), TYPE(0x%x) -> DPB(%d), FORMAT(0x%x), TYPE(0x%x)", + pExynosComponent, __FUNCTION__, + pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eColorFormat, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eFilledDataType, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType); + + pInputPortDefinition->format.video.nFrameWidth = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = codecOutbufConf.nFrameHeight; + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = maxDPBNum; + pOutputPortDefinition->nBufferCountMin = maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* crop info of contents is changed */ + if ((codecOutbufConf.cropRect.nTop != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nTop) || + (codecOutbufConf.cropRect.nLeft != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nLeft) || + (codecOutbufConf.cropRect.nWidth != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nWidth) || + (codecOutbufConf.cropRect.nHeight != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nHeight)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nWidth, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nHeight, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + Exynos_OSAL_Memcpy(&pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf, &codecOutbufConf, sizeof(codecOutbufConf)); + pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum = maxDPBNum; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + + OMX_CONFIG_RECTTYPE *pCropRectangle = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = NULL; + + OMX_BOOL bFormatChanged = OMX_FALSE; + + FunctionIn(); + + /* get geometry for output */ + Exynos_OSAL_Memset(&pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum += EXTRA_DPB_NUM; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] maxDPBNum: %d", pExynosComponent, __FUNCTION__, pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum); + + /* get interlace info */ + if (pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] contents is interlaced type", pExynosComponent, __FUNCTION__); + + pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] past info: width(%d) height(%d)", + pExynosComponent, __FUNCTION__, + pInputPortDefinition->format.video.nFrameWidth, + pInputPortDefinition->format.video.nFrameHeight); + + /* output format is changed internally (8bit <> 10bit) */ + if (pMpeg2Dec->hMFCMpeg2Handle.MFCOutputColorType != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eColorFormat) { + OMX_COLOR_FORMATTYPE eOutputFormat = Exynos_OSAL_Video2OMXFormat(pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eColorFormat); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] The format(%x) is changed to %x by H/W Codec", + pExynosComponent, __FUNCTION__, + pMpeg2Dec->hMFCMpeg2Handle.MFCOutputColorType, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eColorFormat); + + pMpeg2Dec->hMFCMpeg2Handle.MFCOutputColorType = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eColorFormat; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pOutputPort->ePlaneType)); + + bFormatChanged = OMX_TRUE; + + if (!(pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eFilledDataType & DATA_TYPE_8BIT_SBWC)) { + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* SBWC to non SBWC : must update eColorFormat */ + pOutputPort->portDefinition.format.video.eColorFormat = eOutputFormat; + } + + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } else { + pVideoDec->nCompColorFormat = eOutputFormat; + } + } + + switch (pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eFilledDataType) { + case DATA_8BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_8BIT_SBWC; + break; + case DATA_10BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_10BIT_SBWC; + break; + default: + pVideoDec->eDataType = DATA_TYPE_8BIT; + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] resolution info: width(%d / %d), height(%d / %d)", + pExynosComponent, __FUNCTION__, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nWidth, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nHeight); + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nHeight; + } + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight; +#if 0 + /* don't need to change */ + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; +#endif + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } else if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPortDefinition->nBufferCountActual != pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum) || + ((OMX_S32)pOutputPortDefinition->nBufferCountMin < pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight; + + pOutputPortDefinition->nBufferCountActual = pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* contents has crop info */ + if ((pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nWidth) || + (pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nHeight)) { + + if ((pOutputPort->bufferProcessType & BUFFER_COPY) && + (pExynosComponent->bUseImgCrop == OMX_TRUE)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + } + + pInputPortDefinition->format.video.nFrameWidth = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged) with crop", + pExynosComponent, __FUNCTION__); + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecHeaderDecoding(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecBufferOps *pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + + FunctionIn(); + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + nAllocLen[0] = pSrcInputData->allocSize; + } + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enqueue input buffer for header parsing", pExynosComponent, __FUNCTION__); +// ret = OMX_ErrorInsufficientResources; + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* start header parsing */ + if (pInbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run input buffer for header parsing", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* get geometry for output */ + Exynos_OSAL_Memset(&pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedHeader; + + if ((pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", pExynosComponent, __FUNCTION__, + *((OMX_U8 *)pSrcInputData->buffer.addr[0]) , *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 1), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 2), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 3), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 4), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 5), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 6), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 7)); + } + + pInbufOps->Stop(hMFCHandle); + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} +OMX_ERRORTYPE Mpeg2CodecSrcSetup(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 allocFrameSize = 0; + OMX_COLOR_FORMATTYPE eOutputFormat = pExynosOutputPort->portDefinition.format.video.eColorFormat; + + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + + FunctionIn(); + + if ((pSrcInputData->dataLen <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pMpeg2Dec->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pMpeg2Dec->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SignalSet(pMpeg2Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pVideoDec->bThumbnailMode == OMX_TRUE) + pDecOps->Set_IFrameDecoding(hMFCHandle); + + if ((pDecOps->Enable_DTSMode != NULL) && + (pVideoDec->bDTSMode == OMX_TRUE)) + pDecOps->Enable_DTSMode(hMFCHandle); + + if (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.supportInfo.dec.bPrioritySupport == VIDEO_TRUE) + pDecOps->Set_Priority(hMFCHandle, pVideoDec->nPriority); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eCompressionFormat = VIDEO_CODING_MPEG2; + pInbufOps->Set_Shareable(hMFCHandle); + + allocFrameSize = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + allocFrameSize = pSrcInputData->allocSize; + } + + bufferConf.nSizeImage = allocFrameSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + nInBufferCnt = MAX_INPUTBUFFER_NUM_DYNAMIC; + + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + +#ifdef USE_COMPRESSED_COLOR + if ((pExynosOutputPort->eMetaDataType != METADATA_TYPE_GRAPHIC) || + (pExynosOutputPort->bForceUseNonCompFormat == OMX_TRUE)) { + /* use SBWC format only ANB scenario */ + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } +#endif + + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* For SBWC format setting */ + bSupportFormat = CheckFormatHWSupport(pExynosComponent, pVideoDec->nCompColorFormat); + if (bSupportFormat == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] set compressed color format(0x%x)", + pExynosComponent, __FUNCTION__, (OMX_U32)pVideoDec->nCompColorFormat); + + eOutputFormat = pVideoDec->nCompColorFormat; + } + } + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] omx format(0x%x) is %s by h/w", + pExynosComponent, __FUNCTION__, eOutputFormat, + (bSupportFormat == OMX_TRUE)? "supported":"not supported"); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eOutputFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pExynosOutputPort->ePlaneType)); + } else { + OMX_COLOR_FORMATTYPE eCheckFormat = OMX_SEC_COLOR_FormatNV12Tiled; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + if (bSupportFormat != OMX_TRUE) { + eCheckFormat = OMX_COLOR_FormatYUV420SemiPlanar; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + } + if (bSupportFormat == OMX_TRUE) { /* supported by CSC(NV12T/NV12 -> format) */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eCheckFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eCheckFormat, pExynosOutputPort->ePlaneType)); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not support this format (0x%x)", pExynosComponent, __FUNCTION__, eOutputFormat); + ret = OMX_ErrorNotImplemented; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + } + + pMpeg2Dec->hMFCMpeg2Handle.MFCOutputColorType = bufferConf.eColorFormat; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output video format is 0x%x", + pExynosComponent, __FUNCTION__, bufferConf.eColorFormat); + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + ret = Mpeg2CodecHeaderDecoding(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc = OMX_TRUE; + + Mpeg2CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + ret = Mpeg2CodecUpdateResolution(pOMXComponent); + if (ret != OMX_ErrorNone) { + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc = OMX_FALSE; + Mpeg2CodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] first frame will be re-pushed to input", pExynosComponent, __FUNCTION__); + + Mpeg2CodecStop(pOMXComponent, INPUT_PORT_INDEX); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nOutbufs, nPlaneCnt; + + FunctionIn(); + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nAlignPlaneSize[i]; + + Mpeg2CodecStop(pOMXComponent, OUTPUT_PORT_INDEX); + + /* for adaptive playback */ + if (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enable Dynamic DPB", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* get dpb count */ + nOutbufs = pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst = OMX_TRUE; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->eMetaDataType == METADATA_TYPE_DISABLED) { + /*************/ + /* TBD */ + /*************/ + /* data buffer : user buffer + * H/W can't accept user buffer directly + */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst = OMX_TRUE; + } + + if (Mpeg2CodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch (nParamIndex) { + case OMX_IndexParamVideoMpeg2: + { + OMX_VIDEO_PARAM_MPEG2TYPE *pDstMpeg2Param = (OMX_VIDEO_PARAM_MPEG2TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG2TYPE *pSrcMpeg2Param = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstMpeg2Param, sizeof(OMX_VIDEO_PARAM_MPEG2TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstMpeg2Param->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcMpeg2Param = &pMpeg2Dec->Mpeg2Component[pDstMpeg2Param->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstMpeg2Param) + nOffset, + ((char *)pSrcMpeg2Param) + nOffset, + sizeof(OMX_VIDEO_PARAM_MPEG2TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_MPEG2_DEC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG2TYPE *pSrcMpeg2Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcMpeg2Component = &pMpeg2Dec->Mpeg2Component[pDstProfileLevel->nPortIndex]; + + pDstProfileLevel->eProfile = pSrcMpeg2Component->eProfile; + pDstProfileLevel->eLevel = pSrcMpeg2Component->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pMpeg2Dec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + default: + ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch (nIndex) { + case OMX_IndexParamVideoMpeg2: + { + OMX_VIDEO_PARAM_MPEG2TYPE *pDstMpeg2Param = NULL; + OMX_VIDEO_PARAM_MPEG2TYPE *pSrcMpeg2Param = (OMX_VIDEO_PARAM_MPEG2TYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcMpeg2Param, sizeof(OMX_VIDEO_PARAM_MPEG2TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcMpeg2Param->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstMpeg2Param = &pMpeg2Dec->Mpeg2Component[pSrcMpeg2Param->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstMpeg2Param) + nOffset, + ((char *)pSrcMpeg2Param) + nOffset, + sizeof(OMX_VIDEO_PARAM_MPEG2TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_MPEG2_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG2TYPE *pDstMpeg2Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstMpeg2Component = &pMpeg2Dec->Mpeg2Component[pSrcProfileLevel->nPortIndex]; + + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstMpeg2Component->eProfile = pSrcProfileLevel->eProfile; + pDstMpeg2Component->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pMpeg2Dec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + default: + ret = Exynos_OMX_VideoDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch (nIndex) { + case OMX_IndexConfigCommonOutputCrop: + { + if (pExynosComponent->bUseImgCrop == OMX_TRUE) { + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + } else { + /* query crop information on bitstream */ + OMX_CONFIG_RECTTYPE *pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + + if (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + goto EXIT; + } + + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pSrcRectType = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + } + break; + default: + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + + switch (nIndex) { + default: + ret = Exynos_OMX_VideoDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + ret = Exynos_OMX_VideoDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_MPEG2_DEC_ROLE); + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_Mpeg2Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + + ExynosVideoInstInfo *pVideoInstInfo = &(pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i; + + FunctionIn(); + + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc = OMX_FALSE; + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pExynosInputPort->portDefinition.format.video.nFrameWidth, + pExynosInputPort->portDefinition.format.video.nFrameHeight, + pExynosInputPort->portDefinition.format.video.nBitrate, + pExynosInputPort->portDefinition.format.video.xFramerate); + + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pExynosInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pExynosInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pExynosInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pExynosInputPort->portDefinition.format.video.xFramerate; + + /* Mpeg2 Codec Open */ + ret = Mpeg2CodecOpen(pMpeg2Dec, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + nAllocLen[0] = ALIGN(pExynosInputPort->portDefinition.format.video.nFrameWidth * + pExynosInputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + if (nAllocLen[0] < pVideoDec->nMinInBufSize) + nAllocLen[0] = pVideoDec->nMinInBufSize; + + Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX, MFC_INPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_SetPlaneToPort(pExynosOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SemaphoreCreate(&pExynosOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pMpeg2Dec->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pMpeg2Dec->hSourceStartEvent); + pMpeg2Dec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pMpeg2Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pMpeg2Dec->hDestinationOutStartEvent); + + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pMpeg2Dec->hMFCMpeg2Handle.indexTimestamp = 0; + pMpeg2Dec->hMFCMpeg2Handle.outputIndexTimestamp = 0; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pMpeg2Dec->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + pVideoDec->csc_handle = csc_init(csc_method); + if (pVideoDec->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pVideoDec->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_Mpeg2Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoDec != NULL) { + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + if (pMpeg2Dec != NULL) { + Exynos_OSAL_QueueTerminate(&pMpeg2Dec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pMpeg2Dec->hDestinationInStartEvent); + pMpeg2Dec->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pMpeg2Dec->hDestinationOutStartEvent); + pMpeg2Dec->hDestinationOutStartEvent = NULL; + pMpeg2Dec->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pMpeg2Dec->hSourceStartEvent); + pMpeg2Dec->hSourceStartEvent = NULL; + pMpeg2Dec->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pMpeg2Dec != NULL) { + Mpeg2CodecClose(pMpeg2Dec); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_SrcIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_BOOL bInStartCode = OMX_FALSE; + + FunctionIn(); + + if (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = Mpeg2CodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (pMpeg2Dec->bDestinationStart == OMX_FALSE) && + (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst == OMX_FALSE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = Mpeg2CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Mpeg2CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + } + + if (((bInStartCode = Check_Mpeg2_StartCode(pSrcInputData->buffer.addr[0], oneFrameSize)) == OMX_TRUE) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + pExynosComponent->timeStamp[pMpeg2Dec->hMFCMpeg2Handle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->nFlags[pMpeg2Dec->hMFCMpeg2Handle.indexTimestamp] = pSrcInputData->nFlags; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), dataLen(%d), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, oneFrameSize, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pMpeg2Dec->hMFCMpeg2Handle.indexTimestamp); + pDecOps->Set_FrameTag(hMFCHandle, pMpeg2Dec->hMFCMpeg2Handle.indexTimestamp); + pMpeg2Dec->hMFCMpeg2Handle.indexTimestamp++; + pMpeg2Dec->hMFCMpeg2Handle.indexTimestamp %= MAX_TIMESTAMP; + + if (pVideoDec->bQosChanged == OMX_TRUE) { + if (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.supportInfo.dec.bOperatingRateSupport == VIDEO_TRUE) { + if (pDecOps->Set_OperatingRate != NULL) + pDecOps->Set_OperatingRate(hMFCHandle, pVideoDec->nOperatingRate); + } else if (pDecOps->Set_QosRatio != NULL) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + } + + pVideoDec->bQosChanged = OMX_FALSE; + } + + if (pVideoDec->bSearchBlackBarChanged == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] BlackBar searching mode : %s", + pExynosComponent, __FUNCTION__, + (pVideoDec->bSearchBlackBar == OMX_TRUE) ? "enable" : "disable"); + pDecOps->Set_SearchBlackBar(hMFCHandle, (ExynosVideoBoolType)pVideoDec->bSearchBlackBar); + pVideoDec->bSearchBlackBarChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + pPrivate = (void *)pSrcInputData->bufferHeader; + } else { + nAllocLen[0] = pSrcInputData->allocSize; + + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + goto EXIT; + } + Mpeg2CodecStart(pOMXComponent, INPUT_PORT_INDEX); + if (pMpeg2Dec->bSourceStart == OMX_FALSE) { + pMpeg2Dec->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pMpeg2Dec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + if ((pMpeg2Dec->bDestinationStart == OMX_FALSE) && + (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst == OMX_TRUE)) { + pMpeg2Dec->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pMpeg2Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pMpeg2Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] can't find a start code", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedFrame; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_SrcOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + if (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc == OMX_TRUE) { + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + else + pVideoBuffer = NULL; + } else { + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + pSrcOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == + pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]) { + pVideoDec->pMFCDecInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoDec->pMFCDecInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pExynosInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_DstIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) { + nAllocLen[i] = pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nAlignPlaneSize[i]; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] ADDR[%d]: 0x%x, size[%d]: %d", pExynosComponent, __FUNCTION__, + i, pDstInputData->buffer.addr[i], i, nAllocLen[i]); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + } + + goto EXIT; + } + + Mpeg2CodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_DstOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + ExynosVideoGeometry *bufferGeometry = NULL; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + ExynosVideoColorFormatType nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + OMX_COLOR_FORMATTYPE nOMXFormat = OMX_COLOR_FormatUnused; + OMX_U32 nPixelFormat = 0; + + FunctionIn(); + + if (pMpeg2Dec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + Exynos_OSAL_Memset(&videoBuffer, 0, sizeof(ExynosVideoBuffer)); + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO) at ExtensionDequeue", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + displayStatus = pVideoBuffer->displayStatus; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus: 0x%x", pExynosComponent, __FUNCTION__, displayStatus); + + if ((displayStatus == VIDEO_FRAME_STATUS_DISPLAY_DECODING) || + (displayStatus == VIDEO_FRAME_STATUS_DISPLAY_ONLY) || + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + (CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL)) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pOutputPort->exceptionFlag = NEED_PORT_FLUSH; + pVideoDec->bReconfigDPB = OMX_TRUE; + Mpeg2CodecUpdateResolution(pOMXComponent); + pVideoDec->csc_set_format = OMX_FALSE; + } + ret = OMX_ErrorNone; + goto EXIT; + } + + pMpeg2Dec->hMFCMpeg2Handle.outputIndexTimestamp++; + pMpeg2Dec->hMFCMpeg2Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->allocSize = pDstOutputData->dataLen = 0; + nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + nDataLen[plane] = pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->cropRect.nLeft = bufferGeometry->cropRect.nLeft; + pBufferInfo->cropRect.nTop = bufferGeometry->cropRect.nTop; + pBufferInfo->cropRect.nWidth = bufferGeometry->cropRect.nWidth; + pBufferInfo->cropRect.nHeight = bufferGeometry->cropRect.nHeight; + pBufferInfo->colorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + + /* calculate each plane info for the application */ + Exynos_OSAL_GetPlaneSize(pOutputPort->portDefinition.format.video.eColorFormat, + PLANE_SINGLE, pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + nDataLen, nAllocLen); + + pDstOutputData->allocSize = nAllocLen[0] + nAllocLen[1] + nAllocLen[2]; + pDstOutputData->dataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + /* update extra info */ + { + /* interlace */ + pMpeg2Dec->hMFCMpeg2Handle.interlacedType = pVideoBuffer->interlacedType; + + /* HDR */ + if (pVideoBuffer->frameType & VIDEO_FRAME_WITH_HDR_INFO) + Mpeg2CodecUpdateHdrInfo(pOMXComponent); + + /* SBWC Normal format */ + if (pVideoBuffer->frameType & VIDEO_FRAME_NEED_ACTUAL_FORMAT) { + nVideoFormat = pDecOps->Get_ActualFormat(hMFCHandle); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + nOMXFormat = Exynos_OSAL_Video2OMXFormat((int)nVideoFormat); + + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nPixelFormat = Exynos_OSAL_OMX2HALPixelFormat(nOMXFormat, pOutputPort->ePlaneType); + + if (nPixelFormat != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Normal format at SBWC is 0x%x", + pExynosComponent, __FUNCTION__, nPixelFormat); + pMpeg2Dec->hMFCMpeg2Handle.nActualFormat = nPixelFormat; + } + } + } + } + } + + /* update extra information to vendor path for renderer + * if BUFFER_COPY_FORCE is used, it will be updated at Exynos_CSC_OutputData() + */ + if ((pOutputPort->bufferProcessType == BUFFER_SHARE) && + (pVideoBuffer->planes[2].addr != NULL)) { + Mpeg2CodecUpdateExtraInfo(pOMXComponent, pVideoBuffer->planes[2].addr); + } + + indexTimestamp = pDecOps->Get_FrameTag(hMFCHandle); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if ((pExynosComponent->checkTimeStamp.needSetStartTimeStamp != OMX_TRUE) && + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp != OMX_TRUE)) { + if (indexTimestamp == INDEX_AFTER_EOS) { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } else { + pDstOutputData->timeStamp = pExynosComponent->timeStamp[pMpeg2Dec->hMFCMpeg2Handle.outputIndexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[pMpeg2Dec->hMFCMpeg2Handle.outputIndexTimestamp]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] missing out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + } + } else { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } + } else { + /* For timestamp correction. if mfc support frametype detect */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] disp_pic_frame_type: %d", pExynosComponent, __FUNCTION__, pVideoBuffer->frameType); + + /* NEED TIMESTAMP REORDER */ + if (pVideoDec->bDTSMode == OMX_TRUE) { + if ((pVideoBuffer->frameType & VIDEO_FRAME_I) || + ((pVideoBuffer->frameType & VIDEO_FRAME_OTHERS) && + ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) || + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE)) + pMpeg2Dec->hMFCMpeg2Handle.outputIndexTimestamp = indexTimestamp; + else + indexTimestamp = pMpeg2Dec->hMFCMpeg2Handle.outputIndexTimestamp; + } + + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp] | OMX_BUFFERFLAG_ENDOFFRAME; + + if (pVideoBuffer->frameType & VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + + if (pVideoBuffer->frameType & VIDEO_FRAME_WITH_BLACK_BAR) { + if (Mpeg2CodecUpdateBlackBarCrop(pOMXComponent) != OMX_ErrorNone) + goto EXIT; + } + + if (pVideoBuffer->frameType & VIDEO_FRAME_CONCEALMENT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + if (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) { + pDstOutputData->remainDataLen = 0; + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp != INDEX_AFTER_EOS) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] tag(%d) is wrong", pExynosComponent, __FUNCTION__, indexTimestamp); + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + goto EXIT; + } + + if ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) || + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->nFlags[indexTimestamp] &= (~OMX_BUFFERFLAG_EOS); + } + } else if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + pDstOutputData->remainDataLen = 0; + + if (pExynosComponent->bBehaviorEOS == OMX_TRUE) { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_srcInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + ret = Exynos_Mpeg2Dec_SrcIn(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorInputDataDecodeYet) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorCorruptedFrame)) { + + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pVideoDec->bDiscardCSDError == OMX_TRUE)) { + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_srcOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + if ((pMpeg2Dec->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosInputPort))) { + Exynos_OSAL_SignalWait(pMpeg2Dec->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pMpeg2Dec->hSourceStartEvent); + } + + ret = Exynos_Mpeg2Dec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_dstInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + if (pExynosComponent->currentState == OMX_StatePause) + ret = (OMX_ERRORTYPE)OMX_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pMpeg2Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg2Dec->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pMpeg2Dec->hDestinationInStartEvent); + } + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pMpeg2Dec->bypassBufferInfoQ) > 0) { + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pMpeg2Dec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = Mpeg2CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Mpeg2CodecDstSetup(0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + Exynos_OSAL_SignalSet(pMpeg2Dec->hDestinationOutStartEvent); + } + } + + if (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_Mpeg2Dec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + if ((pMpeg2Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg2Dec_dstOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (((pMpeg2Dec->bDestinationStart == OMX_FALSE) || + (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst == OMX_FALSE)) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg2Dec->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pMpeg2Dec->hDestinationOutStartEvent); + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if (Exynos_OSAL_GetElemNum(&pMpeg2Dec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pMpeg2Dec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_Mpeg2Dec_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && + (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MPEG2_DEC, componentName) != 0) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = HW_VIDEO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pMpeg2Dec = Exynos_OSAL_Malloc(sizeof(EXYNOS_MPEG2DEC_HANDLE)); + if (pMpeg2Dec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pMpeg2Dec, 0, sizeof(EXYNOS_MPEG2DEC_HANDLE)); + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoDec->hCodecHandle = (OMX_HANDLETYPE)pMpeg2Dec; + + Exynos_OSAL_Strcpy(pExynosComponent->componentName, componentName); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pExynosPort->portDefinition.nBufferSize = CUSTOM_LIMITED_DRM_INPUT_BUFFER_SIZE; + else +#endif + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + } + + pVideoDec->nMinInBufSize = DEFAULT_VIDEO_MIN_INPUT_BUFFER_SIZE; /* for DRC */ + + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/mpeg2"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + //pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pMpeg2Dec->Mpeg2Component[i], OMX_VIDEO_PARAM_MPEG2TYPE); + pMpeg2Dec->Mpeg2Component[i].nPortIndex = i; + pMpeg2Dec->Mpeg2Component[i].eProfile = OMX_VIDEO_MPEG2ProfileMain; + pMpeg2Dec->Mpeg2Component[i].eLevel = OMX_VIDEO_MPEG2LevelML; /* Check again**** */ + } + + pOMXComponent->GetParameter = &Exynos_Mpeg2Dec_GetParameter; + pOMXComponent->SetParameter = &Exynos_Mpeg2Dec_SetParameter; + pOMXComponent->GetConfig = &Exynos_Mpeg2Dec_GetConfig; + pOMXComponent->SetConfig = &Exynos_Mpeg2Dec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_Mpeg2Dec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_Mpeg2Dec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_Mpeg2Dec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_Mpeg2Dec_Terminate; + + pVideoDec->exynos_codec_srcInputProcess = &Exynos_Mpeg2Dec_srcInputBufferProcess; + pVideoDec->exynos_codec_srcOutputProcess = &Exynos_Mpeg2Dec_srcOutputBufferProcess; + pVideoDec->exynos_codec_dstInputProcess = &Exynos_Mpeg2Dec_dstInputBufferProcess; + pVideoDec->exynos_codec_dstOutputProcess = &Exynos_Mpeg2Dec_dstOutputBufferProcess; + + pVideoDec->exynos_codec_start = &Mpeg2CodecStart; + pVideoDec->exynos_codec_stop = &Mpeg2CodecStop; + pVideoDec->exynos_codec_bufferProcessRun = &Mpeg2CodecOutputBufferProcessRun; + pVideoDec->exynos_codec_enqueueAllBuffer = &Mpeg2CodecEnQueueAllBuffer; + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &Mpeg2CodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &Mpeg2CodecCheckResolution; + + pVideoDec->exynos_codec_updateExtraInfo = &Mpeg2CodecUpdateExtraInfo; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pMpeg2Dec); + pMpeg2Dec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.eCodecType = VIDEO_CODING_MPEG2; + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + if (Exynos_Video_GetInstInfo(&(pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo), VIDEO_TRUE /* dec */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pMpeg2Dec); + pMpeg2Dec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport == VIDEO_TRUE) + pVideoDec->bDrvDPBManaging = OMX_TRUE; + else + pVideoDec->hRefHandle = Exynos_OSAL_RefCount_Create(); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec DrvDPBManaging(%d)", pExynosComponent, __FUNCTION__, + (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport)); + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-dec-compressed-color-format", (OMX_INDEXTYPE)OMX_IndexParamVideoCompressedColorFormat); +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit( + OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoDec->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg2Dec != NULL) { + Exynos_OSAL_Free(pMpeg2Dec); + pMpeg2Dec = pVideoDec->hCodecHandle = NULL; + } + + ret = Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.h b/openmax/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.h new file mode 100644 index 0000000..54f8a89 --- /dev/null +++ b/openmax/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.h @@ -0,0 +1,97 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Mpeg2dec.h + * @brief + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @version 2.0.0 + * @history + * 2012.07.10 : Create + */ + +#ifndef EXYNOS_OMX_MPEG2_DEC_COMPONENT +#define EXYNOS_OMX_MPEG2_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" +#include "ExynosVideoApi.h" + + +typedef struct _EXYNOS_MFC_MPEG2DEC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + OMX_S32 maxDPBNum; + + /* extra info which will be shared with renderer */ + int interlacedType; + ExynosVideoHdrInfo sHdrInfo; + OMX_U32 nActualFormat; + + ExynosVideoColorFormatType MFCOutputColorType; + ExynosVideoDecOps *pDecOps; + ExynosVideoDecBufferOps *pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 2 + OMX_VIDEO_MPEG2PROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_MPEG2LEVELTYPE maxLevel; +} EXYNOS_MFC_MPEG2DEC_HANDLE; + +typedef struct _EXYNOS_MPEG2DEC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_MPEG2TYPE Mpeg2Component[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + + /* EXYNOS MFC Codec specific */ + EXYNOS_MFC_MPEG2DEC_HANDLE hMFCMpeg2Handle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_MPEG2DEC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName); +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit( + OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Mpeg2CodecDstSetup( + OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/mpeg2/NOTICE b/openmax/component/video/dec/mpeg2/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/dec/mpeg2/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/dec/mpeg2/library_register.c b/openmax/component/video/dec/mpeg2/library_register.c new file mode 100644 index 0000000..65faff5 --- /dev/null +++ b/openmax/component/video/dec/mpeg2/library_register.c @@ -0,0 +1,59 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @version 2.0.0 + * @history + * 2012.07.10 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_MPEG2_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register( + ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - video decoder MPEG2 */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_MPEG2_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_MPEG2_DEC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/openmax/component/video/dec/mpeg2/library_register.h b/openmax/component/video/dec/mpeg2/library_register.h new file mode 100644 index 0000000..99d4d4b --- /dev/null +++ b/openmax/component/video/dec/mpeg2/library_register.h @@ -0,0 +1,59 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @version 2.0.0 + * @history + * 2012.07.10 : Create + */ + +#ifndef EXYNOS_OMX_MPEG2_DEC_REG +#define EXYNOS_OMX_MPEG2_DEC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 1 +#define MAX_COMPONENT_ROLE_NUM 1 + +#ifndef USE_CUSTOM_COMPONENT_SUPPORT +#define EXYNOS_OMX_COMPONENT_MPEG2_DEC "OMX.Exynos.MPEG2.Decoder" +#else +#define EXYNOS_OMX_COMPONENT_MPEG2_DEC "OMX.Exynos.mpeg2.dec" +#endif + +#define EXYNOS_OMX_COMPONENT_MPEG2_DEC_ROLE "video_decoder.mpeg2" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register( + ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/mpeg4/Android.mk b/openmax/component/video/dec/mpeg4/Android.mk new file mode 100644 index 0000000..4e37fb4 --- /dev/null +++ b/openmax/component/video/dec/mpeg4/Android.mk @@ -0,0 +1,87 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Mpeg4dec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.MPEG4.Decoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/dec \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_SMALL_SECURE_MEMORY), true) +LOCAL_CFLAGS += -DUSE_SMALL_SECURE_MEMORY +endif + +ifeq ($(BOARD_USE_COMPRESSED_COLOR), true) +LOCAL_CFLAGS += -DUSE_COMPRESSED_COLOR +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.c b/openmax/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.c new file mode 100644 index 0000000..7b464bf --- /dev/null +++ b/openmax/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.c @@ -0,0 +1,3643 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Mpeg4dec.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Vdec.h" +#include "Exynos_OMX_VdecControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Mpeg4dec.h" +#include "ExynosVideoApi.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" + +#include "Exynos_OSAL_Platform.h" + +#include "VendorVideoAPI.h" + +/* To use CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */ +/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_MPEG4_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg4Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pMpeg4Dec->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) { + pMpeg4Dec->hMFCMpeg4Handle.profiles[nProfileCnt++] = (int)OMX_VIDEO_MPEG4ProfileSimple; + pMpeg4Dec->hMFCMpeg4Handle.profiles[nProfileCnt++] = (int)OMX_VIDEO_MPEG4ProfileAdvancedSimple; + pMpeg4Dec->hMFCMpeg4Handle.nProfileCnt = nProfileCnt; + pMpeg4Dec->hMFCMpeg4Handle.maxLevel = (int)OMX_VIDEO_MPEG4Level5; + } else { + pMpeg4Dec->hMFCMpeg4Handle.profiles[nProfileCnt++] = (int)OMX_VIDEO_H263ProfileBaseline; + pMpeg4Dec->hMFCMpeg4Handle.profiles[nProfileCnt++] = (int)OMX_VIDEO_H263ProfileH320Coding; + pMpeg4Dec->hMFCMpeg4Handle.profiles[nProfileCnt++] = (int)OMX_VIDEO_H263ProfileBackwardCompatible; + pMpeg4Dec->hMFCMpeg4Handle.profiles[nProfileCnt++] = (int)OMX_VIDEO_H263ProfileISWV2; + pMpeg4Dec->hMFCMpeg4Handle.nProfileCnt = nProfileCnt; + pMpeg4Dec->hMFCMpeg4Handle.maxLevel = (int)OMX_VIDEO_H263Level70; + } + +EXIT: + + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + int nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg4Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pMpeg4Dec->hMFCMpeg4Handle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pMpeg4Dec->hMFCMpeg4Handle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pMpeg4Dec->hMFCMpeg4Handle.maxLevel; +#else + while ((pMpeg4Dec->hMFCMpeg4Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pMpeg4Dec->hMFCMpeg4Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pMpeg4Dec->hMFCMpeg4Handle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pMpeg4Dec->hMFCMpeg4Handle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg4Dec == NULL) + goto EXIT; + + while ((pMpeg4Dec->hMFCMpeg4Handle.maxLevel >> nLevelCnt++) > 0); + + if ((pMpeg4Dec->hMFCMpeg4Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pMpeg4Dec->hMFCMpeg4Handle.nProfileCnt; i++) { + if (pMpeg4Dec->hMFCMpeg4Handle.profiles[i] == (int)pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + FunctionOut(); + + return (bProfileSupport && bLevelSupport); +} + +static OMX_ERRORTYPE GetCodecOutputPrivateData(OMX_PTR codecBuffer, OMX_PTR addr[], OMX_U32 size[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pCodecBuffer = NULL; + + if (codecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pCodecBuffer = (ExynosVideoBuffer *)codecBuffer; + + if (addr != NULL) { + addr[0] = pCodecBuffer->planes[0].addr; + addr[1] = pCodecBuffer->planes[1].addr; + addr[2] = pCodecBuffer->planes[2].addr; + } + + if (size != NULL) { + size[0] = pCodecBuffer->planes[0].allocSize; + size[1] = pCodecBuffer->planes[1].allocSize; + size[2] = pCodecBuffer->planes[2].allocSize; + } + +EXIT: + return ret; +} + +static OMX_BOOL gbFIMV1 = OMX_FALSE; + +static OMX_BOOL Check_Stream_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize, + CODEC_TYPE codecType) +{ + OMX_BOOL ret = OMX_FALSE; + + FunctionIn(); + + switch (codecType) { + case CODEC_TYPE_MPEG4: + if (gbFIMV1) { + ret = OMX_TRUE; + goto EXIT; + } else { + if (streamSize < 3) { + ret = OMX_FALSE; + goto EXIT; + } else if ((pInputStream[0] == 0x00) && + (pInputStream[1] == 0x00) && + (pInputStream[2] == 0x01)) { + ret = OMX_TRUE; + } else { + ret = OMX_FALSE; + goto EXIT; + } + } + break; + case CODEC_TYPE_H263: + if (streamSize > 0) { + unsigned startCode = 0xFFFFFFFF; + unsigned pTypeMask = 0x03; + unsigned pType = 0; + OMX_U32 len = 0; + int readStream; + /* Check PSC(Picture Start Code) : 0000 0000 0000 0000 1000 00 */ + while (((startCode << 8 >> 10) != 0x20) || (pType != 0x02)) { + readStream = *(pInputStream + len); + startCode = (startCode << 8) | readStream; + + readStream = *(pInputStream + len + 1); + pType = readStream & pTypeMask; + + len++; + if (len > 0x3) + break; + } + + if (len > 0x3) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] Picture Start Code Missing", __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } else { + ret = OMX_TRUE; + } + } else { + ret = OMX_FALSE; + goto EXIT; + } + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: undefined codec type (%d)", __FUNCTION__, codecType); + ret = OMX_FALSE; + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg4Dec == NULL) + goto EXIT; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pOutputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecOpen(EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec, ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pMpeg4Dec == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pDecOps = (ExynosVideoDecOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecOps)); + pInbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + pOutbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + + if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pMpeg4Dec->hMFCMpeg4Handle.pDecOps = pDecOps; + pMpeg4Dec->hMFCMpeg4Handle.pInbufOps = pInbufOps; + pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pDecOps->nSize = sizeof(ExynosVideoDecOps); + pInbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + + if (Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for decoder ops */ + if ((pDecOps->Init == NULL) || (pDecOps->Finalize == NULL) || + (pDecOps->Get_ActualBufferCount == NULL) || + (pDecOps->Set_FrameTag == NULL) || (pDecOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.pDecOps->Init(pVideoInstInfo); + if (pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pMpeg4Dec->hMFCMpeg4Handle.pDecOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pMpeg4Dec->hMFCMpeg4Handle.pInbufOps = NULL; + } + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecClose(EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pMpeg4Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + + if (hMFCHandle != NULL) { + pDecOps->Finalize(hMFCHandle); + pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle = NULL; + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc = OMX_FALSE; + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Decoder(pDecOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pMpeg4Dec->hMFCMpeg4Handle.pInbufOps = NULL; + } + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pMpeg4Dec->hMFCMpeg4Handle.pDecOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecStart(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg4Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc == OMX_TRUE)) { + pInbufOps->Run(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_TRUE)) { + pOutbufOps->Run(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecStop(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg4Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) { + pInbufOps->Stop(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) { + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pOutbufOps->Stop(hMFCHandle); + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) + pOutbufOps->Clear_RegisteredBuffer(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecOutputBufferProcessRun(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg4Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pMpeg4Dec->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pMpeg4Dec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pMpeg4Dec->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pMpeg4Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pMpeg4Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_FALSE) { + Exynos_OSAL_SignalSet(pMpeg4Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecReconfigAllBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + ExynosVideoDecBufferOps *pBufferOps = NULL; + + FunctionIn(); + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pMpeg4Dec->bSourceStart == OMX_TRUE)) { + ret = OMX_ErrorNotImplemented; + goto EXIT; + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pMpeg4Dec->bDestinationStart == OMX_TRUE)) { + pBufferOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + + if (pExynosPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /**********************************/ + /* Codec Buffer Free & Unregister */ + /**********************************/ + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_FALSE; + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = Mpeg4CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to MPEG4CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType == BUFFER_SHARE) { + /***************************/ + /* Codec Buffer Unregister */ + /***************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_FALSE; + } + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecEnQueueAllBuffer(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + + ExynosVideoDecBufferOps *pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + + int i; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecInputBuffer[i]->fd[0], pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecOutputBuffer[i]->fd[0], pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecUpdateExtraInfo( + OMX_COMPONENTTYPE *pOMXComponent, + ExynosVideoMeta *pMeta) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + + if (pMeta == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMeta->eType = VIDEO_INFO_TYPE_INVALID; + + /* interlace */ + { + if (pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] interlace type = %x", + pExynosComponent, __FUNCTION__, pMpeg4Dec->hMFCMpeg4Handle.interlacedType); + pMeta->eType |= VIDEO_INFO_TYPE_INTERLACED; + pMeta->data.dec.nInterlacedType = pMpeg4Dec->hMFCMpeg4Handle.interlacedType; + } + } + + /* Normal format for SBWC black bar */ + { + if (pMpeg4Dec->hMFCMpeg4Handle.nActualFormat != 0) { + pMeta->nPixelFormat = pMpeg4Dec->hMFCMpeg4Handle.nActualFormat; + pMeta->eType |= VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT; + + pMpeg4Dec->hMFCMpeg4Handle.nActualFormat = 0; + } else { + pMeta->nPixelFormat = 0; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecUpdateBlackBarCrop(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + OMX_CONFIG_RECTTYPE *pBlackBarCropRect = &pVideoDec->blackBarCropRect; + + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + ExynosVideoRect CropRect; + + FunctionIn(); + + Exynos_OSAL_Memset(&CropRect, 0, sizeof(ExynosVideoRect)); + if (pOutbufOps->Get_BlackBarCrop(hMFCHandle, &CropRect) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get crop info", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + + pBlackBarCropRect->nLeft = CropRect.nLeft; + pBlackBarCropRect->nTop = CropRect.nTop; + pBlackBarCropRect->nWidth = CropRect.nWidth; + pBlackBarCropRect->nHeight = CropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Black Bar Info: LEFT(%d) TOP(%d) WIDTH(%d) HEIGHT(%d)", + pExynosComponent, __FUNCTION__, + pBlackBarCropRect->nLeft, pBlackBarCropRect->nTop, + pBlackBarCropRect->nWidth, pBlackBarCropRect->nHeight); + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + (OMX_INDEXTYPE)OMX_IndexConfigBlackBarCrop, + NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecCheckResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_EXCEPTION_STATE eOutputExcepState = pOutputPort->exceptionFlag; + + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + + OMX_CONFIG_RECTTYPE *pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = &(pInputPort->portDefinition); + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = &(pOutputPort->portDefinition); + + int maxDPBNum = 0; + + FunctionIn(); + + /* get geometry */ + Exynos_OSAL_Memset(&codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to get geometry"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + maxDPBNum += EXTRA_DPB_NUM; + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + } + + /* resolution is changed */ + if ((codecOutbufConf.nFrameWidth != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth) || + (codecOutbufConf.nFrameHeight != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight) || + (codecOutbufConf.nStride != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nStride) || +#if 0 // TODO: check posibility + (codecOutbufConf.eColorFormat != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eColorFormat) || + (codecOutbufConf.eFilledDataType != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eFilledDataType) || +#endif + (maxDPBNum != pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] DPB(%d), FORMAT(0x%x), TYPE(0x%x) -> DPB(%d), FORMAT(0x%x), TYPE(0x%x)", + pExynosComponent, __FUNCTION__, + pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eColorFormat, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eFilledDataType, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType); + + pInputPortDefinition->format.video.nFrameWidth = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = codecOutbufConf.nFrameHeight; + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = maxDPBNum; + pOutputPortDefinition->nBufferCountMin = maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* crop info of contents is changed */ + if ((codecOutbufConf.cropRect.nTop != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nTop) || + (codecOutbufConf.cropRect.nLeft != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nLeft) || + (codecOutbufConf.cropRect.nWidth != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nWidth) || + (codecOutbufConf.cropRect.nHeight != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nHeight)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nWidth, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nHeight, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + Exynos_OSAL_Memcpy(&pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf, &codecOutbufConf, sizeof(codecOutbufConf)); + pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum = maxDPBNum; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + + OMX_CONFIG_RECTTYPE *pCropRectangle = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = NULL; + + OMX_BOOL bFormatChanged = OMX_FALSE; + + FunctionIn(); + + /* get geometry for output */ + Exynos_OSAL_Memset(&pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum += EXTRA_DPB_NUM; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] maxDPBNum: %d", pExynosComponent, __FUNCTION__, pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum); + + /* get interlace info */ + if (pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] contents is interlaced type", pExynosComponent, __FUNCTION__); + + pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] past info: width(%d) height(%d)", + pExynosComponent, __FUNCTION__, + pInputPortDefinition->format.video.nFrameWidth, + pInputPortDefinition->format.video.nFrameHeight); + + /* output format is changed internally (8bit <> 10bit) */ + if (pMpeg4Dec->hMFCMpeg4Handle.MFCOutputColorType != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eColorFormat) { + OMX_COLOR_FORMATTYPE eOutputFormat = Exynos_OSAL_Video2OMXFormat(pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eColorFormat); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] The format(%x) is changed to %x by H/W Codec", + pExynosComponent, __FUNCTION__, + pMpeg4Dec->hMFCMpeg4Handle.MFCOutputColorType, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eColorFormat); + + pMpeg4Dec->hMFCMpeg4Handle.MFCOutputColorType = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eColorFormat; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pOutputPort->ePlaneType)); + + bFormatChanged = OMX_TRUE; + + if (!(pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eFilledDataType & DATA_TYPE_8BIT_SBWC)) { + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* SBWC to non SBWC : must update eColorFormat */ + pOutputPort->portDefinition.format.video.eColorFormat = eOutputFormat; + } + + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } else { + pVideoDec->nCompColorFormat = eOutputFormat; + } + } + + switch (pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eFilledDataType) { + case DATA_8BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_8BIT_SBWC; + break; + case DATA_10BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_10BIT_SBWC; + break; + default: + pVideoDec->eDataType = DATA_TYPE_8BIT; + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] resolution info: width(%d / %d), height(%d / %d)", + pExynosComponent, __FUNCTION__, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nWidth, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nHeight); + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nHeight; + } + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight; +#if 0 + /* don't need to change */ + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; +#endif + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } else if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPortDefinition->nBufferCountActual != pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum) || + ((OMX_S32)pOutputPortDefinition->nBufferCountMin < pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight; + + pOutputPortDefinition->nBufferCountActual = pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* contents has crop info */ + if ((pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nWidth) || + (pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nHeight)) { + + if ((pOutputPort->bufferProcessType & BUFFER_COPY) && + (pExynosComponent->bUseImgCrop == OMX_TRUE)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + } + + pInputPortDefinition->format.video.nFrameWidth = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged) with crop", + pExynosComponent, __FUNCTION__); + + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecHeaderDecoding(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecBufferOps *pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + + FunctionIn(); + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + nAllocLen[0] = pSrcInputData->allocSize; + } + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enqueue input buffer for header parsing", pExynosComponent, __FUNCTION__); +// ret = OMX_ErrorInsufficientResources; + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* start header parsing */ + if (pInbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run input buffer for header parsing", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* get geometry for output */ + Exynos_OSAL_Memset(&pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedHeader; + + if ((pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", pExynosComponent, __FUNCTION__, + *((OMX_U8 *)pSrcInputData->buffer.addr[0]) , *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 1), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 2), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 3), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 4), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 5), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 6), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 7)); + } + + pInbufOps->Stop(hMFCHandle); + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecSrcSetup(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 allocFrameSize = 0; + OMX_COLOR_FORMATTYPE eOutputFormat = pExynosOutputPort->portDefinition.format.video.eColorFormat; + + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + + FunctionIn(); + + if ((pSrcInputData->dataLen <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pMpeg4Dec->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pMpeg4Dec->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SignalSet(pMpeg4Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pVideoDec->bThumbnailMode == OMX_TRUE) + pDecOps->Set_IFrameDecoding(hMFCHandle); + + if ((pDecOps->Enable_DTSMode != NULL) && + (pVideoDec->bDTSMode == OMX_TRUE)) + pDecOps->Enable_DTSMode(hMFCHandle); + + if (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.supportInfo.dec.bPrioritySupport == VIDEO_TRUE) + pDecOps->Set_Priority(hMFCHandle, pVideoDec->nPriority); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + if (pMpeg4Dec->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) + bufferConf.eCompressionFormat = VIDEO_CODING_MPEG4; + else + bufferConf.eCompressionFormat = VIDEO_CODING_H263; + + pInbufOps->Set_Shareable(hMFCHandle); + + allocFrameSize = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + allocFrameSize = pSrcInputData->allocSize; + } + + bufferConf.nSizeImage = allocFrameSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + nInBufferCnt = MAX_INPUTBUFFER_NUM_DYNAMIC; + + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + +#ifdef USE_COMPRESSED_COLOR + if ((pExynosOutputPort->eMetaDataType != METADATA_TYPE_GRAPHIC) || + (pExynosOutputPort->bForceUseNonCompFormat == OMX_TRUE)) { + /* use SBWC format only ANB scenario */ + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } +#endif + + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* For SBWC format setting */ + bSupportFormat = CheckFormatHWSupport(pExynosComponent, pVideoDec->nCompColorFormat); + if (bSupportFormat == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] set compressed color format(0x%x)", + pExynosComponent, __FUNCTION__, (OMX_U32)pVideoDec->nCompColorFormat); + + eOutputFormat = pVideoDec->nCompColorFormat; + } + } + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] omx format(0x%x) is %s by h/w", + pExynosComponent, __FUNCTION__, eOutputFormat, + (bSupportFormat == OMX_TRUE)? "supported":"not supported"); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eOutputFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pExynosOutputPort->ePlaneType)); + } else { + OMX_COLOR_FORMATTYPE eCheckFormat = OMX_SEC_COLOR_FormatNV12Tiled; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + if (bSupportFormat != OMX_TRUE) { + eCheckFormat = OMX_COLOR_FormatYUV420SemiPlanar; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + } + if (bSupportFormat == OMX_TRUE) { /* supported by CSC(NV12T/NV12 -> format) */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eCheckFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eCheckFormat, pExynosOutputPort->ePlaneType)); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not support this format (0x%x)", pExynosComponent, __FUNCTION__, eOutputFormat); + ret = OMX_ErrorNotImplemented; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + } + + pMpeg4Dec->hMFCMpeg4Handle.MFCOutputColorType = bufferConf.eColorFormat; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output video format is 0x%x", + pExynosComponent, __FUNCTION__, bufferConf.eColorFormat); + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + ret = Mpeg4CodecHeaderDecoding(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc = OMX_TRUE; + + Mpeg4CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + ret = Mpeg4CodecUpdateResolution(pOMXComponent); + if (ret != OMX_ErrorNone) { + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc = OMX_FALSE; + Mpeg4CodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] first frame will be re-pushed to input", pExynosComponent, __FUNCTION__); + + Mpeg4CodecStop(pOMXComponent, INPUT_PORT_INDEX); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nOutbufs, nPlaneCnt; + + FunctionIn(); + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nAlignPlaneSize[i]; + + Mpeg4CodecStop(pOMXComponent, OUTPUT_PORT_INDEX); + + /* for adaptive playback */ + if (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enable Dynamic DPB", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if ((IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) && + (pMpeg4Dec->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4)) + pDecOps->Enable_PackedPB(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* get dpb count */ + nOutbufs = pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_TRUE; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->eMetaDataType == METADATA_TYPE_DISABLED) { + /*************/ + /* TBD */ + /*************/ + /* data buffer : user buffer + * H/W can't accept user buffer directly + */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_TRUE; + } + + if (Mpeg4CodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoMpeg4: + { + OMX_VIDEO_PARAM_MPEG4TYPE *pDstMpeg4Param = (OMX_VIDEO_PARAM_MPEG4TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG4TYPE *pSrcMpeg4Param = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstMpeg4Param, sizeof(OMX_VIDEO_PARAM_MPEG4TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstMpeg4Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcMpeg4Param = &pMpeg4Dec->mpeg4Component[pDstMpeg4Param->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstMpeg4Param) + nOffset, + ((char *)pSrcMpeg4Param) + nOffset, + sizeof(OMX_VIDEO_PARAM_MPEG4TYPE) - nOffset); + } + break; + case OMX_IndexParamVideoH263: + { + OMX_VIDEO_PARAM_H263TYPE *pDstH263Param = (OMX_VIDEO_PARAM_H263TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_H263TYPE *pSrcH263Param = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstH263Param, sizeof(OMX_VIDEO_PARAM_H263TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstH263Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcH263Param = &pMpeg4Dec->h263Component[pDstH263Param->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstH263Param) + nOffset, + ((char *)pSrcH263Param) + nOffset, + sizeof(OMX_VIDEO_PARAM_H263TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_S32 codecType; + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + codecType = pMpeg4Dec->hMFCMpeg4Handle.codecType; + if (codecType == CODEC_TYPE_MPEG4) + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_MPEG4_DEC_ROLE); + else + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H263_DEC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG4TYPE *pSrcMpeg4Param = NULL; + OMX_VIDEO_PARAM_H263TYPE *pSrcH263Param = NULL; + OMX_S32 codecType; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + codecType = pMpeg4Dec->hMFCMpeg4Handle.codecType; + if (codecType == CODEC_TYPE_MPEG4) { + pSrcMpeg4Param = &pMpeg4Dec->mpeg4Component[pDstProfileLevel->nPortIndex]; + pDstProfileLevel->eProfile = pSrcMpeg4Param->eProfile; + pDstProfileLevel->eLevel = pSrcMpeg4Param->eLevel; + } else { + pSrcH263Param = &pMpeg4Dec->h263Component[pDstProfileLevel->nPortIndex]; + pDstProfileLevel->eProfile = pSrcH263Param->eProfile; + pDstProfileLevel->eLevel = pSrcH263Param->eLevel; + } + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pMpeg4Dec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexExynosParamReorderMode: + { + EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *pReorderParam = (EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pReorderParam, sizeof(EXYNOS_OMX_VIDEO_PARAM_REORDERMODE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pReorderParam->bReorderMode = pVideoDec->bReorderMode; + } + break; + default: + ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoMpeg4: + { + OMX_VIDEO_PARAM_MPEG4TYPE *pDstMpeg4Param = NULL; + OMX_VIDEO_PARAM_MPEG4TYPE *pSrcMpeg4Param = (OMX_VIDEO_PARAM_MPEG4TYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcMpeg4Param, sizeof(OMX_VIDEO_PARAM_MPEG4TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcMpeg4Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstMpeg4Param = &pMpeg4Dec->mpeg4Component[pSrcMpeg4Param->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstMpeg4Param) + nOffset, + ((char *)pSrcMpeg4Param) + nOffset, + sizeof(OMX_VIDEO_PARAM_MPEG4TYPE) - nOffset); + } + break; + case OMX_IndexParamVideoH263: + { + OMX_VIDEO_PARAM_H263TYPE *pDstH263Param = NULL; + OMX_VIDEO_PARAM_H263TYPE *pSrcH263Param = (OMX_VIDEO_PARAM_H263TYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcH263Param, sizeof(OMX_VIDEO_PARAM_H263TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcH263Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstH263Param = &pMpeg4Dec->h263Component[pSrcH263Param->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstH263Param) + nOffset, + ((char *)pSrcH263Param) + nOffset, + sizeof(OMX_VIDEO_PARAM_H263TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_MPEG4_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4; + } else if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H263_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingH263; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG4TYPE *pDstMpeg4Param = NULL; + OMX_VIDEO_PARAM_H263TYPE *pDstH263Param = NULL; + OMX_S32 codecType; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + codecType = pMpeg4Dec->hMFCMpeg4Handle.codecType; + if (codecType == CODEC_TYPE_MPEG4) { + /* + * To do: Check validity of profile & level parameters + */ + + pDstMpeg4Param = &pMpeg4Dec->mpeg4Component[pSrcProfileLevel->nPortIndex]; + pDstMpeg4Param->eProfile = pSrcProfileLevel->eProfile; + pDstMpeg4Param->eLevel = pSrcProfileLevel->eLevel; + } else { + /* + * To do: Check validity of profile & level parameters + */ + + pDstH263Param = &pMpeg4Dec->h263Component[pSrcProfileLevel->nPortIndex]; + pDstH263Param->eProfile = pSrcProfileLevel->eProfile; + pDstH263Param->eLevel = pSrcProfileLevel->eLevel; + } + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pMpeg4Dec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexExynosParamReorderMode: + { + EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *pReorderParam = (EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pReorderParam, sizeof(EXYNOS_OMX_VIDEO_PARAM_REORDERMODE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoDec->bReorderMode = pReorderParam->bReorderMode; + } + break; + default: + ret = Exynos_OMX_VideoDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_GetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch (nIndex) { + case OMX_IndexConfigCommonOutputCrop: + { + if (pExynosComponent->bUseImgCrop == OMX_TRUE) { + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + } else { + /* query crop information on bitstream */ + OMX_CONFIG_RECTTYPE *pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + + if (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + goto EXIT; + } + + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pSrcRectType = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + } + break; + default: + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_SetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + + switch (nIndex) { + default: + ret = Exynos_OMX_VideoDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_REORDER_MODE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamReorderMode; + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = Exynos_OMX_VideoDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_ComponentRoleEnum( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_U8 *cRole, + OMX_IN OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 codecType; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex != (MAX_COMPONENT_ROLE_NUM - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + codecType = ((EXYNOS_MPEG4DEC_HANDLE *)(((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle))->hMFCMpeg4Handle.codecType; + if (codecType == CODEC_TYPE_MPEG4) + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_MPEG4_DEC_ROLE); + else + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_H263_DEC_ROLE); + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_Mpeg4Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + + ExynosVideoInstInfo *pVideoInstInfo = &(pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i; + + FunctionIn(); + + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc = OMX_FALSE; + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pExynosInputPort->portDefinition.format.video.nFrameWidth, + pExynosInputPort->portDefinition.format.video.nFrameHeight, + pExynosInputPort->portDefinition.format.video.nBitrate, + pExynosInputPort->portDefinition.format.video.xFramerate); + + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pExynosInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pExynosInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pExynosInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pExynosInputPort->portDefinition.format.video.xFramerate; + + /* Mpeg4 Codec Open */ + ret = Mpeg4CodecOpen(pMpeg4Dec, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + nAllocLen[0] = ALIGN(pExynosInputPort->portDefinition.format.video.nFrameWidth * + pExynosInputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + if (nAllocLen[0] < pVideoDec->nMinInBufSize) + nAllocLen[0] = pVideoDec->nMinInBufSize; + + Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX, MFC_INPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_SetPlaneToPort(pExynosOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SemaphoreCreate(&pExynosOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pMpeg4Dec->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pMpeg4Dec->hSourceStartEvent); + pMpeg4Dec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pMpeg4Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pMpeg4Dec->hDestinationOutStartEvent); + + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp = 0; + pMpeg4Dec->hMFCMpeg4Handle.outputIndexTimestamp = 0; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pMpeg4Dec->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) { + pVideoDec->csc_handle = csc_init(CSC_METHOD_HW); + csc_set_hw_property(pVideoDec->csc_handle, CSC_HW_PROPERTY_FIXED_NODE, 2); + csc_set_hw_property(pVideoDec->csc_handle, CSC_HW_PROPERTY_MODE_DRM, 1); + } else { + pVideoDec->csc_handle = csc_init(csc_method); + } + + if (pVideoDec->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pVideoDec->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_Mpeg4Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoDec != NULL) { + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + if (pMpeg4Dec != NULL) { + Exynos_OSAL_QueueTerminate(&pMpeg4Dec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pMpeg4Dec->hDestinationInStartEvent); + pMpeg4Dec->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pMpeg4Dec->hDestinationOutStartEvent); + pMpeg4Dec->hDestinationOutStartEvent = NULL; + pMpeg4Dec->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pMpeg4Dec->hSourceStartEvent); + pMpeg4Dec->hSourceStartEvent = NULL; + pMpeg4Dec->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pMpeg4Dec != NULL) { + Mpeg4CodecClose(pMpeg4Dec); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_SrcIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_BOOL bInStartCode = OMX_FALSE; + + FunctionIn(); + + if (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = Mpeg4CodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (pMpeg4Dec->bDestinationStart == OMX_FALSE) && + (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_FALSE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = Mpeg4CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to MPEG4CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + } + + if (((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) || + ((bInStartCode = Check_Stream_StartCode(pSrcInputData->buffer.addr[0], oneFrameSize, pMpeg4Dec->hMFCMpeg4Handle.codecType)) == OMX_TRUE)) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + + if (pVideoDec->bReorderMode == OMX_FALSE) { + /* next slot will be used like as circular queue */ + pExynosComponent->timeStamp[pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->nFlags[pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp] = pSrcInputData->nFlags; + } else { /* MSRND */ + Exynos_SetReorderTimestamp(pExynosComponent, &(pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp), pSrcInputData->timeStamp, pSrcInputData->nFlags); + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), dataLen(%d), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, oneFrameSize, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp); + + pDecOps->Set_FrameTag(hMFCHandle, pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp); + pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp++; + pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp %= MAX_TIMESTAMP; + + if (pVideoDec->bQosChanged == OMX_TRUE) { + if (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.supportInfo.dec.bOperatingRateSupport == VIDEO_TRUE) { + if (pDecOps->Set_OperatingRate != NULL) + pDecOps->Set_OperatingRate(hMFCHandle, pVideoDec->nOperatingRate); + } else if (pDecOps->Set_QosRatio != NULL) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + } + + pVideoDec->bQosChanged = OMX_FALSE; + } + + if (pVideoDec->bSearchBlackBarChanged == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] BlackBar searching mode : %s", + pExynosComponent, __FUNCTION__, + (pVideoDec->bSearchBlackBar == OMX_TRUE) ? "enable" : "disable"); + pDecOps->Set_SearchBlackBar(hMFCHandle, (ExynosVideoBoolType)pVideoDec->bSearchBlackBar); + pVideoDec->bSearchBlackBarChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + pPrivate = (void *)pSrcInputData->bufferHeader; + } else { + nAllocLen[0] = pSrcInputData->allocSize; + + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + goto EXIT; + } + Mpeg4CodecStart(pOMXComponent, INPUT_PORT_INDEX); + if (pMpeg4Dec->bSourceStart == OMX_FALSE) { + pMpeg4Dec->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pMpeg4Dec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + if ((pMpeg4Dec->bDestinationStart == OMX_FALSE) && + (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_TRUE)) { + pMpeg4Dec->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pMpeg4Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pMpeg4Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] can't find a start code", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedFrame; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_SrcOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + if (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc == OMX_TRUE) { + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + else + pVideoBuffer = NULL; + } else { + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + pSrcOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == + pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]) { + pVideoDec->pMFCDecInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoDec->pMFCDecInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pExynosInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_DstIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) { + nAllocLen[i] = pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nAlignPlaneSize[i]; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] ADDR[%d]: 0x%x, size[%d]: %d", pExynosComponent, __FUNCTION__, + i, pDstInputData->buffer.addr[i], i, nAllocLen[i]); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + } + + goto EXIT; + } + + Mpeg4CodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_DstOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + ExynosVideoGeometry *bufferGeometry = NULL; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + ExynosVideoColorFormatType nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + OMX_COLOR_FORMATTYPE nOMXFormat = OMX_COLOR_FormatUnused; + OMX_U32 nPixelFormat = 0; + + FunctionIn(); + + if (pMpeg4Dec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + Exynos_OSAL_Memset(&videoBuffer, 0, sizeof(ExynosVideoBuffer)); + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO) at ExtensionDequeue", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + displayStatus = pVideoBuffer->displayStatus; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus: 0x%x", pExynosComponent, __FUNCTION__, displayStatus); + + if ((displayStatus == VIDEO_FRAME_STATUS_DISPLAY_DECODING) || + (displayStatus == VIDEO_FRAME_STATUS_DISPLAY_ONLY) || + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + (CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL)) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pOutputPort->exceptionFlag = NEED_PORT_FLUSH; + pVideoDec->bReconfigDPB = OMX_TRUE; + Mpeg4CodecUpdateResolution(pOMXComponent); + pVideoDec->csc_set_format = OMX_FALSE; + } + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pMpeg4Dec->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) { + pMpeg4Dec->hMFCMpeg4Handle.outputIndexTimestamp++; + pMpeg4Dec->hMFCMpeg4Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + } + + pDstOutputData->allocSize = pDstOutputData->dataLen = 0; + nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + nDataLen[plane] = pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->cropRect.nLeft = bufferGeometry->cropRect.nLeft; + pBufferInfo->cropRect.nTop = bufferGeometry->cropRect.nTop; + pBufferInfo->cropRect.nWidth = bufferGeometry->cropRect.nWidth; + pBufferInfo->cropRect.nHeight = bufferGeometry->cropRect.nHeight; + pBufferInfo->colorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + + /* calculate each plane info for the application */ + Exynos_OSAL_GetPlaneSize(pOutputPort->portDefinition.format.video.eColorFormat, + PLANE_SINGLE, pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + nDataLen, nAllocLen); + + pDstOutputData->allocSize = nAllocLen[0] + nAllocLen[1] + nAllocLen[2]; + pDstOutputData->dataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + /* update extra info */ + { + /* interlace */ + pMpeg4Dec->hMFCMpeg4Handle.interlacedType = pVideoBuffer->interlacedType; + + /* SBWC Normal format */ + if (pVideoBuffer->frameType & VIDEO_FRAME_NEED_ACTUAL_FORMAT) { + nVideoFormat = pDecOps->Get_ActualFormat(hMFCHandle); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + nOMXFormat = Exynos_OSAL_Video2OMXFormat((int)nVideoFormat); + + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nPixelFormat = Exynos_OSAL_OMX2HALPixelFormat(nOMXFormat, pOutputPort->ePlaneType); + + if (nPixelFormat != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Normal format at SBWC is 0x%x", + pExynosComponent, __FUNCTION__, nPixelFormat); + pMpeg4Dec->hMFCMpeg4Handle.nActualFormat = nPixelFormat; + } + } + } + } + } + + /* update extra information to vendor path for renderer + * if BUFFER_COPY_FORCE is used, it will be updated at Exynos_CSC_OutputData() + */ + if ((pOutputPort->bufferProcessType == BUFFER_SHARE) && + (pVideoBuffer->planes[2].addr != NULL)) { + Mpeg4CodecUpdateExtraInfo(pOMXComponent, pVideoBuffer->planes[2].addr); + } + + indexTimestamp = pDecOps->Get_FrameTag(hMFCHandle); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + + if (pVideoDec->bReorderMode == OMX_FALSE) { + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if ((pExynosComponent->checkTimeStamp.needSetStartTimeStamp != OMX_TRUE) && + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp != OMX_TRUE)) { + if (indexTimestamp == INDEX_AFTER_EOS) { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } else { + pDstOutputData->timeStamp = pExynosComponent->timeStamp[pMpeg4Dec->hMFCMpeg4Handle.outputIndexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[pMpeg4Dec->hMFCMpeg4Handle.outputIndexTimestamp]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] missing out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + } + } else { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } + } else { + /* For timestamp correction. if mfc support frametype detect */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] disp_pic_frame_type: %d", pExynosComponent, __FUNCTION__, pVideoBuffer->frameType); + + /* NEED TIMESTAMP REORDER */ + if (pVideoDec->bDTSMode == OMX_TRUE) { + if ((pVideoBuffer->frameType & VIDEO_FRAME_I) || + ((pVideoBuffer->frameType & VIDEO_FRAME_OTHERS) && + ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) || + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE)) + pMpeg4Dec->hMFCMpeg4Handle.outputIndexTimestamp = indexTimestamp; + else + indexTimestamp = pMpeg4Dec->hMFCMpeg4Handle.outputIndexTimestamp; + } + + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp] | OMX_BUFFERFLAG_ENDOFFRAME; + + if (pVideoBuffer->frameType & VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + } else { /* MSRND */ + EXYNOS_OMX_CURRENT_FRAME_TIMESTAMP sCurrentTimestamp; + + Exynos_GetReorderTimestamp(pExynosComponent, &sCurrentTimestamp, indexTimestamp, pVideoBuffer->frameType); + + pDstOutputData->timeStamp = sCurrentTimestamp.timeStamp; + pDstOutputData->nFlags = sCurrentTimestamp.nFlags | OMX_BUFFERFLAG_ENDOFFRAME; + + pExynosComponent->nFlags[sCurrentTimestamp.nIndex] = 0x00; + pExynosComponent->bTimestampSlotUsed[sCurrentTimestamp.nIndex] = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), reordered tag: %d, original tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + sCurrentTimestamp.nIndex, + indexTimestamp); + } + + if (pMpeg4Dec->hMFCMpeg4Handle.codecType == CODEC_TYPE_H263) { + pMpeg4Dec->hMFCMpeg4Handle.outputIndexTimestamp++; + pMpeg4Dec->hMFCMpeg4Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + } + + if (pVideoBuffer->frameType & VIDEO_FRAME_WITH_BLACK_BAR) { + if (Mpeg4CodecUpdateBlackBarCrop(pOMXComponent) != OMX_ErrorNone) + goto EXIT; + } + + if (pVideoBuffer->frameType & VIDEO_FRAME_CONCEALMENT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + if (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) { + pDstOutputData->remainDataLen = 0; + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp != INDEX_AFTER_EOS) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] tag(%d) is wrong", pExynosComponent, __FUNCTION__, indexTimestamp); + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + goto EXIT; + } + + if ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) || + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->nFlags[indexTimestamp] &= (~OMX_BUFFERFLAG_EOS); + } + } else if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + pDstOutputData->remainDataLen = 0; + + if (pExynosComponent->bBehaviorEOS == OMX_TRUE) { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_srcInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + ret = Exynos_Mpeg4Dec_SrcIn(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorInputDataDecodeYet) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorCorruptedFrame)) { + + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pVideoDec->bDiscardCSDError == OMX_TRUE)) { + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_srcOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + if ((pMpeg4Dec->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosInputPort))) { + Exynos_OSAL_SignalWait(pMpeg4Dec->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pMpeg4Dec->hSourceStartEvent); + } + + ret = Exynos_Mpeg4Dec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_dstInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + if (pExynosComponent->currentState == OMX_StatePause) + ret = (OMX_ERRORTYPE)OMX_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pMpeg4Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg4Dec->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pMpeg4Dec->hDestinationInStartEvent); + } + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pMpeg4Dec->bypassBufferInfoQ) > 0) { + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pMpeg4Dec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = Mpeg4CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to MPEG4CodecDstSetup(0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + Exynos_OSAL_SignalSet(pMpeg4Dec->hDestinationOutStartEvent); + } + } + + if (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_Mpeg4Dec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + if ((pMpeg4Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Dec_dstOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (((pMpeg4Dec->bDestinationStart == OMX_FALSE) || + (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_FALSE)) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg4Dec->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pMpeg4Dec->hDestinationOutStartEvent); + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if (Exynos_OSAL_GetElemNum(&pMpeg4Dec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pMpeg4Dec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_Mpeg4Dec_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && + (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + OMX_BOOL bSecureMode = OMX_FALSE; + int i = 0; + OMX_S32 codecType = -1; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MPEG4_DEC, componentName) == 0) { + codecType = CODEC_TYPE_MPEG4; + bSecureMode = OMX_FALSE; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H263_DEC, componentName) == 0) { + codecType = CODEC_TYPE_H263; + bSecureMode = OMX_FALSE; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MPEG4_DRM_DEC, componentName) == 0) { + codecType = CODEC_TYPE_MPEG4; + bSecureMode = OMX_TRUE; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = (bSecureMode == OMX_TRUE)? HW_VIDEO_DEC_SECURE_CODEC:HW_VIDEO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pMpeg4Dec = Exynos_OSAL_Malloc(sizeof(EXYNOS_MPEG4DEC_HANDLE)); + if (pMpeg4Dec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pMpeg4Dec, 0, sizeof(EXYNOS_MPEG4DEC_HANDLE)); + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoDec->hCodecHandle = (OMX_HANDLETYPE)pMpeg4Dec; + pMpeg4Dec->hMFCMpeg4Handle.codecType = codecType; + Exynos_OSAL_Strcpy(pExynosComponent->componentName, componentName); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pExynosPort->portDefinition.nBufferSize = CUSTOM_LIMITED_DRM_INPUT_BUFFER_SIZE; + else +#endif + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + } + + pVideoDec->nMinInBufSize = DEFAULT_VIDEO_MIN_INPUT_BUFFER_SIZE; /* for DRC */ + + if (codecType == CODEC_TYPE_MPEG4) { + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/mpeg4"); + } else { + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingH263; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/h263"); + } + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + +#ifdef USE_SINGLE_PLANE_IN_DRM + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pExynosPort->ePlaneType = PLANE_SINGLE; +#endif + + if (codecType == CODEC_TYPE_MPEG4) { + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pMpeg4Dec->mpeg4Component[i], OMX_VIDEO_PARAM_MPEG4TYPE); + pMpeg4Dec->mpeg4Component[i].nPortIndex = i; + pMpeg4Dec->mpeg4Component[i].eProfile = OMX_VIDEO_MPEG4ProfileSimple; + pMpeg4Dec->mpeg4Component[i].eLevel = OMX_VIDEO_MPEG4Level3; + } + } else { + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pMpeg4Dec->h263Component[i], OMX_VIDEO_PARAM_H263TYPE); + pMpeg4Dec->h263Component[i].nPortIndex = i; + pMpeg4Dec->h263Component[i].eProfile = OMX_VIDEO_H263ProfileBaseline | OMX_VIDEO_H263ProfileISWV2; + pMpeg4Dec->h263Component[i].eLevel = OMX_VIDEO_H263Level45; + } + } + + pOMXComponent->GetParameter = &Exynos_Mpeg4Dec_GetParameter; + pOMXComponent->SetParameter = &Exynos_Mpeg4Dec_SetParameter; + pOMXComponent->GetConfig = &Exynos_Mpeg4Dec_GetConfig; + pOMXComponent->SetConfig = &Exynos_Mpeg4Dec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_Mpeg4Dec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_Mpeg4Dec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_Mpeg4Dec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_Mpeg4Dec_Terminate; + + pVideoDec->exynos_codec_srcInputProcess = &Exynos_Mpeg4Dec_srcInputBufferProcess; + pVideoDec->exynos_codec_srcOutputProcess = &Exynos_Mpeg4Dec_srcOutputBufferProcess; + pVideoDec->exynos_codec_dstInputProcess = &Exynos_Mpeg4Dec_dstInputBufferProcess; + pVideoDec->exynos_codec_dstOutputProcess = &Exynos_Mpeg4Dec_dstOutputBufferProcess; + + pVideoDec->exynos_codec_start = &Mpeg4CodecStart; + pVideoDec->exynos_codec_stop = &Mpeg4CodecStop; + pVideoDec->exynos_codec_bufferProcessRun = &Mpeg4CodecOutputBufferProcessRun; + pVideoDec->exynos_codec_enqueueAllBuffer = &Mpeg4CodecEnQueueAllBuffer; + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &Mpeg4CodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &Mpeg4CodecCheckResolution; + + pVideoDec->exynos_codec_updateExtraInfo = &Mpeg4CodecUpdateExtraInfo; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pMpeg4Dec); + pMpeg4Dec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pMpeg4Dec->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) + pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.eCodecType = VIDEO_CODING_MPEG4; + else + pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.eCodecType = VIDEO_CODING_H263; + + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + if (Exynos_Video_GetInstInfo(&(pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo), VIDEO_TRUE /* dec */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pMpeg4Dec); + pMpeg4Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + pMpeg4Dec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport == VIDEO_TRUE) + pVideoDec->bDrvDPBManaging = OMX_TRUE; + else + pVideoDec->hRefHandle = Exynos_OSAL_RefCount_Create(); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec DrvDPBManaging(%d)", pExynosComponent, __FUNCTION__, + (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport)); + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-dec-compressed-color-format", (OMX_INDEXTYPE)OMX_IndexParamVideoCompressedColorFormat); +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoDec->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pMpeg4Dec != NULL) { + Exynos_OSAL_Free(pMpeg4Dec); + pMpeg4Dec = pVideoDec->hCodecHandle = NULL; + } + + ret = Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.h b/openmax/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.h new file mode 100644 index 0000000..1761fc4 --- /dev/null +++ b/openmax/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.h @@ -0,0 +1,123 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Mpeg4dec.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_MPEG4_DEC_COMPONENT +#define EXYNOS_OMX_MPEG4_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" +#include "ExynosVideoApi.h" + + +typedef enum _CODEC_TYPE +{ + CODEC_TYPE_H263, + CODEC_TYPE_MPEG4 +} CODEC_TYPE; + +/* + * This structure is the same as BitmapInfoHhr struct in pv_avifile_typedefs.h file + */ +typedef struct _BitmapInfoHhr +{ + OMX_U32 BiSize; + OMX_U32 BiWidth; + OMX_U32 BiHeight; + OMX_U16 BiPlanes; + OMX_U16 BiBitCount; + OMX_U32 BiCompression; + OMX_U32 BiSizeImage; + OMX_U32 BiXPelsPerMeter; + OMX_U32 BiYPelsPerMeter; + OMX_U32 BiClrUsed; + OMX_U32 BiClrImportant; +} BitmapInfoHhr; + +typedef struct _EXYNOS_MFC_MPEG4DEC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + OMX_S32 maxDPBNum; + CODEC_TYPE codecType; + + /* extra info which will be shared with renderer */ + int interlacedType; + OMX_U32 nActualFormat; + + ExynosVideoColorFormatType MFCOutputColorType; + ExynosVideoDecOps *pDecOps; + ExynosVideoDecBufferOps *pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 4 + OMX_S32 profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_S32 maxLevel; +} EXYNOS_MFC_MPEG4DEC_HANDLE; + +typedef struct _EXYNOS_MPEG4DEC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_H263TYPE h263Component[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_MPEG4TYPE mpeg4Component[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + + /* EXYNOS MFC Codec specific */ + EXYNOS_MFC_MPEG4DEC_HANDLE hMFCMpeg4Handle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_MPEG4DEC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName); +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit( + OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Mpeg4CodecDstSetup( + OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/mpeg4/NOTICE b/openmax/component/video/dec/mpeg4/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/dec/mpeg4/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/dec/mpeg4/library_register.c b/openmax/component/video/dec/mpeg4/library_register.c new file mode 100644 index 0000000..e55c680 --- /dev/null +++ b/openmax/component/video/dec/mpeg4/library_register.c @@ -0,0 +1,69 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_MPEG4_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register( + ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - video decoder MPEG4 */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_MPEG4_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_MPEG4_DEC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 2 - video decoder MPEG4 for DRM*/ + Exynos_OSAL_Strcpy(ppExynosComponent[1]->componentName, EXYNOS_OMX_COMPONENT_MPEG4_DRM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[1]->roles[0], EXYNOS_OMX_COMPONENT_MPEG4_DEC_ROLE); + ppExynosComponent[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 3 - video decoder H.263 */ + Exynos_OSAL_Strcpy(ppExynosComponent[2]->componentName, EXYNOS_OMX_COMPONENT_H263_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[2]->roles[0], EXYNOS_OMX_COMPONENT_H263_DEC_ROLE); + ppExynosComponent[2]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/openmax/component/video/dec/mpeg4/library_register.h b/openmax/component/video/dec/mpeg4/library_register.h new file mode 100644 index 0000000..ed95a44 --- /dev/null +++ b/openmax/component/video/dec/mpeg4/library_register.h @@ -0,0 +1,72 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_MPEG4_DEC_REG +#define EXYNOS_OMX_MPEG4_DEC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 3 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* MPEG4 */ +#ifndef USE_CUSTOM_COMPONENT_SUPPORT +#define EXYNOS_OMX_COMPONENT_MPEG4_DEC "OMX.Exynos.MPEG4.Decoder" +#define EXYNOS_OMX_COMPONENT_MPEG4_DRM_DEC "OMX.Exynos.MPEG4.Decoder.secure" +#else +#define EXYNOS_OMX_COMPONENT_MPEG4_DEC "OMX.Exynos.mpeg4.dec" +#define EXYNOS_OMX_COMPONENT_MPEG4_DRM_DEC "OMX.Exynos.mpeg4.dec.secure" +#endif + +#define EXYNOS_OMX_COMPONENT_MPEG4_DEC_ROLE "video_decoder.mpeg4" + + +/* H.263 */ +#ifndef USE_CUSTOM_COMPONENT_SUPPORT +#define EXYNOS_OMX_COMPONENT_H263_DEC "OMX.Exynos.H263.Decoder" +#else +#define EXYNOS_OMX_COMPONENT_H263_DEC "OMX.Exynos.h263.dec" +#endif + +#define EXYNOS_OMX_COMPONENT_H263_DEC_ROLE "video_decoder.h263" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register( + ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/vc1/Android.mk b/openmax/component/video/dec/vc1/Android.mk new file mode 100644 index 0000000..5a884a2 --- /dev/null +++ b/openmax/component/video/dec/vc1/Android.mk @@ -0,0 +1,87 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Wmvdec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.WMV.Decoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/dec \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_SMALL_SECURE_MEMORY), true) +LOCAL_CFLAGS += -DUSE_SMALL_SECURE_MEMORY +endif + +ifeq ($(BOARD_USE_COMPRESSED_COLOR), true) +LOCAL_CFLAGS += -DUSE_COMPRESSED_COLOR +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/dec/vc1/Exynos_OMX_Wmvdec.c b/openmax/component/video/dec/vc1/Exynos_OMX_Wmvdec.c new file mode 100644 index 0000000..a50b00c --- /dev/null +++ b/openmax/component/video/dec/vc1/Exynos_OMX_Wmvdec.c @@ -0,0 +1,3646 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Wmvdec.c + * @brief + * @author HyeYeon Chung (hyeon.chung@samsung.com) + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @version 2.0.0 + * @history + * 2012.07.10 : Create + * : Support WMV3 (Vc-1 Simple/Main Profile) + * : Support WMvC1 (Vc-1 Advanced Profile) + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Vdec.h" +#include "Exynos_OMX_VdecControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Wmvdec.h" +#include "ExynosVideoApi.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" + +#include "Exynos_OSAL_Platform.h" + +#include "VendorVideoAPI.h" + +/* To use CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */ +/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_WMV_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +#define SL_META_LEN 36 /* sequence layer metadata length in bytes */ + +/* Enable or disable "WMV3_ADDITIONAL_START_CODE" based on MFC F/W's need */ +//#define WMV3_ADDITIONAL_START_CODE + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pWmvDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pWmvDec->hMFCWmvHandle.profiles[nProfileCnt] = OMX_VIDEO_VC1ProfileSimple; + pWmvDec->hMFCWmvHandle.maxLevel[nProfileCnt++] = OMX_VIDEO_VC1LevelMedium; + + pWmvDec->hMFCWmvHandle.profiles[nProfileCnt] = OMX_VIDEO_VC1ProfileMain; + pWmvDec->hMFCWmvHandle.maxLevel[nProfileCnt++] = OMX_VIDEO_VC1LevelHigh; + + pWmvDec->hMFCWmvHandle.profiles[nProfileCnt] = OMX_VIDEO_VC1ProfileAdvanced; + pWmvDec->hMFCWmvHandle.maxLevel[nProfileCnt++] = OMX_VIDEO_VC1Level4; + + pWmvDec->hMFCWmvHandle.nProfileCnt = nProfileCnt; + +EXIT: + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + OMX_U32 nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pWmvDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + for (i = 0; i < pWmvDec->hMFCWmvHandle.nProfileCnt; i++) + nMaxIndex += pWmvDec->hMFCWmvHandle.maxLevel[i]; + + if ((pWmvDec->hMFCWmvHandle.nProfileCnt == 0) || + (nMaxIndex == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + for (i = 0; i < pWmvDec->hMFCWmvHandle.nProfileCnt; i++) { + if (pProfileLevelType->nProfileIndex < (nLevelCnt + pWmvDec->hMFCWmvHandle.maxLevel[i])) { + pProfileLevelType->eProfile = pWmvDec->hMFCWmvHandle.profiles[i]; + pProfileLevelType->eLevel = (OMX_U32)(pProfileLevelType->nProfileIndex - nLevelCnt); + break; + } + + nLevelCnt += pWmvDec->hMFCWmvHandle.maxLevel[i]; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pWmvDec == NULL) + goto EXIT; + + if (pWmvDec->hMFCWmvHandle.nProfileCnt == 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pWmvDec->hMFCWmvHandle.nProfileCnt; i++) { + if ((pWmvDec->hMFCWmvHandle.profiles[i] == pProfileLevelType->eProfile) && + (pWmvDec->hMFCWmvHandle.maxLevel[i] >= pProfileLevelType->eLevel)) { + ret = OMX_TRUE; + break; + } + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (ret == OMX_TRUE)? "":"not "); +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE GetCodecOutputPrivateData(OMX_PTR codecBuffer, OMX_PTR addr[], OMX_U32 size[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pCodecBuffer = NULL; + + if (codecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pCodecBuffer = (ExynosVideoBuffer *)codecBuffer; + + if (addr != NULL) { + addr[0] = pCodecBuffer->planes[0].addr; + addr[1] = pCodecBuffer->planes[1].addr; + addr[2] = pCodecBuffer->planes[2].addr; + } + + if (size != NULL) { + size[0] = pCodecBuffer->planes[0].allocSize; + size[1] = pCodecBuffer->planes[1].allocSize; + size[2] = pCodecBuffer->planes[2].allocSize; + } + +EXIT: + return ret; +} + +static WMV_FORMAT getFormatType( + OMX_U8 *pInputStream) +{ + WMV_FORMAT ret = WMV_FORMAT_UNKNOWN; + OMX_BYTE pCheckBuffer = (OMX_BYTE)pInputStream; + + if (pInputStream == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] pInputStream is null", __FUNCTION__); + return ret; + } + + if ((pCheckBuffer[3] == 0xC5) && + (pCheckBuffer[4] == 0x04)) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%s] WMV_FORMAT_WMV3", __FUNCTION__); + ret = WMV_FORMAT_WMV3; + } else if (((pCheckBuffer[3] == 0x01) && + (pCheckBuffer[4] == 0x0F)) || + ((pCheckBuffer[2] == 0x01) && + (pCheckBuffer[3] == 0x0F))) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%s] WMV_FORMAT_VC1", __FUNCTION__); + ret = WMV_FORMAT_VC1; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] WMV_FORMAT_UNKNOWN", __FUNCTION__); + } + + return ret; +} + +static OMX_BOOL Check_Stream_PrefixCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize, + WMV_FORMAT wmvFormat) +{ + switch (wmvFormat) { + case WMV_FORMAT_WMV3: +#ifdef WMV3_ADDITIONAL_START_CODE + return OMX_FALSE; +#else + if (streamSize > 0) + return OMX_TRUE; + else + return OMX_FALSE; +#endif + break; + case WMV_FORMAT_VC1: + /* TODO : for comformanc test based on common buffer scheme w/o parser */ + if (streamSize < 3) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] streamSize is too small (%d)", __FUNCTION__, streamSize); + return OMX_FALSE; + } else if ((pInputStream[0] == 0x00) && + (pInputStream[1] == 0x00) && + (pInputStream[2] == 0x01)) { + return OMX_TRUE; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] Cannot find prefix", __FUNCTION__); + return OMX_FALSE; + } + break; + + default: + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] undefined wmvFormat (%d)", __FUNCTION__, wmvFormat); + return OMX_FALSE; + break; + } +} + +OMX_BOOL Make_Stream_MetaData( + OMX_U8 *pInputStream, + OMX_U32 *pStreamSize, + WMV_FORMAT wmvFormat) +{ + OMX_BOOL ret = OMX_FALSE; + OMX_BYTE pCurrBuf = pInputStream; + switch ((int)wmvFormat) { + case WMV_FORMAT_WMV3: + if ((*pStreamSize) >= SL_META_LEN) { + (*pStreamSize) = SL_META_LEN; + ret = OMX_TRUE; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] *pStreamSize is too small to contain metadata(%d)", __FUNCTION__, *pStreamSize); + ret = OMX_FALSE; + } + break; + case WMV_FORMAT_VC1: + if ((pInputStream[1] == 0x00) && + (pInputStream[2] == 0x00) && + (pInputStream[3] == 0x01) && + (pInputStream[4] == 0x0F)) { + Exynos_OSAL_Memmove(pCurrBuf, pInputStream + 1, (*pStreamSize) - 1); + (*pStreamSize) -= 1; + ret = OMX_TRUE; + } else if ((pInputStream[0] == 0x00) && + (pInputStream[1] == 0x00) && + (pInputStream[2] == 0x01) && + (pInputStream[3] == 0x0F) && + ((*pStreamSize) >= 1)) { + ret = OMX_TRUE; + } + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] It is not necessary to make bitstream metadata for wmvFormat (%d)", __FUNCTION__, (int)wmvFormat); + ret = OMX_FALSE; + break; + } + + return ret; +} + +static OMX_BOOL Make_Stream_StartCode( + OMX_U8 *pInputStream, + OMX_U32 *pStreamSize, + WMV_FORMAT wmvFormat) +{ + OMX_BOOL ret = OMX_FALSE; + OMX_U8 vc1StartCode[4] = {0x00, 0x00, 0x01, 0x0d}; + +#ifdef WMV3_ADDITIONAL_START_CODE + /* first 4 bytes : size of Frame, second 4 bytes : present Time stamp */ + OMX_U8 wmvStartCode[8] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}; +#endif + + switch ((int)wmvFormat) { + case WMV_FORMAT_WMV3: +#ifdef WMV3_ADDITIONAL_START_CODE + Exynos_OSAL_Memmove(pInputStream + 8, pInputStream, (*pStreamSize)); + Exynos_OSAL_Memcpy(pInputStream, wmvStartCode, 8); + (*pStreamSize) += 8; +#endif + ret = OMX_TRUE; + break; + case WMV_FORMAT_VC1: + /* Should find better way to shift data */ + Exynos_OSAL_Memmove(pInputStream + 4, pInputStream, (*pStreamSize)); + Exynos_OSAL_Memcpy(pInputStream, vc1StartCode, 4); + (*pStreamSize) += 4; + ret = OMX_TRUE; + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] undefined wmvFormat (%d)", __FUNCTION__, wmvFormat); + ret = OMX_FALSE; + break; + } + +EXIT: + return ret; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pWmvDec == NULL) + goto EXIT; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pOutputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pWmvDec->hMFCWmvHandle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pWmvDec->hMFCWmvHandle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE WmvCodecOpen(EXYNOS_WMVDEC_HANDLE *pWmvDec, ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pWmvDec == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pDecOps = (ExynosVideoDecOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecOps)); + pInbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + pOutbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + + if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pWmvDec->hMFCWmvHandle.pDecOps = pDecOps; + pWmvDec->hMFCWmvHandle.pInbufOps = pInbufOps; + pWmvDec->hMFCWmvHandle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pDecOps->nSize = sizeof(ExynosVideoDecOps); + pInbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + + if (Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for decoder ops */ + if ((pDecOps->Init == NULL) || (pDecOps->Finalize == NULL) || + (pDecOps->Get_ActualBufferCount == NULL) || + (pDecOps->Set_FrameTag == NULL) || (pDecOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pWmvDec->hMFCWmvHandle.hMFCHandle = pWmvDec->hMFCWmvHandle.pDecOps->Init(pVideoInstInfo); + if (pWmvDec->hMFCWmvHandle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pWmvDec->hMFCWmvHandle.pDecOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pWmvDec->hMFCWmvHandle.pInbufOps = NULL; + } + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pWmvDec->hMFCWmvHandle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WmvCodecClose(EXYNOS_WMVDEC_HANDLE *pWmvDec) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pWmvDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + + if (hMFCHandle != NULL) { + pDecOps->Finalize(hMFCHandle); + pWmvDec->hMFCWmvHandle.hMFCHandle = NULL; + pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc = OMX_FALSE; + pWmvDec->hMFCWmvHandle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Decoder(pDecOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pWmvDec->hMFCWmvHandle.pOutbufOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pWmvDec->hMFCWmvHandle.pInbufOps = NULL; + } + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pWmvDec->hMFCWmvHandle.pDecOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WmvCodecStart(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pWmvDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc == OMX_TRUE)) { + pInbufOps->Run(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pWmvDec->hMFCWmvHandle.bConfiguredMFCDst == OMX_TRUE)) { + pOutbufOps->Run(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WmvCodecStop(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pWmvDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) { + pInbufOps->Stop(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) { + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pOutbufOps->Stop(hMFCHandle); + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) + pOutbufOps->Clear_RegisteredBuffer(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WmvCodecOutputBufferProcessRun(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pWmvDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pWmvDec->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pWmvDec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pWmvDec->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pWmvDec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pWmvDec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pWmvDec->hMFCWmvHandle.bConfiguredMFCDst == OMX_FALSE) { + Exynos_OSAL_SignalSet(pWmvDec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WmvCodecReconfigAllBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + ExynosVideoDecBufferOps *pBufferOps = NULL; + + FunctionIn(); + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pWmvDec->bSourceStart == OMX_TRUE)) { + ret = OMX_ErrorNotImplemented; + goto EXIT; + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pWmvDec->bDestinationStart == OMX_TRUE)) { + pBufferOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + + if (pExynosPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /**********************************/ + /* Codec Buffer Free & Unregister */ + /**********************************/ + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pWmvDec->hMFCWmvHandle.bConfiguredMFCDst = OMX_FALSE; + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = WmvCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to WmvCodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType == BUFFER_SHARE) { + /***************************/ + /* Codec Buffer Unregister */ + /***************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pWmvDec->hMFCWmvHandle.bConfiguredMFCDst = OMX_FALSE; + } + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WmvCodecEnQueueAllBuffer(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + + ExynosVideoDecBufferOps *pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + + int i; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecInputBuffer[i]->fd[0], pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pWmvDec->hMFCWmvHandle.bConfiguredMFCDst == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pWmvDec->hMFCWmvHandle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecOutputBuffer[i]->fd[0], pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WmvCodecUpdateExtraInfo( + OMX_COMPONENTTYPE *pOMXComponent, + ExynosVideoMeta *pMeta) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + + if (pMeta == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMeta->eType = VIDEO_INFO_TYPE_INVALID; + + /* interlace */ + { + if (pWmvDec->hMFCWmvHandle.codecOutbufConf.bInterlaced == VIDEO_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] interlace type = %x", + pExynosComponent, __FUNCTION__, pWmvDec->hMFCWmvHandle.interlacedType); + pMeta->eType |= VIDEO_INFO_TYPE_INTERLACED; + pMeta->data.dec.nInterlacedType = pWmvDec->hMFCWmvHandle.interlacedType; + } + } + + /* Normal format for SBWC black bar */ + { + if (pWmvDec->hMFCWmvHandle.nActualFormat != 0) { + pMeta->nPixelFormat = pWmvDec->hMFCWmvHandle.nActualFormat; + pMeta->eType |= VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT; + + pWmvDec->hMFCWmvHandle.nActualFormat = 0; + } else { + pMeta->nPixelFormat = 0; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE WmvCodecUpdateBlackBarCrop(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + OMX_CONFIG_RECTTYPE *pBlackBarCropRect = &pVideoDec->blackBarCropRect; + + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + ExynosVideoRect CropRect; + + FunctionIn(); + + Exynos_OSAL_Memset(&CropRect, 0, sizeof(ExynosVideoRect)); + if (pOutbufOps->Get_BlackBarCrop(hMFCHandle, &CropRect) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get crop info", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + + pBlackBarCropRect->nLeft = CropRect.nLeft; + pBlackBarCropRect->nTop = CropRect.nTop; + pBlackBarCropRect->nWidth = CropRect.nWidth; + pBlackBarCropRect->nHeight = CropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Black Bar Info: LEFT(%d) TOP(%d) WIDTH(%d) HEIGHT(%d)", + pExynosComponent, __FUNCTION__, + pBlackBarCropRect->nLeft, pBlackBarCropRect->nTop, + pBlackBarCropRect->nWidth, pBlackBarCropRect->nHeight); + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + (OMX_INDEXTYPE)OMX_IndexConfigBlackBarCrop, + NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WmvCodecCheckResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_EXCEPTION_STATE eOutputExcepState = pOutputPort->exceptionFlag; + + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + + OMX_CONFIG_RECTTYPE *pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = &(pInputPort->portDefinition); + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = &(pOutputPort->portDefinition); + + int maxDPBNum = 0; + + FunctionIn(); + + /* get geometry */ + Exynos_OSAL_Memset(&codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to get geometry"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + maxDPBNum += EXTRA_DPB_NUM; + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + } + + /* resolution is changed */ + if ((codecOutbufConf.nFrameWidth != pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth) || + (codecOutbufConf.nFrameHeight != pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight) || + (codecOutbufConf.nStride != pWmvDec->hMFCWmvHandle.codecOutbufConf.nStride) || +#if 0 // TODO: check posibility + (codecOutbufConf.eColorFormat != pWmvDec->hMFCWmvHandle.codecOutbufConf.eColorFormat) || + (codecOutbufConf.eFilledDataType != pWmvDec->hMFCWmvHandle.codecOutbufConf.eFilledDataType) || +#endif + (maxDPBNum != pWmvDec->hMFCWmvHandle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth, + pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] DPB(%d), FORMAT(0x%x), TYPE(0x%x) -> DPB(%d), FORMAT(0x%x), TYPE(0x%x)", + pExynosComponent, __FUNCTION__, + pWmvDec->hMFCWmvHandle.maxDPBNum, + pWmvDec->hMFCWmvHandle.codecOutbufConf.eColorFormat, + pWmvDec->hMFCWmvHandle.codecOutbufConf.eFilledDataType, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType); + + pInputPortDefinition->format.video.nFrameWidth = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = codecOutbufConf.nFrameHeight; + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = maxDPBNum; + pOutputPortDefinition->nBufferCountMin = maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* crop info of contents is changed */ + if ((codecOutbufConf.cropRect.nTop != pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nTop) || + (codecOutbufConf.cropRect.nLeft != pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nLeft) || + (codecOutbufConf.cropRect.nWidth != pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nWidth) || + (codecOutbufConf.cropRect.nHeight != pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nHeight)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nWidth, + pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nHeight, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + Exynos_OSAL_Memcpy(&pWmvDec->hMFCWmvHandle.codecOutbufConf, &codecOutbufConf, sizeof(codecOutbufConf)); + pWmvDec->hMFCWmvHandle.maxDPBNum = maxDPBNum; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WmvCodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + + OMX_CONFIG_RECTTYPE *pCropRectangle = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = NULL; + + OMX_BOOL bFormatChanged = OMX_FALSE; + + FunctionIn(); + + /* get geometry for output */ + Exynos_OSAL_Memset(&pWmvDec->hMFCWmvHandle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pWmvDec->hMFCWmvHandle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + pWmvDec->hMFCWmvHandle.maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + pWmvDec->hMFCWmvHandle.maxDPBNum += EXTRA_DPB_NUM; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] maxDPBNum: %d", pExynosComponent, __FUNCTION__, pWmvDec->hMFCWmvHandle.maxDPBNum); + + /* get interlace info */ + if (pWmvDec->hMFCWmvHandle.codecOutbufConf.bInterlaced == VIDEO_TRUE) + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] contents is interlaced type", pExynosComponent, __FUNCTION__); + + pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] past info: width(%d) height(%d)", + pExynosComponent, __FUNCTION__, + pInputPortDefinition->format.video.nFrameWidth, + pInputPortDefinition->format.video.nFrameHeight); + + /* output format is changed internally (8bit <> 10bit) */ + if (pWmvDec->hMFCWmvHandle.MFCOutputColorType != pWmvDec->hMFCWmvHandle.codecOutbufConf.eColorFormat) { + OMX_COLOR_FORMATTYPE eOutputFormat = Exynos_OSAL_Video2OMXFormat(pWmvDec->hMFCWmvHandle.codecOutbufConf.eColorFormat); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] The format(%x) is changed to %x by H/W Codec", + pExynosComponent, __FUNCTION__, + pWmvDec->hMFCWmvHandle.MFCOutputColorType, + pWmvDec->hMFCWmvHandle.codecOutbufConf.eColorFormat); + + pWmvDec->hMFCWmvHandle.MFCOutputColorType = pWmvDec->hMFCWmvHandle.codecOutbufConf.eColorFormat; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pOutputPort->ePlaneType)); + + bFormatChanged = OMX_TRUE; + + if (!(pWmvDec->hMFCWmvHandle.codecOutbufConf.eFilledDataType & DATA_TYPE_8BIT_SBWC)) { + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* SBWC to non SBWC : must update eColorFormat */ + pOutputPort->portDefinition.format.video.eColorFormat = eOutputFormat; + } + + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } else { + pVideoDec->nCompColorFormat = eOutputFormat; + } + } + + switch (pWmvDec->hMFCWmvHandle.codecOutbufConf.eFilledDataType) { + case DATA_8BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_8BIT_SBWC; + break; + case DATA_10BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_10BIT_SBWC; + break; + default: + pVideoDec->eDataType = DATA_TYPE_8BIT; + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] resolution info: width(%d / %d), height(%d / %d)", + pExynosComponent, __FUNCTION__, + pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth, + pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nWidth, + pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight, + pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nHeight); + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nHeight; + } + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight; +#if 0 + /* don't need to change */ + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; +#endif + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } else if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPortDefinition->nBufferCountActual != pWmvDec->hMFCWmvHandle.maxDPBNum) || + ((OMX_S32)pOutputPortDefinition->nBufferCountMin < pWmvDec->hMFCWmvHandle.maxDPBNum)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight; + + pOutputPortDefinition->nBufferCountActual = pWmvDec->hMFCWmvHandle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pWmvDec->hMFCWmvHandle.maxDPBNum; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* contents has crop info */ + if ((pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth != pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nWidth) || + (pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight != pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nHeight)) { + + if ((pOutputPort->bufferProcessType & BUFFER_COPY) && + (pExynosComponent->bUseImgCrop == OMX_TRUE)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + } + + pInputPortDefinition->format.video.nFrameWidth = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged) with crop", + pExynosComponent, __FUNCTION__); + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WmvCodecHeaderDecoding(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + OMX_BOOL bMetaData = OMX_FALSE; + + ExynosVideoDecBufferOps *pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + + FunctionIn(); + + bMetaData = Make_Stream_MetaData(pSrcInputData->buffer.addr[0], &oneFrameSize, pWmvDec->hMFCWmvHandle.wmvFormat); + if (bMetaData == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Fail to Make Stream MetaData", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedHeader; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + nDataLen[0] = oneFrameSize; + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + nAllocLen[0] = pSrcInputData->allocSize; + } + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enqueue input buffer for header parsing", pExynosComponent, __FUNCTION__); +// ret = OMX_ErrorInsufficientResources; + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* start header parsing */ + if (pInbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run input buffer for header parsing", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* get geometry for output */ + Exynos_OSAL_Memset(&pWmvDec->hMFCWmvHandle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pWmvDec->hMFCWmvHandle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedHeader; + + if ((pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", pExynosComponent, __FUNCTION__, + *((OMX_U8 *)pSrcInputData->buffer.addr[0]) , *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 1), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 2), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 3), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 4), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 5), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 6), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 7)); + } + + pInbufOps->Stop(hMFCHandle); + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} +OMX_ERRORTYPE WmvCodecSrcSetup(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 allocFrameSize = 0; + OMX_COLOR_FORMATTYPE eOutputFormat = pExynosOutputPort->portDefinition.format.video.eColorFormat; + + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + + FunctionIn(); + + if ((pSrcInputData->dataLen <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pWmvDec->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pWmvDec->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SignalSet(pWmvDec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pVideoDec->bThumbnailMode == OMX_TRUE) + pDecOps->Set_IFrameDecoding(hMFCHandle); + + if ((pDecOps->Enable_DTSMode != NULL) && + (pVideoDec->bDTSMode == OMX_TRUE)) + pDecOps->Enable_DTSMode(hMFCHandle); + + if (pWmvDec->hMFCWmvHandle.videoInstInfo.supportInfo.dec.bPrioritySupport == VIDEO_TRUE) + pDecOps->Set_Priority(hMFCHandle, pVideoDec->nPriority); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + if (pSrcInputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG) + pWmvDec->hMFCWmvHandle.wmvFormat = getFormatType(pSrcInputData->buffer.addr[0]); + + if (pWmvDec->hMFCWmvHandle.wmvFormat == WMV_FORMAT_WMV3) { + bufferConf.eCompressionFormat = VIDEO_CODING_VC1_RCV; + } else if (pWmvDec->hMFCWmvHandle.wmvFormat == WMV_FORMAT_VC1) { + bufferConf.eCompressionFormat = VIDEO_CODING_VC1; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Unsupported WMV Codec Format Type", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pInbufOps->Set_Shareable(hMFCHandle); + + allocFrameSize = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + allocFrameSize = pSrcInputData->allocSize; + } + + bufferConf.nSizeImage = allocFrameSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + nInBufferCnt = MAX_INPUTBUFFER_NUM_DYNAMIC; + + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + +#ifdef USE_COMPRESSED_COLOR + if ((pExynosOutputPort->eMetaDataType != METADATA_TYPE_GRAPHIC) || + (pExynosOutputPort->bForceUseNonCompFormat == OMX_TRUE)) { + /* use SBWC format only ANB scenario */ + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } +#endif + + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* For SBWC format setting */ + bSupportFormat = CheckFormatHWSupport(pExynosComponent, pVideoDec->nCompColorFormat); + if (bSupportFormat == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] set compressed color format(0x%x)", + pExynosComponent, __FUNCTION__, (OMX_U32)pVideoDec->nCompColorFormat); + + eOutputFormat = pVideoDec->nCompColorFormat; + } + } + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] omx format(0x%x) is %s by h/w", + pExynosComponent, __FUNCTION__, eOutputFormat, + (bSupportFormat == OMX_TRUE)? "supported":"not supported"); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eOutputFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pExynosOutputPort->ePlaneType)); + } else { + OMX_COLOR_FORMATTYPE eCheckFormat = OMX_SEC_COLOR_FormatNV12Tiled; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + if (bSupportFormat != OMX_TRUE) { + eCheckFormat = OMX_COLOR_FormatYUV420SemiPlanar; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + } + if (bSupportFormat == OMX_TRUE) { /* supported by CSC(NV12T/NV12 -> format) */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eCheckFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eCheckFormat, pExynosOutputPort->ePlaneType)); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not support this format (0x%x)", eOutputFormat); + ret = OMX_ErrorNotImplemented; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + } + + pWmvDec->hMFCWmvHandle.MFCOutputColorType = bufferConf.eColorFormat; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output video format is 0x%x", + pExynosComponent, __FUNCTION__, bufferConf.eColorFormat); + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + ret = WmvCodecHeaderDecoding(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc = OMX_TRUE; + + WmvCodecStart(pOMXComponent, INPUT_PORT_INDEX); + + ret = WmvCodecUpdateResolution(pOMXComponent); + if (ret != OMX_ErrorNone) { + pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc = OMX_TRUE; + WmvCodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + /* disable header info re-input scheme + ret = OMX_ErrorInputDataDecodeYet; + WmvCodecStop(pOMXComponent, INPUT_PORT_INDEX); + */ + ret = (OMX_ERRORTYPE)OMX_ErrorNoneSrcSetupFinish; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WmvCodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nOutbufs, nPlaneCnt; + + FunctionIn(); + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = pWmvDec->hMFCWmvHandle.codecOutbufConf.nAlignPlaneSize[i]; + + WmvCodecStop(pOMXComponent, OUTPUT_PORT_INDEX); + + /* for adaptive playback */ + if (pWmvDec->hMFCWmvHandle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enable Dynamic DPB", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* get dpb count */ + nOutbufs = pWmvDec->hMFCWmvHandle.maxDPBNum; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* without Register output buffer */ + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + + pWmvDec->hMFCWmvHandle.bConfiguredMFCDst = OMX_TRUE; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->eMetaDataType == METADATA_TYPE_DISABLED) { + /*************/ + /* TBD */ + /*************/ + /* data buffer : user buffer + * H/W can't accept user buffer directly + */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pWmvDec->hMFCWmvHandle.bConfiguredMFCDst = OMX_TRUE; + } + + if (WmvCodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoWmv: + { + OMX_VIDEO_PARAM_WMVTYPE *pDstWmvParam = (OMX_VIDEO_PARAM_WMVTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_WMVTYPE *pSrcWmvParam = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstWmvParam, sizeof(OMX_VIDEO_PARAM_WMVTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstWmvParam->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcWmvParam = &pWmvDec->WmvComponent[pDstWmvParam->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstWmvParam) + nOffset, + ((char *)pSrcWmvParam) + nOffset, + sizeof(OMX_VIDEO_PARAM_WMVTYPE) - nOffset); + } + break; + case OMX_IndexParamVideoVC1: + { + OMX_VIDEO_PARAM_VC1TYPE *pDstVc1Param = (OMX_VIDEO_PARAM_VC1TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VC1TYPE *pSrcVc1Param = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstVc1Param, sizeof(OMX_VIDEO_PARAM_VC1TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstVc1Param->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVc1Param = &pWmvDec->Vc1Component[pDstVc1Param->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstVc1Param) + nOffset, + ((char *)pSrcVc1Param) + nOffset, + sizeof(OMX_VIDEO_PARAM_VC1TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_WMV_DEC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + OMX_VIDEO_PARAM_VC1TYPE *pSrcVc1Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVc1Component = &pWmvDec->Vc1Component[pDstProfileLevel->nPortIndex]; + + pDstProfileLevel->eProfile = pSrcVc1Component->eProfile; + pDstProfileLevel->eLevel = pSrcVc1Component->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pWmvDec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexExynosParamReorderMode: + { + EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *pReorderParam = (EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pReorderParam, sizeof(EXYNOS_OMX_VIDEO_PARAM_REORDERMODE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pReorderParam->bReorderMode = pVideoDec->bReorderMode; + } + break; + default: + ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoWmv: + { + OMX_VIDEO_PARAM_WMVTYPE *pDstWmvParam = NULL; + OMX_VIDEO_PARAM_WMVTYPE *pSrcWmvParam = (OMX_VIDEO_PARAM_WMVTYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcWmvParam, sizeof(OMX_VIDEO_PARAM_WMVTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcWmvParam->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstWmvParam = &pWmvDec->WmvComponent[pSrcWmvParam->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstWmvParam) + nOffset, + ((char *)pSrcWmvParam) + nOffset, + sizeof(OMX_VIDEO_PARAM_WMVTYPE) - nOffset); + } + break; + case OMX_IndexParamVideoVC1: + { + OMX_VIDEO_PARAM_VC1TYPE *pDstVc1Param = NULL; + OMX_VIDEO_PARAM_VC1TYPE *pSrcVc1Param = (OMX_VIDEO_PARAM_VC1TYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcVc1Param, sizeof(OMX_VIDEO_PARAM_VC1TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcVc1Param->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstVc1Param = &pWmvDec->Vc1Component[pSrcVc1Param->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstVc1Param) + nOffset, + ((char *)pSrcVc1Param) + nOffset, + sizeof(OMX_VIDEO_PARAM_VC1TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_WMV_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VC1TYPE *pDstVc1Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstVc1Component = &pWmvDec->Vc1Component[pSrcProfileLevel->nPortIndex]; + + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstVc1Component->eProfile = pSrcProfileLevel->eProfile; + pDstVc1Component->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pWmvDec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexExynosParamReorderMode: + { + EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *pReorderParam = (EXYNOS_OMX_VIDEO_PARAM_REORDERMODE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pReorderParam, sizeof(EXYNOS_OMX_VIDEO_PARAM_REORDERMODE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoDec->bReorderMode = pReorderParam->bReorderMode; + } + break; + default: + ret = Exynos_OMX_VideoDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch (nIndex) { + case OMX_IndexConfigCommonOutputCrop: + { + if (pExynosComponent->bUseImgCrop == OMX_TRUE) { + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + } else { + /* query crop information on bitstream */ + OMX_CONFIG_RECTTYPE *pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + + if (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + goto EXIT; + } + + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pSrcRectType = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + } + break; + default: + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + + switch (nIndex) { + default: + ret = Exynos_OMX_VideoDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_REORDER_MODE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamReorderMode; + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = Exynos_OMX_VideoDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_WMV_DEC_ROLE); + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_WmvDec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + + ExynosVideoInstInfo *pVideoInstInfo = &(pWmvDec->hMFCWmvHandle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i; + + FunctionIn(); + + pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc = OMX_FALSE; + pWmvDec->hMFCWmvHandle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pExynosInputPort->portDefinition.format.video.nFrameWidth, + pExynosInputPort->portDefinition.format.video.nFrameHeight, + pExynosInputPort->portDefinition.format.video.nBitrate, + pExynosInputPort->portDefinition.format.video.xFramerate); + + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pExynosInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pExynosInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pExynosInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pExynosInputPort->portDefinition.format.video.xFramerate; + + /* WMV Codec Open */ + ret = WmvCodecOpen(pWmvDec, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + nAllocLen[0] = ALIGN(pExynosInputPort->portDefinition.format.video.nFrameWidth * + pExynosInputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + if (nAllocLen[0] < pVideoDec->nMinInBufSize) + nAllocLen[0] = pVideoDec->nMinInBufSize; + + Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX, MFC_INPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_SetPlaneToPort(pExynosOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SemaphoreCreate(&pExynosOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pWmvDec->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pWmvDec->hSourceStartEvent); + pWmvDec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pWmvDec->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pWmvDec->hDestinationOutStartEvent); + + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pWmvDec->hMFCWmvHandle.indexTimestamp = 0; + pWmvDec->hMFCWmvHandle.outputIndexTimestamp = 0; + /* Default WMV codec format is set as VC1*/ + pWmvDec->hMFCWmvHandle.wmvFormat = WMV_FORMAT_VC1; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pWmvDec->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + pVideoDec->csc_handle = csc_init(csc_method); + if (pVideoDec->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pVideoDec->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_WmvDec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoDec != NULL) { + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + if (pWmvDec != NULL) { + Exynos_OSAL_QueueTerminate(&pWmvDec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pWmvDec->hDestinationInStartEvent); + pWmvDec->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pWmvDec->hDestinationOutStartEvent); + pWmvDec->hDestinationOutStartEvent = NULL; + pWmvDec->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pWmvDec->hSourceStartEvent); + pWmvDec->hSourceStartEvent = NULL; + pWmvDec->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pWmvDec != NULL) { + WmvCodecClose(pWmvDec); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_SrcIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_BOOL bStartCode = OMX_FALSE; + + FunctionIn(); + + if (pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc == OMX_FALSE) { + ret = WmvCodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (pWmvDec->bDestinationStart == OMX_FALSE) && + (pWmvDec->hMFCWmvHandle.bConfiguredMFCDst == OMX_FALSE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = WmvCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to WmvCodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + } + + bStartCode = Check_Stream_PrefixCode(pSrcInputData->buffer.addr[0], oneFrameSize, pWmvDec->hMFCWmvHandle.wmvFormat); + if ((bStartCode == OMX_FALSE) && + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS)) { + OMX_U32 bufferSizeWithHeader; + if (pWmvDec->hMFCWmvHandle.wmvFormat == WMV_FORMAT_WMV3) + bufferSizeWithHeader = oneFrameSize + 8; + else if (pWmvDec->hMFCWmvHandle.wmvFormat == WMV_FORMAT_VC1) + bufferSizeWithHeader = oneFrameSize + 4; + else + bufferSizeWithHeader = 0; + + if (pSrcInputData->allocSize < bufferSizeWithHeader) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] can not attach startcode due to lack of buffer space", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedFrame; + goto EXIT; + } + + /* try to generate a start code */ + bStartCode = Make_Stream_StartCode(pSrcInputData->buffer.addr[0], &oneFrameSize, pWmvDec->hMFCWmvHandle.wmvFormat); + } + + if ((bStartCode == OMX_TRUE) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + if (pVideoDec->bReorderMode == OMX_FALSE) { + /* next slot will be used like as circular queue */ + pExynosComponent->timeStamp[pWmvDec->hMFCWmvHandle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->nFlags[pWmvDec->hMFCWmvHandle.indexTimestamp] = pSrcInputData->nFlags; + } else { /* MSRND */ + Exynos_SetReorderTimestamp(pExynosComponent, &(pWmvDec->hMFCWmvHandle.indexTimestamp), pSrcInputData->timeStamp, pSrcInputData->nFlags); + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), dataLen(%d), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, oneFrameSize, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pWmvDec->hMFCWmvHandle.indexTimestamp); + + pDecOps->Set_FrameTag(hMFCHandle, pWmvDec->hMFCWmvHandle.indexTimestamp); + pWmvDec->hMFCWmvHandle.indexTimestamp++; + pWmvDec->hMFCWmvHandle.indexTimestamp %= MAX_TIMESTAMP; + + if (pVideoDec->bQosChanged == OMX_TRUE) { + if (pWmvDec->hMFCWmvHandle.videoInstInfo.supportInfo.dec.bOperatingRateSupport == VIDEO_TRUE) { + if (pDecOps->Set_OperatingRate != NULL) + pDecOps->Set_OperatingRate(hMFCHandle, pVideoDec->nOperatingRate); + } else if (pDecOps->Set_QosRatio != NULL) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + } + + pVideoDec->bQosChanged = OMX_FALSE; + } + + if (pVideoDec->bSearchBlackBarChanged == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] BlackBar searching mode : %s", + pExynosComponent, __FUNCTION__, + (pVideoDec->bSearchBlackBar == OMX_TRUE) ? "enable" : "disable"); + pDecOps->Set_SearchBlackBar(hMFCHandle, (ExynosVideoBoolType)pVideoDec->bSearchBlackBar); + pVideoDec->bSearchBlackBarChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + pPrivate = (void *)pSrcInputData->bufferHeader; + } else { + nAllocLen[0] = pSrcInputData->allocSize; + + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } + + nDataLen[0] = oneFrameSize; /* it is possible to be changed at Make_Stream_MetaData() */ + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + goto EXIT; + } + WmvCodecStart(pOMXComponent, INPUT_PORT_INDEX); + if (pWmvDec->bSourceStart == OMX_FALSE) { + pWmvDec->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pWmvDec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + if ((pWmvDec->bDestinationStart == OMX_FALSE) && + (pWmvDec->hMFCWmvHandle.bConfiguredMFCDst == OMX_TRUE)) { + pWmvDec->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pWmvDec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pWmvDec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bStartCode == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] can not find a start code", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedFrame; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_SrcOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc == OMX_TRUE) { + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + else + pVideoBuffer = NULL; + } else { + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + pSrcOutputData->bufferHeader = NULL; + } else { + pSrcOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + pSrcOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == + pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]) { + pVideoDec->pMFCDecInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoDec->pMFCDecInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pExynosInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_DstIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) { + nAllocLen[i] = pWmvDec->hMFCWmvHandle.codecOutbufConf.nAlignPlaneSize[i]; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] ADDR[%d]: 0x%x, size[%d]: %d", pExynosComponent, __FUNCTION__, + i, pDstInputData->buffer.addr[i], i, nAllocLen[i]); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + } + + goto EXIT; + } + + WmvCodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_DstOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + ExynosVideoGeometry *bufferGeometry = NULL; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + ExynosVideoColorFormatType nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + OMX_COLOR_FORMATTYPE nOMXFormat = OMX_COLOR_FormatUnused; + OMX_U32 nPixelFormat = 0; + + FunctionIn(); + + if (pWmvDec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + Exynos_OSAL_Memset(&videoBuffer, 0, sizeof(ExynosVideoBuffer)); + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO) at ExtensionDequeue", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + displayStatus = pVideoBuffer->displayStatus; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus: 0x%x", pExynosComponent, __FUNCTION__, displayStatus); + + if ((displayStatus == VIDEO_FRAME_STATUS_DISPLAY_DECODING) || + (displayStatus == VIDEO_FRAME_STATUS_DISPLAY_ONLY) || + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + (CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL)) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pOutputPort->exceptionFlag = NEED_PORT_FLUSH; + pVideoDec->bReconfigDPB = OMX_TRUE; + WmvCodecUpdateResolution(pOMXComponent); + pVideoDec->csc_set_format = OMX_FALSE; + } + ret = OMX_ErrorNone; + goto EXIT; + } + + pWmvDec->hMFCWmvHandle.outputIndexTimestamp++; + pWmvDec->hMFCWmvHandle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->allocSize = pDstOutputData->dataLen = 0; + nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + nDataLen[plane] = pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pWmvDec->hMFCWmvHandle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->cropRect.nLeft = bufferGeometry->cropRect.nLeft; + pBufferInfo->cropRect.nTop = bufferGeometry->cropRect.nTop; + pBufferInfo->cropRect.nWidth = bufferGeometry->cropRect.nWidth; + pBufferInfo->cropRect.nHeight = bufferGeometry->cropRect.nHeight; + pBufferInfo->colorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + + /* calculate each plane info for the application */ + Exynos_OSAL_GetPlaneSize(pOutputPort->portDefinition.format.video.eColorFormat, + PLANE_SINGLE, pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + nDataLen, nAllocLen); + + pDstOutputData->allocSize = nAllocLen[0] + nAllocLen[1] + nAllocLen[2]; + pDstOutputData->dataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + /* update extra info */ + { + /* interlace */ + pWmvDec->hMFCWmvHandle.interlacedType = pVideoBuffer->interlacedType; + + /* SBWC Normal format */ + if (pVideoBuffer->frameType & VIDEO_FRAME_NEED_ACTUAL_FORMAT) { + nVideoFormat = pDecOps->Get_ActualFormat(hMFCHandle); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + nOMXFormat = Exynos_OSAL_Video2OMXFormat((int)nVideoFormat); + + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nPixelFormat = Exynos_OSAL_OMX2HALPixelFormat(nOMXFormat, pOutputPort->ePlaneType); + + if (nPixelFormat != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Normal format at SBWC is 0x%x", + pExynosComponent, __FUNCTION__, nPixelFormat); + pWmvDec->hMFCWmvHandle.nActualFormat = nPixelFormat; + } + } + } + } + } + + /* update extra information to vendor path for renderer + * if BUFFER_COPY_FORCE is used, it will be updated at Exynos_CSC_OutputData() + */ + if ((pOutputPort->bufferProcessType == BUFFER_SHARE) && + (pVideoBuffer->planes[2].addr != NULL)) { + WmvCodecUpdateExtraInfo(pOMXComponent, pVideoBuffer->planes[2].addr); + } + + indexTimestamp = pDecOps->Get_FrameTag(hMFCHandle); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + + if (pVideoDec->bReorderMode == OMX_FALSE) { + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if ((pExynosComponent->checkTimeStamp.needSetStartTimeStamp != OMX_TRUE) && + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp != OMX_TRUE)) { + if (indexTimestamp == INDEX_AFTER_EOS) { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } else { + pDstOutputData->timeStamp = pExynosComponent->timeStamp[pWmvDec->hMFCWmvHandle.outputIndexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[pWmvDec->hMFCWmvHandle.outputIndexTimestamp]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] missing out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + } + } else { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } + } else { + /* For timestamp correction. if mfc support frametype detect */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] disp_pic_frame_type: %d", pExynosComponent, __FUNCTION__, pVideoBuffer->frameType); + + /* NEED TIMESTAMP REORDER */ + if (pVideoDec->bDTSMode == OMX_TRUE) { + if ((pVideoBuffer->frameType & VIDEO_FRAME_I) || + ((pVideoBuffer->frameType & VIDEO_FRAME_OTHERS) && + ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) || + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE)) + pWmvDec->hMFCWmvHandle.outputIndexTimestamp = indexTimestamp; + else + indexTimestamp = pWmvDec->hMFCWmvHandle.outputIndexTimestamp; + } + + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp] | OMX_BUFFERFLAG_ENDOFFRAME; + + if (pVideoBuffer->frameType & VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + } else { /* MSRND */ + EXYNOS_OMX_CURRENT_FRAME_TIMESTAMP sCurrentTimestamp; + + Exynos_GetReorderTimestamp(pExynosComponent, &sCurrentTimestamp, indexTimestamp, pVideoBuffer->frameType); + + pDstOutputData->timeStamp = sCurrentTimestamp.timeStamp; + pDstOutputData->nFlags = sCurrentTimestamp.nFlags | OMX_BUFFERFLAG_ENDOFFRAME; + + pExynosComponent->nFlags[sCurrentTimestamp.nIndex] = 0x00; + pExynosComponent->bTimestampSlotUsed[sCurrentTimestamp.nIndex] = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), reordered tag: %d, original tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + sCurrentTimestamp.nIndex, + indexTimestamp); + } + + if (pVideoBuffer->frameType & VIDEO_FRAME_WITH_BLACK_BAR) { + if (WmvCodecUpdateBlackBarCrop(pOMXComponent) != OMX_ErrorNone) + goto EXIT; + } + + if (pVideoBuffer->frameType & VIDEO_FRAME_CONCEALMENT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + if (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) { + pDstOutputData->remainDataLen = 0; + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp != INDEX_AFTER_EOS) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] tag(%d) is wrong", pExynosComponent, __FUNCTION__, indexTimestamp); + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + goto EXIT; + } + + if ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) || + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->nFlags[indexTimestamp] &= (~OMX_BUFFERFLAG_EOS); + } + } else if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + pDstOutputData->remainDataLen = 0; + + if (pExynosComponent->bBehaviorEOS == OMX_TRUE) { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_srcInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + ret = Exynos_WmvDec_SrcIn(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorInputDataDecodeYet) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorNoneSrcSetupFinish) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorCorruptedFrame)) { + + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pVideoDec->bDiscardCSDError == OMX_TRUE)) { + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_srcOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + if ((pWmvDec->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosInputPort))) { + Exynos_OSAL_SignalWait(pWmvDec->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pWmvDec->hSourceStartEvent); + } + + ret = Exynos_WmvDec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_dstInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + if (pExynosComponent->currentState == OMX_StatePause) + ret = (OMX_ERRORTYPE)OMX_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pWmvDec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pWmvDec->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pWmvDec->hDestinationInStartEvent); + } + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pWmvDec->bypassBufferInfoQ) > 0) { + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pWmvDec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = WmvCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to WmvCodecDstSetup(0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + Exynos_OSAL_SignalSet(pWmvDec->hDestinationOutStartEvent); + } + } + + if (pWmvDec->hMFCWmvHandle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_WmvDec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + if ((pWmvDec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_WmvDec_dstOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_WMVDEC_HANDLE *pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (((pWmvDec->bDestinationStart == OMX_FALSE) || + (pWmvDec->hMFCWmvHandle.bConfiguredMFCDst == OMX_FALSE)) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pWmvDec->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pWmvDec->hDestinationOutStartEvent); + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if (Exynos_OSAL_GetElemNum(&pWmvDec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pWmvDec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_WmvDec_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && + (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + OMX_S32 wmvFormat = WMV_FORMAT_UNKNOWN; + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_WMV_DEC, componentName) != 0) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = HW_VIDEO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pWmvDec = Exynos_OSAL_Malloc(sizeof(EXYNOS_WMVDEC_HANDLE)); + if (pWmvDec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pWmvDec, 0, sizeof(EXYNOS_WMVDEC_HANDLE)); + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoDec->hCodecHandle = (OMX_HANDLETYPE)pWmvDec; + pWmvDec->hMFCWmvHandle.wmvFormat = wmvFormat; + Exynos_OSAL_Strcpy(pExynosComponent->componentName, componentName); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pExynosPort->portDefinition.nBufferSize = CUSTOM_LIMITED_DRM_INPUT_BUFFER_SIZE; + else +#endif + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + } + + pVideoDec->nMinInBufSize = DEFAULT_VIDEO_MIN_INPUT_BUFFER_SIZE; /* for DRC */ + + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/wmv"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + //pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pWmvDec->WmvComponent[i], OMX_VIDEO_PARAM_WMVTYPE); + pWmvDec->WmvComponent[i].nPortIndex = i; + pWmvDec->WmvComponent[i].eFormat = OMX_VIDEO_WMVFormat9; + } + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pWmvDec->Vc1Component[i], OMX_VIDEO_PARAM_VC1TYPE); + pWmvDec->Vc1Component[i].nPortIndex = i; + pWmvDec->Vc1Component[i].eProfile = OMX_VIDEO_VC1ProfileMain; + pWmvDec->Vc1Component[i].eLevel = OMX_VIDEO_VC1LevelHigh; + } + + pOMXComponent->GetParameter = &Exynos_WmvDec_GetParameter; + pOMXComponent->SetParameter = &Exynos_WmvDec_SetParameter; + pOMXComponent->GetConfig = &Exynos_WmvDec_GetConfig; + pOMXComponent->SetConfig = &Exynos_WmvDec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_WmvDec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_WmvDec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_WmvDec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_WmvDec_Terminate; + + pVideoDec->exynos_codec_srcInputProcess = &Exynos_WmvDec_srcInputBufferProcess; + pVideoDec->exynos_codec_srcOutputProcess = &Exynos_WmvDec_srcOutputBufferProcess; + pVideoDec->exynos_codec_dstInputProcess = &Exynos_WmvDec_dstInputBufferProcess; + pVideoDec->exynos_codec_dstOutputProcess = &Exynos_WmvDec_dstOutputBufferProcess; + + pVideoDec->exynos_codec_start = &WmvCodecStart; + pVideoDec->exynos_codec_stop = &WmvCodecStop; + pVideoDec->exynos_codec_bufferProcessRun = &WmvCodecOutputBufferProcessRun; + pVideoDec->exynos_codec_enqueueAllBuffer = &WmvCodecEnQueueAllBuffer; + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &WmvCodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &WmvCodecCheckResolution; + + pVideoDec->exynos_codec_updateExtraInfo = &WmvCodecUpdateExtraInfo; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pWmvDec); + pWmvDec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pWmvDec->hMFCWmvHandle.videoInstInfo.eCodecType = VIDEO_CODING_VC1; + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pWmvDec->hMFCWmvHandle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pWmvDec->hMFCWmvHandle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + if (Exynos_Video_GetInstInfo(&(pWmvDec->hMFCWmvHandle.videoInstInfo), VIDEO_TRUE /* dec */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pWmvDec); + pWmvDec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pWmvDec->hMFCWmvHandle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport == VIDEO_TRUE) + pVideoDec->bDrvDPBManaging = OMX_TRUE; + else + pVideoDec->hRefHandle = Exynos_OSAL_RefCount_Create(); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec DrvDPBManaging(%d)", pExynosComponent, __FUNCTION__, + (pWmvDec->hMFCWmvHandle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport)); + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-dec-compressed-color-format", (OMX_INDEXTYPE)OMX_IndexParamVideoCompressedColorFormat); +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit( + OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoDec->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)pVideoDec->hCodecHandle; + if (pWmvDec != NULL) { + Exynos_OSAL_Free(pWmvDec); + pWmvDec = pVideoDec->hCodecHandle = NULL; + } + + ret = Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/dec/vc1/Exynos_OMX_Wmvdec.h b/openmax/component/video/dec/vc1/Exynos_OMX_Wmvdec.h new file mode 100644 index 0000000..4ec187e --- /dev/null +++ b/openmax/component/video/dec/vc1/Exynos_OMX_Wmvdec.h @@ -0,0 +1,108 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Wmvdec.h + * @brief + * @author HyeYeon Chung (hyeon.chung@samsung.com) + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @version 2.0.0 + * @history + * 2012.07.10 : Create + */ + +#ifndef EXYNOS_OMX_WMV_DEC_COMPONENT +#define EXYNOS_OMX_WMV_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" +#include "ExynosVideoApi.h" + +#define BITMAPINFOHEADER_SIZE 40 +#define BITMAPINFOHEADER_ASFBINDING_SIZE 41 +#define COMPRESSION_POS 16 + +typedef enum WMV_FORMAT { + WMV_FORMAT_VC1, + WMV_FORMAT_WMV3, + WMV_FORMAT_UNKNOWN +} WMV_FORMAT; + +typedef struct _EXYNOS_MFC_WMVDEC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + OMX_S32 maxDPBNum; + WMV_FORMAT wmvFormat; + + /* extra info which will be shared with renderer */ + int interlacedType; + OMX_U32 nActualFormat; + + ExynosVideoColorFormatType MFCOutputColorType; + ExynosVideoDecOps *pDecOps; + ExynosVideoDecBufferOps *pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 3 + OMX_VIDEO_VC1PROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_VC1LEVELTYPE maxLevel[MAX_PROFILE_NUM]; +} EXYNOS_MFC_WMVDEC_HANDLE; + +typedef struct _EXYNOS_WMVDEC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_WMVTYPE WmvComponent[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_VC1TYPE Vc1Component[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + + /* EXYNOS MFC Codec specific */ + EXYNOS_MFC_WMVDEC_HANDLE hMFCWmvHandle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_WMVDEC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName); +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit( + OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE WmvCodecDstSetup( + OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/vc1/NOTICE b/openmax/component/video/dec/vc1/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/dec/vc1/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/dec/vc1/library_register.c b/openmax/component/video/dec/vc1/library_register.c new file mode 100644 index 0000000..f127389 --- /dev/null +++ b/openmax/component/video/dec/vc1/library_register.c @@ -0,0 +1,59 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author HyeYeon Chung (hyeon.chung@samsung.com) + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @version 2.0.0 + * @history + * 2012.07.10 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_WMV_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register( + ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - video decoder WMV */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_WMV_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_WMV_DEC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/openmax/component/video/dec/vc1/library_register.h b/openmax/component/video/dec/vc1/library_register.h new file mode 100644 index 0000000..3288921 --- /dev/null +++ b/openmax/component/video/dec/vc1/library_register.h @@ -0,0 +1,59 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author HyeYeon Chung (hyeon.chung@samsung.com) + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @version 2.0.0 + * @history + * 2012.07.10 : Create + */ + +#ifndef EXYNOS_OMX_WMV_DEC_REG +#define EXYNOS_OMX_WMV_DEC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 1 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* WMV */ +#ifndef USE_CUSTOM_COMPONENT_SUPPORT +#define EXYNOS_OMX_COMPONENT_WMV_DEC "OMX.Exynos.WMV.Decoder" +#else +#define EXYNOS_OMX_COMPONENT_WMV_DEC "OMX.Exynos.vc1.dec" +#endif + +#define EXYNOS_OMX_COMPONENT_WMV_DEC_ROLE "video_decoder.vc1" + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register( + ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/vp8/Android.mk b/openmax/component/video/dec/vp8/Android.mk new file mode 100644 index 0000000..562967a --- /dev/null +++ b/openmax/component/video/dec/vp8/Android.mk @@ -0,0 +1,88 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Vp8dec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.VP8.Decoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := +LOCAL_CFLAGS += -DUSE_VP8_SUPPORT + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager\ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/dec \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_SMALL_SECURE_MEMORY), true) +LOCAL_CFLAGS += -DUSE_SMALL_SECURE_MEMORY +endif + +ifeq ($(BOARD_USE_COMPRESSED_COLOR), true) +LOCAL_CFLAGS += -DUSE_COMPRESSED_COLOR +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/dec/vp8/Exynos_OMX_Vp8dec.c b/openmax/component/video/dec/vp8/Exynos_OMX_Vp8dec.c new file mode 100644 index 0000000..bc295cf --- /dev/null +++ b/openmax/component/video/dec/vp8/Exynos_OMX_Vp8dec.c @@ -0,0 +1,3353 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Vp8dec.c + * @brief + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Vdec.h" +#include "Exynos_OMX_VdecControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Vp8dec.h" +#include "ExynosVideoApi.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" + +#include "Exynos_OSAL_Platform.h" + +/* To use CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */ +/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VP8_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp8Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Dec->hMFCVp8Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP8ProfileMain; + pVp8Dec->hMFCVp8Handle.nProfileCnt = nProfileCnt; + pVp8Dec->hMFCVp8Handle.maxLevel = OMX_VIDEO_VP8Level_Version3; + +EXIT: + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + int nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp8Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pVp8Dec->hMFCVp8Handle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pVp8Dec->hMFCVp8Handle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pVp8Dec->hMFCVp8Handle.maxLevel; +#else + while ((pVp8Dec->hMFCVp8Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pVp8Dec->hMFCVp8Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pVp8Dec->hMFCVp8Handle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pVp8Dec->hMFCVp8Handle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp8Dec == NULL) + goto EXIT; + + while ((pVp8Dec->hMFCVp8Handle.maxLevel >> nLevelCnt++) > 0); + + if ((pVp8Dec->hMFCVp8Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pVp8Dec->hMFCVp8Handle.nProfileCnt; i++) { + if (pVp8Dec->hMFCVp8Handle.profiles[i] == pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + FunctionOut(); + + return (bProfileSupport && bLevelSupport); +} + +static OMX_ERRORTYPE GetCodecOutputPrivateData(OMX_PTR codecBuffer, OMX_PTR addr[], OMX_U32 size[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pCodecBuffer = NULL; + + if (codecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pCodecBuffer = (ExynosVideoBuffer *)codecBuffer; + + if (addr != NULL) { + addr[0] = pCodecBuffer->planes[0].addr; + addr[1] = pCodecBuffer->planes[1].addr; + addr[2] = pCodecBuffer->planes[2].addr; + } + + if (size != NULL) { + size[0] = pCodecBuffer->planes[0].allocSize; + size[1] = pCodecBuffer->planes[1].allocSize; + size[2] = pCodecBuffer->planes[2].allocSize; + } + +EXIT: + return ret; +} + +OMX_BOOL Check_VP8_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize) +{ + OMX_BOOL ret = OMX_FALSE; + + FunctionIn(); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] streamSize: %d", __FUNCTION__, streamSize); + if (streamSize < 3) { + ret = OMX_FALSE; + goto EXIT; + } + + if (!(pInputStream[0] & 0x01)){ + /* Key Frame Start code*/ + if (pInputStream[3] != 0x9d || pInputStream[4] != 0x01 || pInputStream[5]!=0x2a) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] VP8 Key Frame Start Code not Found", __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] VP8 Found Key Frame Start Code", __FUNCTION__); + } + + ret = OMX_TRUE; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp8Dec == NULL) + goto EXIT; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pOutputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pVp8Dec->hMFCVp8Handle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pVp8Dec->hMFCVp8Handle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE VP8CodecOpen(EXYNOS_VP8DEC_HANDLE *pVp8Dec, ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pVp8Dec == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pDecOps = (ExynosVideoDecOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecOps)); + pInbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + pOutbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + + if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVp8Dec->hMFCVp8Handle.pDecOps = pDecOps; + pVp8Dec->hMFCVp8Handle.pInbufOps = pInbufOps; + pVp8Dec->hMFCVp8Handle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pDecOps->nSize = sizeof(ExynosVideoDecOps); + pInbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + + if (Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for decoder ops */ + if ((pDecOps->Init == NULL) || (pDecOps->Finalize == NULL) || + (pDecOps->Get_ActualBufferCount == NULL) || + (pDecOps->Set_FrameTag == NULL) || (pDecOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pVp8Dec->hMFCVp8Handle.hMFCHandle = pVp8Dec->hMFCVp8Handle.pDecOps->Init(pVideoInstInfo); + if (pVp8Dec->hMFCVp8Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pVp8Dec->hMFCVp8Handle.pDecOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pVp8Dec->hMFCVp8Handle.pInbufOps = NULL; + } + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pVp8Dec->hMFCVp8Handle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecClose(EXYNOS_VP8DEC_HANDLE *pVp8Dec) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pVp8Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + if (hMFCHandle != NULL) { + pDecOps->Finalize(hMFCHandle); + pVp8Dec->hMFCVp8Handle.hMFCHandle = NULL; + pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Decoder(pDecOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pVp8Dec->hMFCVp8Handle.pOutbufOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pVp8Dec->hMFCVp8Handle.pInbufOps = NULL; + } + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pVp8Dec->hMFCVp8Handle.pDecOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecStart(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp8Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc == OMX_TRUE)) { + pInbufOps->Run(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst == OMX_TRUE)) { + pOutbufOps->Run(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecStop(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp8Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) { + pInbufOps->Stop(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) { + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pOutbufOps->Stop(hMFCHandle); + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) + pOutbufOps->Clear_RegisteredBuffer(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecOutputBufferProcessRun(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp8Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pVp8Dec->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pVp8Dec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pVp8Dec->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pVp8Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pVp8Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst == OMX_FALSE) { + Exynos_OSAL_SignalSet(pVp8Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Vp8CodecReconfigAllBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + ExynosVideoDecBufferOps *pBufferOps = NULL; + + FunctionIn(); + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pVp8Dec->bSourceStart == OMX_TRUE)) { + ret = OMX_ErrorNotImplemented; + goto EXIT; + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pVp8Dec->bDestinationStart == OMX_TRUE)) { + pBufferOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + if (pExynosPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /**********************************/ + /* Codec Buffer Free & Unregister */ + /**********************************/ + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst = OMX_FALSE; + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = VP8CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to Vp8CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType == BUFFER_SHARE) { + /***************************/ + /* Codec Buffer Unregister */ + /***************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst = OMX_FALSE; + } + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecEnQueueAllBuffer(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + + ExynosVideoDecBufferOps *pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + int i; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecInputBuffer[i]->fd[0], pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pVp8Dec->hMFCVp8Handle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecOutputBuffer[i]->fd[0], pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecUpdateExtraInfo( + OMX_COMPONENTTYPE *pOMXComponent, + ExynosVideoMeta *pMeta) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + + if (pMeta == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMeta->eType = VIDEO_INFO_TYPE_INVALID; + + /* Normal format for SBWC black bar */ + { + if (pVp8Dec->hMFCVp8Handle.nActualFormat != 0) { + pMeta->nPixelFormat = pVp8Dec->hMFCVp8Handle.nActualFormat; + pMeta->eType |= VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT; + + pVp8Dec->hMFCVp8Handle.nActualFormat = 0; + } else { + pMeta->nPixelFormat = 0; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE Vp8CodecUpdateBlackBarCrop(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + OMX_CONFIG_RECTTYPE *pBlackBarCropRect = &pVideoDec->blackBarCropRect; + + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + ExynosVideoRect CropRect; + + FunctionIn(); + + Exynos_OSAL_Memset(&CropRect, 0, sizeof(ExynosVideoRect)); + if (pOutbufOps->Get_BlackBarCrop(hMFCHandle, &CropRect) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get crop info", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + + pBlackBarCropRect->nLeft = CropRect.nLeft; + pBlackBarCropRect->nTop = CropRect.nTop; + pBlackBarCropRect->nWidth = CropRect.nWidth; + pBlackBarCropRect->nHeight = CropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Black Bar Info: LEFT(%d) TOP(%d) WIDTH(%d) HEIGHT(%d)", + pExynosComponent, __FUNCTION__, + pBlackBarCropRect->nLeft, pBlackBarCropRect->nTop, + pBlackBarCropRect->nWidth, pBlackBarCropRect->nHeight); + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + (OMX_INDEXTYPE)OMX_IndexConfigBlackBarCrop, + NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Vp8CodecCheckResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_EXCEPTION_STATE eOutputExcepState = pOutputPort->exceptionFlag; + + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + + OMX_CONFIG_RECTTYPE *pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = &(pInputPort->portDefinition); + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = &(pOutputPort->portDefinition); + + int maxDPBNum = 0; + + FunctionIn(); + + /* get geometry */ + Exynos_OSAL_Memset(&codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to get geometry"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + maxDPBNum += EXTRA_DPB_NUM; + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + } + + /* resolution is changed */ + if ((codecOutbufConf.nFrameWidth != pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth) || + (codecOutbufConf.nFrameHeight != pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight) || + (codecOutbufConf.nStride != pVp8Dec->hMFCVp8Handle.codecOutbufConf.nStride) || +#if 0 // TODO: check posibility + (codecOutbufConf.eColorFormat != pVp8Dec->hMFCVp8Handle.codecOutbufConf.eColorFormat) || + (codecOutbufConf.eFilledDataType != pVp8Dec->hMFCVp8Handle.codecOutbufConf.eFilledDataType) || +#endif + (maxDPBNum != pVp8Dec->hMFCVp8Handle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] DPB(%d), FORMAT(0x%x), TYPE(0x%x) -> DPB(%d), FORMAT(0x%x), TYPE(0x%x)", + pExynosComponent, __FUNCTION__, + pVp8Dec->hMFCVp8Handle.maxDPBNum, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.eColorFormat, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.eFilledDataType, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType); + + pInputPortDefinition->format.video.nFrameWidth = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = codecOutbufConf.nFrameHeight; + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = maxDPBNum; + pOutputPortDefinition->nBufferCountMin = maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* crop info of contents is changed */ + if ((codecOutbufConf.cropRect.nTop != pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nTop) || + (codecOutbufConf.cropRect.nLeft != pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nLeft) || + (codecOutbufConf.cropRect.nWidth != pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nWidth) || + (codecOutbufConf.cropRect.nHeight != pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nHeight)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nWidth, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nHeight, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + Exynos_OSAL_Memcpy(&pVp8Dec->hMFCVp8Handle.codecOutbufConf, &codecOutbufConf, sizeof(codecOutbufConf)); + pVp8Dec->hMFCVp8Handle.maxDPBNum = maxDPBNum; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Vp8CodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + OMX_CONFIG_RECTTYPE *pCropRectangle = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = NULL; + + OMX_BOOL bFormatChanged = OMX_FALSE; + + FunctionIn(); + + /* get geometry for output */ + Exynos_OSAL_Memset(&pVp8Dec->hMFCVp8Handle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pVp8Dec->hMFCVp8Handle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + pVp8Dec->hMFCVp8Handle.maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + pVp8Dec->hMFCVp8Handle.maxDPBNum += EXTRA_DPB_NUM; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] maxDPBNum: %d", pExynosComponent, __FUNCTION__, pVp8Dec->hMFCVp8Handle.maxDPBNum); + + pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] past info: width(%d) height(%d)", + pExynosComponent, __FUNCTION__, + pInputPortDefinition->format.video.nFrameWidth, + pInputPortDefinition->format.video.nFrameHeight); + + /* output format is changed internally (8bit <> 10bit) */ + if (pVp8Dec->hMFCVp8Handle.MFCOutputColorType != pVp8Dec->hMFCVp8Handle.codecOutbufConf.eColorFormat) { + OMX_COLOR_FORMATTYPE eOutputFormat = Exynos_OSAL_Video2OMXFormat(pVp8Dec->hMFCVp8Handle.codecOutbufConf.eColorFormat); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] The format(%x) is changed to %x by H/W Codec", + pExynosComponent, __FUNCTION__, + pVp8Dec->hMFCVp8Handle.MFCOutputColorType, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.eColorFormat); + + pVp8Dec->hMFCVp8Handle.MFCOutputColorType = pVp8Dec->hMFCVp8Handle.codecOutbufConf.eColorFormat; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pOutputPort->ePlaneType)); + + bFormatChanged = OMX_TRUE; + + if (!(pVp8Dec->hMFCVp8Handle.codecOutbufConf.eFilledDataType & DATA_TYPE_8BIT_SBWC)) { + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* SBWC to non SBWC : must update eColorFormat */ + pOutputPort->portDefinition.format.video.eColorFormat = eOutputFormat; + } + + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } else { + pVideoDec->nCompColorFormat = eOutputFormat; + } + } + + switch (pVp8Dec->hMFCVp8Handle.codecOutbufConf.eFilledDataType) { + case DATA_8BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_8BIT_SBWC; + break; + case DATA_10BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_10BIT_SBWC; + break; + default: + pVideoDec->eDataType = DATA_TYPE_8BIT; + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] resolution info: width(%d / %d), height(%d / %d)", + pExynosComponent, __FUNCTION__, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nWidth, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nHeight); + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nHeight; + } + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight; +#if 0 + /* don't need to change */ + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; +#endif + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } else if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPortDefinition->nBufferCountActual != pVp8Dec->hMFCVp8Handle.maxDPBNum) || + ((OMX_S32)pOutputPortDefinition->nBufferCountMin < pVp8Dec->hMFCVp8Handle.maxDPBNum)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight; + + pOutputPortDefinition->nBufferCountActual = pVp8Dec->hMFCVp8Handle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pVp8Dec->hMFCVp8Handle.maxDPBNum; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* contents has crop info */ + if ((pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth != pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nWidth) || + (pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight != pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nHeight)) { + + if ((pOutputPort->bufferProcessType & BUFFER_COPY) && + (pExynosComponent->bUseImgCrop == OMX_TRUE)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + } + + pInputPortDefinition->format.video.nFrameWidth = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged) with crop", + pExynosComponent, __FUNCTION__); + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecHeaderDecoding(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecBufferOps *pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + + FunctionIn(); + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + nAllocLen[0] = pSrcInputData->allocSize; + } + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enqueue input buffer for header parsing", pExynosComponent, __FUNCTION__); +// ret = OMX_ErrorInsufficientResources; + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* start header parsing */ + if (pInbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run input buffer for header parsing", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* get geometry for output */ + Exynos_OSAL_Memset(&pVp8Dec->hMFCVp8Handle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pVp8Dec->hMFCVp8Handle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedHeader; + + if ((pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", pExynosComponent, __FUNCTION__, + *((OMX_U8 *)pSrcInputData->buffer.addr[0]) , *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 1), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 2), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 3), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 4), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 5), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 6), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 7)); + } + + pInbufOps->Stop(hMFCHandle); + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} +OMX_ERRORTYPE VP8CodecSrcSetup(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE eOutputFormat = pExynosOutputPort->portDefinition.format.video.eColorFormat; + OMX_U32 allocFrameSize = 0; + + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + + FunctionIn(); + + if ((pSrcInputData->dataLen <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pVp8Dec->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pVp8Dec->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SignalSet(pVp8Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pVideoDec->bThumbnailMode == OMX_TRUE) + pDecOps->Set_IFrameDecoding(hMFCHandle); + + if ((pDecOps->Enable_DTSMode != NULL) && + (pVideoDec->bDTSMode == OMX_TRUE)) + pDecOps->Enable_DTSMode(hMFCHandle); + + if (pVp8Dec->hMFCVp8Handle.videoInstInfo.supportInfo.dec.bPrioritySupport == VIDEO_TRUE) + pDecOps->Set_Priority(hMFCHandle, pVideoDec->nPriority); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eCompressionFormat = VIDEO_CODING_VP8; + pInbufOps->Set_Shareable(hMFCHandle); + + allocFrameSize = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + allocFrameSize = pSrcInputData->allocSize; + } + + bufferConf.nSizeImage = allocFrameSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + nInBufferCnt = MAX_INPUTBUFFER_NUM_DYNAMIC; + + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + +#ifdef USE_COMPRESSED_COLOR + if ((pExynosOutputPort->eMetaDataType != METADATA_TYPE_GRAPHIC) || + (pExynosOutputPort->bForceUseNonCompFormat == OMX_TRUE)) { + /* use SBWC format only ANB scenario */ + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } +#endif + + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* For SBWC format setting */ + bSupportFormat = CheckFormatHWSupport(pExynosComponent, pVideoDec->nCompColorFormat); + if (bSupportFormat == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] set compressed color format(0x%x)", + pExynosComponent, __FUNCTION__, (OMX_U32)pVideoDec->nCompColorFormat); + + eOutputFormat = pVideoDec->nCompColorFormat; + } + } + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] omx format(0x%x) is %s by h/w", + pExynosComponent, __FUNCTION__, eOutputFormat, + (bSupportFormat == OMX_TRUE)? "supported":"not supported"); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eOutputFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pExynosOutputPort->ePlaneType)); + } else { + OMX_COLOR_FORMATTYPE eCheckFormat = OMX_SEC_COLOR_FormatNV12Tiled; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + if (bSupportFormat != OMX_TRUE) { + eCheckFormat = OMX_COLOR_FormatYUV420SemiPlanar; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + } + if (bSupportFormat == OMX_TRUE) { /* supported by CSC(NV12T/NV12 -> format) */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eCheckFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eCheckFormat, pExynosOutputPort->ePlaneType)); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not support this format (0x%x)", pExynosComponent, __FUNCTION__, eOutputFormat); + ret = OMX_ErrorNotImplemented; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + } + + pVp8Dec->hMFCVp8Handle.MFCOutputColorType = bufferConf.eColorFormat; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output video format is 0x%x", + pExynosComponent, __FUNCTION__, bufferConf.eColorFormat); + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + ret = VP8CodecHeaderDecoding(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc = OMX_TRUE; + + VP8CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + ret = Vp8CodecUpdateResolution(pOMXComponent); + if (ret != OMX_ErrorNone) { + pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc = OMX_FALSE; + VP8CodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + VP8CodecStop(pOMXComponent, INPUT_PORT_INDEX); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nOutbufs, nPlaneCnt; + + FunctionIn(); + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nAlignPlaneSize[i]; + + VP8CodecStop(pOMXComponent, OUTPUT_PORT_INDEX); + + /* for adaptive playback */ + if (pVp8Dec->hMFCVp8Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enable Dynamic DPB", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* get dpb count */ + nOutbufs = pVp8Dec->hMFCVp8Handle.maxDPBNum; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + + pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst = OMX_TRUE; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->eMetaDataType == METADATA_TYPE_DISABLED) { + /*************/ + /* TBD */ + /*************/ + /* data buffer : user buffer + * H/W can't accept user buffer directly + */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst = OMX_TRUE; + } + + if (VP8CodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoVp8: + { + OMX_VIDEO_PARAM_VP8TYPE *pDstVP8Component = (OMX_VIDEO_PARAM_VP8TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP8TYPE *pSrcVP8Component = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstVP8Component, sizeof(OMX_VIDEO_PARAM_VP8TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstVP8Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVP8Component = &pVp8Dec->VP8Component[pDstVP8Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstVP8Component) + nOffset, + ((char *)pSrcVP8Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_VP8TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_VP8_DEC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP8TYPE *pSrcVP8Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVP8Component = &pVp8Dec->VP8Component[pDstProfileLevel->nPortIndex]; + + pDstProfileLevel->eProfile = pSrcVP8Component->eProfile; + pDstProfileLevel->eLevel = pSrcVP8Component->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pVp8Dec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + default: + ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoVp8: + { + OMX_VIDEO_PARAM_VP8TYPE *pDstVP8Component = NULL; + OMX_VIDEO_PARAM_VP8TYPE *pSrcVP8Component = (OMX_VIDEO_PARAM_VP8TYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcVP8Component, sizeof(OMX_VIDEO_PARAM_VP8TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcVP8Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstVP8Component = &pVp8Dec->VP8Component[pSrcVP8Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstVP8Component) + nOffset, + ((char *)pSrcVP8Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_VP8TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_VP8_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP8TYPE *pDstVP8Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstVP8Component = &pVp8Dec->VP8Component[pSrcProfileLevel->nPortIndex]; + + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstVP8Component->eProfile = pSrcProfileLevel->eProfile; + pDstVP8Component->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pVp8Dec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + default: + ret = Exynos_OMX_VideoDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch (nIndex) { + case OMX_IndexConfigCommonOutputCrop: + { + if (pExynosComponent->bUseImgCrop == OMX_TRUE) { + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + } else { + /* query crop information on bitstream */ + OMX_CONFIG_RECTTYPE *pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + + if (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + goto EXIT; + } + + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pSrcRectType = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + } + break; + default: + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + + switch (nIndex) { + default: + ret = Exynos_OMX_VideoDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + ret = Exynos_OMX_VideoDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_VP8_DEC_ROLE); + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_VP8Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + + ExynosVideoInstInfo *pVideoInstInfo = &(pVp8Dec->hMFCVp8Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i; + + FunctionIn(); + + pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pExynosInputPort->portDefinition.format.video.nFrameWidth, + pExynosInputPort->portDefinition.format.video.nFrameHeight, + pExynosInputPort->portDefinition.format.video.nBitrate, + pExynosInputPort->portDefinition.format.video.xFramerate); + + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pExynosInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pExynosInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pExynosInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pExynosInputPort->portDefinition.format.video.xFramerate; + + /* VP8 Codec Open */ + ret = VP8CodecOpen(pVp8Dec, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + nAllocLen[0] = ALIGN(pExynosInputPort->portDefinition.format.video.nFrameWidth * + pExynosInputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + if (nAllocLen[0] < pVideoDec->nMinInBufSize) + nAllocLen[0] = pVideoDec->nMinInBufSize; + + Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX, MFC_INPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_SetPlaneToPort(pExynosOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SemaphoreCreate(&pExynosOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pVp8Dec->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pVp8Dec->hSourceStartEvent); + pVp8Dec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pVp8Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pVp8Dec->hDestinationOutStartEvent); + + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pVp8Dec->hMFCVp8Handle.indexTimestamp = 0; + pVp8Dec->hMFCVp8Handle.outputIndexTimestamp = 0; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pVp8Dec->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + pVideoDec->csc_handle = csc_init(csc_method); + if (pVideoDec->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pVideoDec->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_VP8Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoDec != NULL) { + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + if (pVp8Dec != NULL) { + Exynos_OSAL_QueueTerminate(&pVp8Dec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pVp8Dec->hDestinationInStartEvent); + pVp8Dec->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pVp8Dec->hDestinationOutStartEvent); + pVp8Dec->hDestinationOutStartEvent = NULL; + pVp8Dec->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pVp8Dec->hSourceStartEvent); + pVp8Dec->hSourceStartEvent = NULL; + pVp8Dec->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pVp8Dec != NULL) { + VP8CodecClose(pVp8Dec); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_SrcIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_BOOL bInStartCode = OMX_FALSE; + + FunctionIn(); + + if (pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = VP8CodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (pVp8Dec->bDestinationStart == OMX_FALSE) && + (pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst == OMX_FALSE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = VP8CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Vp8CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + } + + if (((bInStartCode = Check_VP8_StartCode(pSrcInputData->buffer.addr[0], oneFrameSize)) == OMX_TRUE) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + pExynosComponent->timeStamp[pVp8Dec->hMFCVp8Handle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->nFlags[pVp8Dec->hMFCVp8Handle.indexTimestamp] = pSrcInputData->nFlags; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), dataLen(%d), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, oneFrameSize, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pVp8Dec->hMFCVp8Handle.indexTimestamp); + + pDecOps->Set_FrameTag(hMFCHandle, pVp8Dec->hMFCVp8Handle.indexTimestamp); + pVp8Dec->hMFCVp8Handle.indexTimestamp++; + pVp8Dec->hMFCVp8Handle.indexTimestamp %= MAX_TIMESTAMP; + + if (pVideoDec->bQosChanged == OMX_TRUE) { + if (pVp8Dec->hMFCVp8Handle.videoInstInfo.supportInfo.dec.bOperatingRateSupport == VIDEO_TRUE) { + if (pDecOps->Set_OperatingRate != NULL) + pDecOps->Set_OperatingRate(hMFCHandle, pVideoDec->nOperatingRate); + } else if (pDecOps->Set_QosRatio != NULL) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + } + + pVideoDec->bQosChanged = OMX_FALSE; + } + + if (pVideoDec->bSearchBlackBarChanged == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] BlackBar searching mode : %s", + pExynosComponent, __FUNCTION__, + (pVideoDec->bSearchBlackBar == OMX_TRUE) ? "enable" : "disable"); + pDecOps->Set_SearchBlackBar(hMFCHandle, (ExynosVideoBoolType)pVideoDec->bSearchBlackBar); + pVideoDec->bSearchBlackBarChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + pPrivate = (void *)pSrcInputData->bufferHeader; + } else { + nAllocLen[0] = pSrcInputData->allocSize; + + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + goto EXIT; + } + + VP8CodecStart(pOMXComponent, INPUT_PORT_INDEX); + if (pVp8Dec->bSourceStart == OMX_FALSE) { + pVp8Dec->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp8Dec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + if ((pVp8Dec->bDestinationStart == OMX_FALSE) && + (pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst == OMX_TRUE)) { + pVp8Dec->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp8Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pVp8Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] can't find a start code", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedFrame; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_SrcOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc == OMX_TRUE) { + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + else + pVideoBuffer = NULL; + } else { + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + pSrcOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == + pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]) { + pVideoDec->pMFCDecInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoDec->pMFCDecInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pExynosInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_DstIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) { + nAllocLen[i] = pVp8Dec->hMFCVp8Handle.codecOutbufConf.nAlignPlaneSize[i]; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] ADDR[%d]: 0x%x, size[%d]: %d", pExynosComponent, __FUNCTION__, + i, pDstInputData->buffer.addr[i], i, nAllocLen[i]); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + } + + goto EXIT; + } + + VP8CodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_DstOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + ExynosVideoGeometry *bufferGeometry = NULL; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + ExynosVideoColorFormatType nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + OMX_COLOR_FORMATTYPE nOMXFormat = OMX_COLOR_FormatUnused; + OMX_U32 nPixelFormat = 0; + + FunctionIn(); + + if (pVp8Dec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + Exynos_OSAL_Memset(&videoBuffer, 0, sizeof(ExynosVideoBuffer)); + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO) at ExtensionDequeue", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + displayStatus = pVideoBuffer->displayStatus; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus: 0x%x", pExynosComponent, __FUNCTION__, displayStatus); + + if ((displayStatus == VIDEO_FRAME_STATUS_DISPLAY_DECODING) || + (displayStatus == VIDEO_FRAME_STATUS_DISPLAY_ONLY) || + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + (CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL)) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pOutputPort->exceptionFlag = NEED_PORT_FLUSH; + pVideoDec->bReconfigDPB = OMX_TRUE; + Vp8CodecUpdateResolution(pOMXComponent); + pVideoDec->csc_set_format = OMX_FALSE; + } + ret = OMX_ErrorNone; + goto EXIT; + } + + pVp8Dec->hMFCVp8Handle.outputIndexTimestamp++; + pVp8Dec->hMFCVp8Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->allocSize = pDstOutputData->dataLen = 0; + nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + nDataLen[plane] = pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pVp8Dec->hMFCVp8Handle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->cropRect.nLeft = bufferGeometry->cropRect.nLeft; + pBufferInfo->cropRect.nTop = bufferGeometry->cropRect.nTop; + pBufferInfo->cropRect.nWidth = bufferGeometry->cropRect.nWidth; + pBufferInfo->cropRect.nHeight = bufferGeometry->cropRect.nHeight; + pBufferInfo->colorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + + /* calculate each plane info for the application */ + Exynos_OSAL_GetPlaneSize(pOutputPort->portDefinition.format.video.eColorFormat, + PLANE_SINGLE, pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + nDataLen, nAllocLen); + + pDstOutputData->allocSize = nAllocLen[0] + nAllocLen[1] + nAllocLen[2]; + pDstOutputData->dataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + /* update extra info */ + { + /* SBWC Normal format */ + if (pVideoBuffer->frameType & VIDEO_FRAME_NEED_ACTUAL_FORMAT) { + nVideoFormat = pDecOps->Get_ActualFormat(hMFCHandle); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + nOMXFormat = Exynos_OSAL_Video2OMXFormat((int)nVideoFormat); + + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nPixelFormat = Exynos_OSAL_OMX2HALPixelFormat(nOMXFormat, pOutputPort->ePlaneType); + + if (nPixelFormat != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Normal format at SBWC is 0x%x", + pExynosComponent, __FUNCTION__, nPixelFormat); + pVp8Dec->hMFCVp8Handle.nActualFormat = nPixelFormat; + } + } + } + } + } + + /* update extra information to vendor path for renderer + * if BUFFER_COPY_FORCE is used, it will be updated at Exynos_CSC_OutputData() + */ + if ((pOutputPort->bufferProcessType == BUFFER_SHARE) && + (pVideoBuffer->planes[2].addr != NULL)) { + VP8CodecUpdateExtraInfo(pOMXComponent, pVideoBuffer->planes[2].addr); + } + + indexTimestamp = pDecOps->Get_FrameTag(hMFCHandle); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if ((pExynosComponent->checkTimeStamp.needSetStartTimeStamp != OMX_TRUE) && + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp != OMX_TRUE)) { + if (indexTimestamp == INDEX_AFTER_EOS) { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } else { + pDstOutputData->timeStamp = pExynosComponent->timeStamp[pVp8Dec->hMFCVp8Handle.outputIndexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[pVp8Dec->hMFCVp8Handle.outputIndexTimestamp]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] missing out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + } + } else { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } + } else { + /* For timestamp correction. if mfc support frametype detect */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] disp_pic_frame_type: %d", pExynosComponent, __FUNCTION__, pVideoBuffer->frameType); + + /* NEED TIMESTAMP REORDER */ + if (pVideoDec->bDTSMode == OMX_TRUE) { + if ((pVideoBuffer->frameType & VIDEO_FRAME_I) || + ((pVideoBuffer->frameType & VIDEO_FRAME_OTHERS) && + ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) || + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE)) + pVp8Dec->hMFCVp8Handle.outputIndexTimestamp = indexTimestamp; + else + indexTimestamp = pVp8Dec->hMFCVp8Handle.outputIndexTimestamp; + } + + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp] | OMX_BUFFERFLAG_ENDOFFRAME; + + if (pVideoBuffer->frameType & VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + + if (pVideoBuffer->frameType & VIDEO_FRAME_WITH_BLACK_BAR) { + if (Vp8CodecUpdateBlackBarCrop(pOMXComponent) != OMX_ErrorNone) + goto EXIT; + } + + if (pVideoBuffer->frameType & VIDEO_FRAME_CONCEALMENT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + if (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) { + pDstOutputData->remainDataLen = 0; + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp != INDEX_AFTER_EOS) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] tag(%d) is wrong", pExynosComponent, __FUNCTION__, indexTimestamp); + + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + goto EXIT; + } + + if ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) || + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->nFlags[indexTimestamp] &= (~OMX_BUFFERFLAG_EOS); + } + } else if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + pDstOutputData->remainDataLen = 0; + + if (pExynosComponent->bBehaviorEOS == OMX_TRUE) { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_srcInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + ret = Exynos_VP8Dec_SrcIn(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorInputDataDecodeYet) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorCorruptedFrame)) { + + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pVideoDec->bDiscardCSDError == OMX_TRUE)) { + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_srcOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosInputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + if ((pVp8Dec->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosInputPort))) { + Exynos_OSAL_SignalWait(pVp8Dec->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp8Dec->hSourceStartEvent); + } + + ret = Exynos_VP8Dec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_dstInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + if (pExynosComponent->currentState == OMX_StatePause) + ret = (OMX_ERRORTYPE)OMX_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pVp8Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pVp8Dec->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp8Dec->hDestinationInStartEvent); + } + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pVp8Dec->bypassBufferInfoQ) > 0) { + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pVp8Dec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = VP8CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Vp8CodecDstSetup(0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + Exynos_OSAL_SignalSet(pVp8Dec->hDestinationOutStartEvent); + } + } + + if (pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_VP8Dec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + if ((pVp8Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Dec_dstOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (((pVp8Dec->bDestinationStart == OMX_FALSE) || + (pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst == OMX_FALSE)) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pVp8Dec->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp8Dec->hDestinationOutStartEvent); + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if (Exynos_OSAL_GetElemNum(&pVp8Dec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pVp8Dec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_VP8Dec_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && + (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP8_DEC, componentName) != 0) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = HW_VIDEO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pVp8Dec = Exynos_OSAL_Malloc(sizeof(EXYNOS_VP8DEC_HANDLE)); + if (pVp8Dec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVp8Dec, 0, sizeof(EXYNOS_VP8DEC_HANDLE)); + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoDec->hCodecHandle = (OMX_HANDLETYPE)pVp8Dec; + Exynos_OSAL_Strcpy(pExynosComponent->componentName, componentName); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pExynosPort->portDefinition.nBufferSize = CUSTOM_LIMITED_DRM_INPUT_BUFFER_SIZE; + else +#endif + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + } + + pVideoDec->nMinInBufSize = (DEFAULT_VIDEO_MIN_INPUT_BUFFER_SIZE * 2); /* for DRC :: depends on compression ratio */ + + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/x-vnd.on2.vp8"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pVp8Dec->VP8Component[i], OMX_VIDEO_PARAM_VP8TYPE); + pVp8Dec->VP8Component[i].nPortIndex = i; + pVp8Dec->VP8Component[i].eProfile = OMX_VIDEO_VP8ProfileMain; + pVp8Dec->VP8Component[i].eLevel = OMX_VIDEO_VP8Level_Version3; + } + + pOMXComponent->GetParameter = &Exynos_VP8Dec_GetParameter; + pOMXComponent->SetParameter = &Exynos_VP8Dec_SetParameter; + pOMXComponent->GetConfig = &Exynos_VP8Dec_GetConfig; + pOMXComponent->SetConfig = &Exynos_VP8Dec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_VP8Dec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_VP8Dec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_VP8Dec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_VP8Dec_Terminate; + + pVideoDec->exynos_codec_srcInputProcess = &Exynos_VP8Dec_srcInputBufferProcess; + pVideoDec->exynos_codec_srcOutputProcess = &Exynos_VP8Dec_srcOutputBufferProcess; + pVideoDec->exynos_codec_dstInputProcess = &Exynos_VP8Dec_dstInputBufferProcess; + pVideoDec->exynos_codec_dstOutputProcess = &Exynos_VP8Dec_dstOutputBufferProcess; + + pVideoDec->exynos_codec_start = &VP8CodecStart; + pVideoDec->exynos_codec_stop = &VP8CodecStop; + pVideoDec->exynos_codec_bufferProcessRun = &VP8CodecOutputBufferProcessRun; + pVideoDec->exynos_codec_enqueueAllBuffer = &VP8CodecEnQueueAllBuffer; + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &Vp8CodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &Vp8CodecCheckResolution; + + pVideoDec->exynos_codec_updateExtraInfo = NULL; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pVp8Dec); + pVp8Dec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVp8Dec->hMFCVp8Handle.videoInstInfo.eCodecType = VIDEO_CODING_VP8; + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pVp8Dec->hMFCVp8Handle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pVp8Dec->hMFCVp8Handle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + if (Exynos_Video_GetInstInfo(&(pVp8Dec->hMFCVp8Handle.videoInstInfo), VIDEO_TRUE /* dec */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pVp8Dec); + pVp8Dec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pVp8Dec->hMFCVp8Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport == VIDEO_TRUE) + pVideoDec->bDrvDPBManaging = OMX_TRUE; + else + pVideoDec->hRefHandle = Exynos_OSAL_RefCount_Create(); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec DrvDPBManaging(%d)", pExynosComponent, __FUNCTION__, + (pVp8Dec->hMFCVp8Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport)); + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-dec-compressed-color-format", (OMX_INDEXTYPE)OMX_IndexParamVideoCompressedColorFormat); +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit( + OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoDec->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp8Dec != NULL) { + Exynos_OSAL_Free(pVp8Dec); + pVp8Dec = pVideoDec->hCodecHandle = NULL; + } + + ret = Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/dec/vp8/Exynos_OMX_Vp8dec.h b/openmax/component/video/dec/vp8/Exynos_OMX_Vp8dec.h new file mode 100644 index 0000000..134bb5e --- /dev/null +++ b/openmax/component/video/dec/vp8/Exynos_OMX_Vp8dec.h @@ -0,0 +1,96 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Vp8dec.h + * @brief + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_VP8_DEC_COMPONENT +#define EXYNOS_OMX_VP8_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" +#include "ExynosVideoApi.h" + + +typedef struct _EXYNOS_MFC_VP8DEC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + OMX_S32 maxDPBNum; + + /* extra info which will be shared with renderer */ + OMX_U32 nActualFormat; + + ExynosVideoColorFormatType MFCOutputColorType; + ExynosVideoDecOps *pDecOps; + ExynosVideoDecBufferOps *pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 1 + OMX_VIDEO_VP8PROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_VP8LEVELTYPE maxLevel; +} EXYNOS_MFC_VP8DEC_HANDLE; + +typedef struct _EXYNOS_VP8DEC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_VP8TYPE VP8Component[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + + /* EXYNOS MFC Codec specific */ + EXYNOS_MFC_VP8DEC_HANDLE hMFCVp8Handle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_VP8DEC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName); +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit( + OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE VP8CodecDstSetup( + OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/vp8/NOTICE b/openmax/component/video/dec/vp8/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/dec/vp8/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/dec/vp8/library_register.c b/openmax/component/video/dec/vp8/library_register.c new file mode 100644 index 0000000..3cd7c40 --- /dev/null +++ b/openmax/component/video/dec/vp8/library_register.c @@ -0,0 +1,59 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VP8_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register( + ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - video decoder VP8 */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_VP8_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_VP8_DEC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/openmax/component/video/dec/vp8/library_register.h b/openmax/component/video/dec/vp8/library_register.h new file mode 100644 index 0000000..4d8ca84 --- /dev/null +++ b/openmax/component/video/dec/vp8/library_register.h @@ -0,0 +1,60 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_VP8_DEC_REG +#define EXYNOS_OMX_VP8_DEC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 1 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* VP8 */ +#ifndef USE_CUSTOM_COMPONENT_SUPPORT +#define EXYNOS_OMX_COMPONENT_VP8_DEC "OMX.Exynos.VP8.Decoder" +#else +#define EXYNOS_OMX_COMPONENT_VP8_DEC "OMX.Exynos.vp8.dec" +#endif + +#define EXYNOS_OMX_COMPONENT_VP8_DEC_ROLE "video_decoder.vp8" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register( + ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/vp9/Android.mk b/openmax/component/video/dec/vp9/Android.mk new file mode 100644 index 0000000..2bd4a45 --- /dev/null +++ b/openmax/component/video/dec/vp9/Android.mk @@ -0,0 +1,88 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Vp9dec.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.VP9.Decoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := +LOCAL_CFLAGS += -DUSE_VP9_SUPPORT + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/dec \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_SMALL_SECURE_MEMORY), true) +LOCAL_CFLAGS += -DUSE_SMALL_SECURE_MEMORY +endif + +ifeq ($(BOARD_USE_COMPRESSED_COLOR), true) +LOCAL_CFLAGS += -DUSE_COMPRESSED_COLOR +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/dec/vp9/Exynos_OMX_Vp9dec.c b/openmax/component/video/dec/vp9/Exynos_OMX_Vp9dec.c new file mode 100644 index 0000000..3476db6 --- /dev/null +++ b/openmax/component/video/dec/vp9/Exynos_OMX_Vp9dec.c @@ -0,0 +1,3684 @@ +/* + * + * Copyright 2014 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Vp9dec.c + * @brief + * @author Taehwan Kim (t_h.kim@samsung.com) + * SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2014.07.24 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Vdec.h" +#include "Exynos_OMX_VdecControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Vp9dec.h" +#include "ExynosVideoApi.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" + +#include "Exynos_OSAL_Platform.h" + +#include "VendorVideoAPI.h" + +/* To use CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */ +/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VP9_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp9Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Dec->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile0; + switch (pVp9Dec->hMFCVp9Handle.videoInstInfo.HwVersion) { + case MFC_1501: + case MFC_150: + case MFC_1410: + case MFC_1400: + case MFC_140: + case MFC_130: + pVp9Dec->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile2; + pVp9Dec->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile2HDR; + pVp9Dec->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile2HDR10Plus; + break; + case MFC_120: + case MFC_1220: + pVp9Dec->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile2; + pVp9Dec->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile2HDR; + break; + default: + break; + } + pVp9Dec->hMFCVp9Handle.nProfileCnt = nProfileCnt; + + switch (pVp9Dec->hMFCVp9Handle.videoInstInfo.HwVersion) { + case MFC_1501: + case MFC_150: + pVp9Dec->hMFCVp9Handle.maxLevel = OMX_VIDEO_VP9Level6; + break; + case MFC_1410: + case MFC_1400: + case MFC_140: + case MFC_130: + case MFC_120: + case MFC_1220: + pVp9Dec->hMFCVp9Handle.maxLevel = OMX_VIDEO_VP9Level51; + break; + default: + pVp9Dec->hMFCVp9Handle.maxLevel = OMX_VIDEO_VP9Level41; + break; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp9Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pVp9Dec->hMFCVp9Handle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pVp9Dec->hMFCVp9Handle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pVp9Dec->hMFCVp9Handle.maxLevel; +#else + while ((pVp9Dec->hMFCVp9Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pVp9Dec->hMFCVp9Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pVp9Dec->hMFCVp9Handle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pVp9Dec->hMFCVp9Handle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp9Dec == NULL) + goto EXIT; + + while ((pVp9Dec->hMFCVp9Handle.maxLevel >> nLevelCnt++) > 0); + + if ((pVp9Dec->hMFCVp9Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pVp9Dec->hMFCVp9Handle.nProfileCnt; i++) { + if (pVp9Dec->hMFCVp9Handle.profiles[i] == pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + FunctionOut(); + + return (bProfileSupport && bLevelSupport); +} + +static OMX_ERRORTYPE GetCodecOutputPrivateData(OMX_PTR codecBuffer, OMX_PTR addr[], OMX_U32 size[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pCodecBuffer = NULL; + + if (codecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pCodecBuffer = (ExynosVideoBuffer *)codecBuffer; + + if (addr != NULL) { + addr[0] = pCodecBuffer->planes[0].addr; + addr[1] = pCodecBuffer->planes[1].addr; + addr[2] = pCodecBuffer->planes[2].addr; + } + + if (size != NULL) { + size[0] = pCodecBuffer->planes[0].allocSize; + size[1] = pCodecBuffer->planes[1].allocSize; + size[2] = pCodecBuffer->planes[2].allocSize; + } + +EXIT: + return ret; +} + +OMX_BOOL Check_VP9_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize) +{ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] buffer: %p, streamSize: %d", __FUNCTION__, pInputStream, streamSize); + if (streamSize < 1) { + return OMX_FALSE; + } + + return OMX_TRUE; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) + goto EXIT; + + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp9Dec == NULL) + goto EXIT; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pOutputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pVp9Dec->hMFCVp9Handle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pVp9Dec->hMFCVp9Handle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE VP9CodecOpen(EXYNOS_VP9DEC_HANDLE *pVp9Dec, ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pVp9Dec == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pDecOps = (ExynosVideoDecOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecOps)); + pInbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + pOutbufOps = (ExynosVideoDecBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoDecBufferOps)); + + if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVp9Dec->hMFCVp9Handle.pDecOps = pDecOps; + pVp9Dec->hMFCVp9Handle.pInbufOps = pInbufOps; + pVp9Dec->hMFCVp9Handle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pDecOps->nSize = sizeof(ExynosVideoDecOps); + pInbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoDecBufferOps); + + if (Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for decoder ops */ + if ((pDecOps->Init == NULL) || (pDecOps->Finalize == NULL) || + (pDecOps->Get_ActualBufferCount == NULL) || + (pDecOps->Set_FrameTag == NULL) || (pDecOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pVp9Dec->hMFCVp9Handle.hMFCHandle = pVp9Dec->hMFCVp9Handle.pDecOps->Init(pVideoInstInfo); + if (pVp9Dec->hMFCVp9Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pVp9Dec->hMFCVp9Handle.pDecOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pVp9Dec->hMFCVp9Handle.pInbufOps = NULL; + } + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pVp9Dec->hMFCVp9Handle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecClose(EXYNOS_VP9DEC_HANDLE *pVp9Dec) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pVp9Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + if (hMFCHandle != NULL) { + pDecOps->Finalize(hMFCHandle); + pVp9Dec->hMFCVp9Handle.hMFCHandle = NULL; + pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Decoder(pDecOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pVp9Dec->hMFCVp9Handle.pOutbufOps = NULL; + } + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pVp9Dec->hMFCVp9Handle.pInbufOps = NULL; + } + if (pDecOps != NULL) { + Exynos_OSAL_Free(pDecOps); + pVp9Dec->hMFCVp9Handle.pDecOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecStart(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp9Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc == OMX_TRUE)) { + pInbufOps->Run(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst == OMX_TRUE)) { + pOutbufOps->Run(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecStop(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp9Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) { + pInbufOps->Stop(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) { + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pOutbufOps->Stop(hMFCHandle); + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) + pOutbufOps->Clear_RegisteredBuffer(hMFCHandle); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecOutputBufferProcessRun(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoDec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp9Dec == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pVp9Dec->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pVp9Dec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pVp9Dec->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pVp9Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pVp9Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst == OMX_FALSE) { + Exynos_OSAL_SignalSet(pVp9Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Vp9CodecReconfigAllBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + ExynosVideoDecBufferOps *pBufferOps = NULL; + + FunctionIn(); + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pVp9Dec->bSourceStart == OMX_TRUE)) { + ret = OMX_ErrorNotImplemented; + goto EXIT; + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pVp9Dec->bDestinationStart == OMX_TRUE)) { + pBufferOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + if (pExynosPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /**********************************/ + /* Codec Buffer Free & Unregister */ + /**********************************/ + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst = OMX_FALSE; + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = VP9CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to Vp9CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType == BUFFER_SHARE) { + /***************************/ + /* Codec Buffer Unregister */ + /***************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + + pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst = OMX_FALSE; + } + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecEnQueueAllBuffer(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + + ExynosVideoDecBufferOps *pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + int i; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecInputBuffer[i]->fd[0], pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pVp9Dec->hMFCVp9Handle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoDec->pMFCDecOutputBuffer[i]->fd[0], pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + +void Vp9CodecUpdateHdrInfo(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoHdrInfo *pHdrInfo = &(pVp9Dec->hMFCVp9Handle.sHdrInfo); + + if (pDecOps->Get_HDRInfo(hMFCHandle, pHdrInfo) == VIDEO_ERROR_NONE) { + /* update bitstream's info to input port */ + EXYNOS_OMX_VIDEO_COLORASPECTS *pColorAspects = &(pInputPort->ColorAspects); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eType(0x%x) is changed", pExynosComponent, __FUNCTION__, pHdrInfo->eChangedType); + + /* color aspects */ + if (pHdrInfo->eValidType & (HDR_INFO_COLOR_ASPECTS | HDR_INFO_RANGE)) { + /* HDR_INFO_COLOR_ASPECTS (8) */ + pColorAspects->nCoeffType = pHdrInfo->sColorAspects.eCoeffType; + pColorAspects->nPrimaryType = pHdrInfo->sColorAspects.ePrimariesType; + pColorAspects->nTransferType = pHdrInfo->sColorAspects.eTransferType; + + /* HDR_INFO_RANGE (16) */ + pColorAspects->nRangeType = pHdrInfo->sColorAspects.eRangeType; + } + +#ifdef USE_ANDROID + /* if both have changed, should send an event once */ + if (pHdrInfo->eChangedType & (HDR_INFO_COLOR_ASPECTS | HDR_INFO_RANGE)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_IndexConfigVideoColorAspects)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigVideoColorAspects, + NULL); + } +#endif + } + +EXIT: + + return; +} + +OMX_ERRORTYPE VP9CodecUpdateExtraInfo( + OMX_COMPONENTTYPE *pOMXComponent, + ExynosVideoMeta *pMeta) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + + if (pMeta == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMeta->eType = VIDEO_INFO_TYPE_INVALID; + + /* hdr static info : the bitstream doesn't have this. always sets value set by framework */ + { + ExynosType1 *pMetaHDR = &(pMeta->sHdrStaticInfo.sType1); + EXYNOS_OMX_VIDEO_HDRSTATICINFO *pHDRStaticInfo = &(pOutputPort->HDRStaticInfo); + + EXYNOS_OMX_VIDEO_HDRSTATICINFO invalid; + Exynos_OSAL_Memset(&invalid, 0, sizeof(invalid)); + + if (Exynos_OSAL_Memcmp(pHDRStaticInfo, &invalid, sizeof(EXYNOS_OMX_VIDEO_HDRSTATICINFO))) { + pMeta->eType = VIDEO_INFO_TYPE_HDR_STATIC; + + pMetaHDR->mMaxFrameAverageLightLevel = pHDRStaticInfo->nMaxPicAverageLight; + pMetaHDR->mMaxContentLightLevel = pHDRStaticInfo->nMaxContentLight; + pMetaHDR->mMaxDisplayLuminance = pHDRStaticInfo->nMaxDisplayLuminance; + pMetaHDR->mMinDisplayLuminance = pHDRStaticInfo->nMinDisplayLuminance; + + pMetaHDR->mR.x = pHDRStaticInfo->red.x; + pMetaHDR->mR.y = pHDRStaticInfo->red.y; + + pMetaHDR->mG.x = pHDRStaticInfo->green.x; + pMetaHDR->mG.y = pHDRStaticInfo->green.y; + + pMetaHDR->mB.x = pHDRStaticInfo->blue.x; + pMetaHDR->mB.y = pHDRStaticInfo->blue.y; + + pMetaHDR->mW.x = pHDRStaticInfo->white.x; + pMetaHDR->mW.y = pHDRStaticInfo->white.y; + } + } + + /* Normal format for SBWC black bar */ + { + if (pVp9Dec->hMFCVp9Handle.nActualFormat != 0) { + pMeta->nPixelFormat = pVp9Dec->hMFCVp9Handle.nActualFormat; + pMeta->eType |= VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT; + + pVp9Dec->hMFCVp9Handle.nActualFormat = 0; + } else { + pMeta->nPixelFormat = 0; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE VP9CodecUpdateHDR10PlusInfo( + OMX_COMPONENTTYPE *pOMXComponent, + ExynosVideoMeta *pMeta, + void *pHDR10PlusInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + ExynosHdrDynamicInfo *pExynosHDR10PlusInfo = NULL; + + if ((pMeta == NULL) || (pHDR10PlusInfo == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosHDR10PlusInfo = &(pMeta->sHdrDynamicInfo); + + ret = setHDR10PlusInfoForVendorPath(pOMXComponent, pExynosHDR10PlusInfo, pHDR10PlusInfo); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set HDR10Plus Info for Vendor path", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosHDR10PlusInfo->valid = 1; + + pMeta->eType |= VIDEO_INFO_TYPE_HDR_DYNAMIC; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Vp9CodecUpdateBlackBarCrop(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + OMX_CONFIG_RECTTYPE *pBlackBarCropRect = &pVideoDec->blackBarCropRect; + + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + ExynosVideoRect CropRect; + + FunctionIn(); + + Exynos_OSAL_Memset(&CropRect, 0, sizeof(ExynosVideoRect)); + if (pOutbufOps->Get_BlackBarCrop(hMFCHandle, &CropRect) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get crop info", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + + pBlackBarCropRect->nLeft = CropRect.nLeft; + pBlackBarCropRect->nTop = CropRect.nTop; + pBlackBarCropRect->nWidth = CropRect.nWidth; + pBlackBarCropRect->nHeight = CropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Black Bar Info: LEFT(%d) TOP(%d) WIDTH(%d) HEIGHT(%d)", + pExynosComponent, __FUNCTION__, + pBlackBarCropRect->nLeft, pBlackBarCropRect->nTop, + pBlackBarCropRect->nWidth, pBlackBarCropRect->nHeight); + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + (OMX_INDEXTYPE)OMX_IndexConfigBlackBarCrop, + NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Vp9CodecCheckResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_EXCEPTION_STATE eOutputExcepState = pOutputPort->exceptionFlag; + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + + OMX_CONFIG_RECTTYPE *pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = &(pInputPort->portDefinition); + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = &(pOutputPort->portDefinition); + + int maxDPBNum = 0; + + FunctionIn(); + + /* get geometry */ + Exynos_OSAL_Memset(&codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to get geometry"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); + if (pVideoDec->bThumbnailMode == OMX_FALSE) + maxDPBNum += EXTRA_DPB_NUM; + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + } + + /* resolution is changed */ + if ((codecOutbufConf.nFrameWidth != pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth) || + (codecOutbufConf.nFrameHeight != pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight) || + (codecOutbufConf.nStride != pVp9Dec->hMFCVp9Handle.codecOutbufConf.nStride) || +#if 0 // TODO: check posibility + (codecOutbufConf.eColorFormat != pVp9Dec->hMFCVp9Handle.codecOutbufConf.eColorFormat) || + (codecOutbufConf.eFilledDataType != pVp9Dec->hMFCVp9Handle.codecOutbufConf.eFilledDataType) || +#endif + (maxDPBNum != pVp9Dec->hMFCVp9Handle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] DPB(%d), FORMAT(0x%x), TYPE(0x%x) -> DPB(%d), FORMAT(0x%x), TYPE(0x%x)", + pExynosComponent, __FUNCTION__, + pVp9Dec->hMFCVp9Handle.maxDPBNum, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.eColorFormat, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.eFilledDataType, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType); + + pInputPortDefinition->format.video.nFrameWidth = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = codecOutbufConf.nFrameHeight; + + if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = maxDPBNum; + pOutputPortDefinition->nBufferCountMin = maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* crop info of contents is changed */ + if ((codecOutbufConf.cropRect.nTop != pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nTop) || + (codecOutbufConf.cropRect.nLeft != pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nLeft) || + (codecOutbufConf.cropRect.nWidth != pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nWidth) || + (codecOutbufConf.cropRect.nHeight != pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nHeight)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][DRC] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nWidth, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nHeight, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = codecOutbufConf.cropRect.nHeight; + + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + Exynos_OSAL_Memcpy(&pVp9Dec->hMFCVp9Handle.codecOutbufConf, &codecOutbufConf, sizeof(codecOutbufConf)); + pVp9Dec->hMFCVp9Handle.maxDPBNum = maxDPBNum; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Vp9CodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + OMX_CONFIG_RECTTYPE *pCropRectangle = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pInputPortDefinition = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pOutputPortDefinition = NULL; + + OMX_BOOL bFormatChanged = OMX_FALSE; + + FunctionIn(); + + /* get geometry for output */ + Exynos_OSAL_Memset(&pVp9Dec->hMFCVp9Handle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pVp9Dec->hMFCVp9Handle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorHardware; + goto EXIT; + } + + /* get dpb count */ + pVp9Dec->hMFCVp9Handle.maxDPBNum = pDecOps->Get_ActualBufferCount(hMFCHandle); +#if 0 /* no needs EXTRA_DPB, it was confirmed codec team */ + if (pVideoDec->bThumbnailMode == OMX_FALSE) + pVp9Dec->hMFCVp9Handle.maxDPBNum += EXTRA_DPB_NUM; +#endif + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] maxDPBNum: %d", pExynosComponent, __FUNCTION__, pVp9Dec->hMFCVp9Handle.maxDPBNum); + + pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] past info: width(%d) height(%d)", + pExynosComponent, __FUNCTION__, + pInputPortDefinition->format.video.nFrameWidth, + pInputPortDefinition->format.video.nFrameHeight); + + /* output format is changed internally (8bit <> 10bit) */ + if (pVp9Dec->hMFCVp9Handle.MFCOutputColorType != pVp9Dec->hMFCVp9Handle.codecOutbufConf.eColorFormat) { + OMX_COLOR_FORMATTYPE eOutputFormat = Exynos_OSAL_Video2OMXFormat(pVp9Dec->hMFCVp9Handle.codecOutbufConf.eColorFormat); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] The format(%x) is changed to %x by H/W Codec", + pExynosComponent, __FUNCTION__, + pVp9Dec->hMFCVp9Handle.MFCOutputColorType, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.eColorFormat); + + pVp9Dec->hMFCVp9Handle.MFCOutputColorType = pVp9Dec->hMFCVp9Handle.codecOutbufConf.eColorFormat; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pOutputPort->ePlaneType)); + + bFormatChanged = OMX_TRUE; + + if (!(pVp9Dec->hMFCVp9Handle.codecOutbufConf.eFilledDataType & DATA_TYPE_8BIT_SBWC)) { + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* SBWC to non SBWC : must update eColorFormat */ + pOutputPort->portDefinition.format.video.eColorFormat = eOutputFormat; + } + + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } else { + pVideoDec->nCompColorFormat = eOutputFormat; + } + } + + switch (pVp9Dec->hMFCVp9Handle.codecOutbufConf.eFilledDataType) { + case DATA_8BIT_WITH_2BIT: + pVideoDec->eDataType = DATA_TYPE_8BIT_WITH_2BIT; + break; + case DATA_10BIT: + pVideoDec->eDataType = DATA_TYPE_10BIT; + break; + case DATA_8BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_8BIT_SBWC; + break; + case DATA_10BIT_SBWC: + pVideoDec->eDataType = DATA_TYPE_10BIT_SBWC; + break; + default: + pVideoDec->eDataType = DATA_TYPE_8BIT; + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] resolution info: width(%d / %d), height(%d / %d)", + pExynosComponent, __FUNCTION__, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nWidth, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nHeight); + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + pCropRectangle->nTop = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nHeight; + } + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight; +#if 0 + /* don't need to change */ + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; +#endif + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } else if (pOutputPort->bufferProcessType == BUFFER_SHARE) { + if ((pVideoDec->bReconfigDPB) || + (bFormatChanged) || + (pInputPortDefinition->format.video.nFrameWidth != pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth) || + (pInputPortDefinition->format.video.nFrameHeight != pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPortDefinition->nBufferCountActual != pVp9Dec->hMFCVp9Handle.maxDPBNum) || + ((OMX_S32)pOutputPortDefinition->nBufferCountMin < pVp9Dec->hMFCVp9Handle.maxDPBNum)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + pInputPortDefinition->format.video.nFrameWidth = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight; + + pOutputPortDefinition->nBufferCountActual = pVp9Dec->hMFCVp9Handle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pVp9Dec->hMFCVp9Handle.maxDPBNum; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + 0, + NULL); + } + } + + /* contents has crop info */ + if ((pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth != pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nWidth) || + (pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight != pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nHeight)) { + + if ((pOutputPort->bufferProcessType & BUFFER_COPY) && + (pExynosComponent->bUseImgCrop == OMX_TRUE)) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + } + + pInputPortDefinition->format.video.nFrameWidth = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nFrameHeight = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight; + pInputPortDefinition->format.video.nStride = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth; + pInputPortDefinition->format.video.nSliceHeight = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight; + + Exynos_UpdateFrameSize(pOMXComponent); + + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + pCropRectangle->nTop = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nLeft = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nWidth = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged) with crop", + pExynosComponent, __FUNCTION__); + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Vp9CodecUpdateDisplayResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + OMX_CONFIG_RECTTYPE *pCropRectangle = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + ExynosVideoGeometry *pCodecOutbufConf = &pVp9Dec->hMFCVp9Handle.codecOutbufConf; + ExynosVideoGeometry newCodecOutbufConf; + + FunctionIn(); + + Exynos_OSAL_Memset(&newCodecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &newCodecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Inter Resolution Chnage: resol(%d x %d), stride(%d), crop(l:%d, t:%d, w:%d, h:%d) -> resol(%d x %d), stride(%d), crop(l:%d, t:%d, w:%d, h:%d)", + pExynosComponent, __FUNCTION__, + pCodecOutbufConf->nFrameWidth, pCodecOutbufConf->nFrameHeight, pCodecOutbufConf->nStride, + pCodecOutbufConf->cropRect.nLeft, pCodecOutbufConf->cropRect.nTop, + pCodecOutbufConf->cropRect.nWidth, pCodecOutbufConf->cropRect.nHeight, + newCodecOutbufConf.nFrameWidth, newCodecOutbufConf.nFrameHeight, newCodecOutbufConf.nStride, + newCodecOutbufConf.cropRect.nLeft, newCodecOutbufConf.cropRect.nTop, + newCodecOutbufConf.cropRect.nWidth, newCodecOutbufConf.cropRect.nHeight); + + Exynos_OSAL_Memcpy(pCodecOutbufConf, &newCodecOutbufConf, sizeof(ExynosVideoGeometry)); + + pCropRectangle->nLeft = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nLeft; + pCropRectangle->nTop = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nTop; + pCropRectangle->nWidth = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nWidth; + pCropRectangle->nHeight = pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventPortSettingsChanged) with crop", + pExynosComponent, __FUNCTION__); + /** Send crop info call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventPortSettingsChanged, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigCommonOutputCrop, + NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecHeaderDecoding(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecBufferOps *pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + + FunctionIn(); + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + nAllocLen[0] = pSrcInputData->allocSize; + } + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enqueue input buffer for header parsing", pExynosComponent, __FUNCTION__); +// ret = OMX_ErrorInsufficientResources; + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* start header parsing */ + if (pInbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run input buffer for header parsing", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecInit; + goto EXIT; + } + + /* get geometry for output */ + Exynos_OSAL_Memset(&pVp9Dec->hMFCVp9Handle.codecOutbufConf, 0, sizeof(ExynosVideoGeometry)); + if (pOutbufOps->Get_Geometry(hMFCHandle, &pVp9Dec->hMFCVp9Handle.codecOutbufConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about output", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedHeader; + + if ((pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", pExynosComponent, __FUNCTION__, + *((OMX_U8 *)pSrcInputData->buffer.addr[0]) , *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 1), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 2), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 3), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 4), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 5), + *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 6), *((OMX_U8 *)pSrcInputData->buffer.addr[0] + 7)); + } + + pInbufOps->Stop(hMFCHandle); + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecSrcSetup(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE eOutputFormat = pExynosOutputPort->portDefinition.format.video.eColorFormat; + OMX_U32 allocFrameSize = 0; + + EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA = &(pExynosOutputPort->ColorAspects); + EXYNOS_OMX_VIDEO_COLORASPECTS *pBSCA = &(pExynosInputPort->ColorAspects); + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + + FunctionIn(); + + if ((pSrcInputData->dataLen <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pVp9Dec->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pVp9Dec->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SignalSet(pVp9Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + /* MFC VP9 Decoder doesn't need CodecPrivate(as CSD) */ + if (pSrcInputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] VP9 decoder ignores CodecPrivate data(CSD)", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedFrame; + goto EXIT; + } + + if (pVideoDec->bThumbnailMode == OMX_TRUE) + pDecOps->Set_IFrameDecoding(hMFCHandle); + + if ((pDecOps->Enable_DTSMode != NULL) && + (pVideoDec->bDTSMode == OMX_TRUE)) + pDecOps->Enable_DTSMode(hMFCHandle); + + if (pVp9Dec->hMFCVp9Handle.videoInstInfo.supportInfo.dec.bPrioritySupport == VIDEO_TRUE) + pDecOps->Set_Priority(hMFCHandle, pVideoDec->nPriority); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eCompressionFormat = VIDEO_CODING_VP9; + pInbufOps->Set_Shareable(hMFCHandle); + + allocFrameSize = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + /* OMX buffer is not used directly : CODEC buffer */ + allocFrameSize = pSrcInputData->allocSize; + } + + bufferConf.nSizeImage = allocFrameSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + nInBufferCnt = MAX_INPUTBUFFER_NUM_DYNAMIC; + + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + +#ifdef USE_COMPRESSED_COLOR + if ((pExynosOutputPort->eMetaDataType != METADATA_TYPE_GRAPHIC) || + (pExynosOutputPort->bForceUseNonCompFormat == OMX_TRUE)) { + /* use SBWC format only ANB scenario */ + pVideoDec->nCompColorFormat = OMX_COLOR_FormatUnused; + } +#endif + + if (pVideoDec->nCompColorFormat != OMX_COLOR_FormatUnused) { + /* For SBWC format setting */ + bSupportFormat = CheckFormatHWSupport(pExynosComponent, pVideoDec->nCompColorFormat); + if (bSupportFormat == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] set compressed color format(0x%x)", + pExynosComponent, __FUNCTION__, (OMX_U32)pVideoDec->nCompColorFormat); + + eOutputFormat = pVideoDec->nCompColorFormat; + } + } + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] omx format(0x%x) is %s by h/w", + pExynosComponent, __FUNCTION__, eOutputFormat, + (bSupportFormat == OMX_TRUE)? "supported":"not supported"); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eOutputFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pExynosOutputPort->ePlaneType)); + } else { + OMX_COLOR_FORMATTYPE eCheckFormat = OMX_SEC_COLOR_FormatNV12Tiled; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + if (bSupportFormat != OMX_TRUE) { + eCheckFormat = OMX_COLOR_FormatYUV420SemiPlanar; + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eCheckFormat); + } + if (bSupportFormat == OMX_TRUE) { /* supported by CSC(NV12T/NV12 -> format) */ + bufferConf.eColorFormat = Exynos_OSAL_OMX2VideoFormat(eCheckFormat, pExynosOutputPort->ePlaneType); + Exynos_SetPlaneToPort(pExynosOutputPort, Exynos_OSAL_GetPlaneCount(eCheckFormat, pExynosOutputPort->ePlaneType)); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not support this format (0x%x)", pExynosComponent, __FUNCTION__, eOutputFormat); + ret = OMX_ErrorNotImplemented; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + } + + pVp9Dec->hMFCVp9Handle.MFCOutputColorType = bufferConf.eColorFormat; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output video format is 0x%x", + pExynosComponent, __FUNCTION__, bufferConf.eColorFormat); + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + ret = VP9CodecHeaderDecoding(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc = OMX_TRUE; + + VP9CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + ret = Vp9CodecUpdateResolution(pOMXComponent); + if (ret != OMX_ErrorNone) { + pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc = OMX_FALSE; + VP9CodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + VP9CodecStop(pOMXComponent, INPUT_PORT_INDEX); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + int i, nOutbufs, nPlaneCnt; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + FunctionIn(); + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nAlignPlaneSize[i]; + + VP9CodecStop(pOMXComponent, OUTPUT_PORT_INDEX); + + /* for adaptive playback */ + if (pVp9Dec->hMFCVp9Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to enable Dynamic DPB", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* get dpb count */ + nOutbufs = pVp9Dec->hMFCVp9Handle.maxDPBNum; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + + pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst = OMX_TRUE; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->eMetaDataType == METADATA_TYPE_DISABLED) { + /*************/ + /* TBD */ + /*************/ + /* data buffer : user buffer + * H/W can't accept user buffer directly + */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst = OMX_TRUE; + } + + if (VP9CodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoVp9: + { + OMX_VIDEO_PARAM_VP9TYPE *pDstVP9Component = (OMX_VIDEO_PARAM_VP9TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP9TYPE *pSrcVP9Component = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstVP9Component, sizeof(OMX_VIDEO_PARAM_VP9TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstVP9Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVP9Component = &pVp9Dec->VP9Component[pDstVP9Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstVP9Component) + nOffset, + ((char *)pSrcVP9Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_VP9TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_VP9_DEC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP9TYPE *pSrcVP9Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVP9Component = &pVp9Dec->VP9Component[pDstProfileLevel->nPortIndex]; + + pDstProfileLevel->eProfile = pSrcVP9Component->eProfile; + pDstProfileLevel->eLevel = pSrcVP9Component->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pVp9Dec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + default: + ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoVp9: + { + OMX_VIDEO_PARAM_VP9TYPE *pDstVP9Component = NULL; + OMX_VIDEO_PARAM_VP9TYPE *pSrcVP9Component = (OMX_VIDEO_PARAM_VP9TYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcVP9Component, sizeof(OMX_VIDEO_PARAM_VP9TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcVP9Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstVP9Component = &pVp9Dec->VP9Component[pSrcVP9Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstVP9Component) + nOffset, + ((char *)pSrcVP9Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_VP9TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_VP9_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingVP9; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP9TYPE *pDstVP9Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstVP9Component = &pVp9Dec->VP9Component[pSrcProfileLevel->nPortIndex]; + + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstVP9Component->eProfile = pSrcProfileLevel->eProfile; + pDstVP9Component->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pVp9Dec->errorCorrectionType[INPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + default: + ret = Exynos_OMX_VideoDecodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigCommonOutputCrop: + { + if (pExynosComponent->bUseImgCrop == OMX_TRUE) { + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + } else { + /* query crop information on bitstream */ + OMX_CONFIG_RECTTYPE *pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + + if (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + goto EXIT; + } + + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pSrcRectType = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigVideoHdr10PlusInfo: + { + ret = Exynos_OSAL_GetConfig(hComponent, nIndex, pComponentConfigStructure); + } + break; +#endif + default: + ret = Exynos_OMX_VideoDecodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { +#ifdef USE_ANDROID + case OMX_IndexConfigVideoHdr10PlusInfo: + { + ret = Exynos_OSAL_SetConfig(hComponent, nIndex, pComponentConfigStructure); + } + break; +#endif + default: + ret = Exynos_OMX_VideoDecodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + +#ifdef USE_ANDROID + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_HDR10_PLUS_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoHdr10PlusInfo; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + ret = Exynos_OMX_VideoDecodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_VP9_DEC_ROLE); + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_VP9Dec_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + + ExynosVideoInstInfo *pVideoInstInfo = &(pVp9Dec->hMFCVp9Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i; + + FunctionIn(); + + pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pExynosInputPort->portDefinition.format.video.nFrameWidth, + pExynosInputPort->portDefinition.format.video.nFrameHeight, + pExynosInputPort->portDefinition.format.video.nBitrate, + pExynosInputPort->portDefinition.format.video.xFramerate); + + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pExynosInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pExynosInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pExynosInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pExynosInputPort->portDefinition.format.video.xFramerate; + + /* VP9 Codec Open */ + ret = VP9CodecOpen(pVp9Dec, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + nAllocLen[0] = ALIGN(pExynosInputPort->portDefinition.format.video.nFrameWidth * + pExynosInputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + if (nAllocLen[0] < pVideoDec->nMinInBufSize) + nAllocLen[0] = pVideoDec->nMinInBufSize; + + Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX, MFC_INPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, pVideoDec->pMFCDecInputBuffer[i]); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_SetPlaneToPort(pExynosOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_OSAL_SemaphoreCreate(&pExynosOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pVp9Dec->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pVp9Dec->hSourceStartEvent); + pVp9Dec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pVp9Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pVp9Dec->hDestinationOutStartEvent); + + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pVp9Dec->hMFCVp9Handle.indexTimestamp = 0; + pVp9Dec->hMFCVp9Handle.outputIndexTimestamp = 0; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pVp9Dec->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) { + pVideoDec->csc_handle = csc_init(CSC_METHOD_HW); + csc_set_hw_property(pVideoDec->csc_handle, CSC_HW_PROPERTY_FIXED_NODE, 2); + csc_set_hw_property(pVideoDec->csc_handle, CSC_HW_PROPERTY_MODE_DRM, 1); + } else { + pVideoDec->csc_handle = csc_init(csc_method); + } + + if (pVideoDec->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pVideoDec->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_VP9Dec_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoDec != NULL) { + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + if (pVp9Dec != NULL) { + Exynos_OSAL_QueueTerminate(&pVp9Dec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pVp9Dec->hDestinationInStartEvent); + pVp9Dec->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pVp9Dec->hDestinationOutStartEvent); + pVp9Dec->hDestinationOutStartEvent = NULL; + pVp9Dec->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pVp9Dec->hSourceStartEvent); + pVp9Dec->hSourceStartEvent = NULL; + pVp9Dec->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pVp9Dec != NULL) { + VP9CodecClose(pVp9Dec); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_SrcIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_BOOL bInStartCode = OMX_FALSE; + + OMX_U32 nConfigCnt = 0; + OMX_PTR pHDR10plusConfig = NULL; + + int i; + + FunctionIn(); + + if (pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = VP9CodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (pVp9Dec->bDestinationStart == OMX_FALSE) && + (pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst == OMX_FALSE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = VP9CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Vp9CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + } + + if (((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) || + ((bInStartCode = Check_VP9_StartCode(pSrcInputData->buffer.addr[0], oneFrameSize)) == OMX_TRUE)) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + pExynosComponent->timeStamp[pVp9Dec->hMFCVp9Handle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->nFlags[pVp9Dec->hMFCVp9Handle.indexTimestamp] = pSrcInputData->nFlags; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), dataLen(%d), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, oneFrameSize, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pVp9Dec->hMFCVp9Handle.indexTimestamp); + + pDecOps->Set_FrameTag(hMFCHandle, pVp9Dec->hMFCVp9Handle.indexTimestamp); + + if (pVp9Dec->hMFCVp9Handle.videoInstInfo.supportInfo.dec.bHDRDynamicInfoSupport == VIDEO_TRUE) { + nConfigCnt = Exynos_OSAL_GetElemNum(&pExynosComponent->HDR10plusConfigQ); + if (nConfigCnt > 0) { + pHDR10plusConfig = Exynos_OSAL_Dequeue(&pExynosComponent->HDR10plusConfigQ); + + if (pHDR10plusConfig == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to dequeue HDR10+ config", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + for (i = 0; i < MAX_BUFFER_REF; i++) { + if (pExynosComponent->HDR10plusList[i].bOccupied == OMX_FALSE) { + int nParamSize = *(OMX_U32 *)pHDR10plusConfig; + + pExynosComponent->HDR10plusList[i].pHDR10PlusInfo = Exynos_OSAL_Malloc(nParamSize); + if (pExynosComponent->HDR10plusList[i].pHDR10PlusInfo == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pExynosComponent->HDR10plusList[i].bOccupied = OMX_TRUE; + pExynosComponent->HDR10plusList[i].nTag = pVp9Dec->hMFCVp9Handle.indexTimestamp; + Exynos_OSAL_Memcpy(pExynosComponent->HDR10plusList[i].pHDR10PlusInfo, pHDR10plusConfig, nParamSize); + Exynos_OSAL_Free(pHDR10plusConfig); + + break; + } + } + } + } + + pVp9Dec->hMFCVp9Handle.indexTimestamp++; + pVp9Dec->hMFCVp9Handle.indexTimestamp %= MAX_TIMESTAMP; + + if (pVideoDec->bQosChanged == OMX_TRUE) { + if (pVp9Dec->hMFCVp9Handle.videoInstInfo.supportInfo.dec.bOperatingRateSupport == VIDEO_TRUE) { + if (pDecOps->Set_OperatingRate != NULL) + pDecOps->Set_OperatingRate(hMFCHandle, pVideoDec->nOperatingRate); + } else if (pDecOps->Set_QosRatio != NULL) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + } + + pVideoDec->bQosChanged = OMX_FALSE; + } + + if (pVideoDec->bSearchBlackBarChanged == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] BlackBar searching mode : %s", + pExynosComponent, __FUNCTION__, + (pVideoDec->bSearchBlackBar == OMX_TRUE) ? "enable" : "disable"); + pDecOps->Set_SearchBlackBar(hMFCHandle, (ExynosVideoBoolType)pVideoDec->bSearchBlackBar); + pVideoDec->bSearchBlackBarChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + pPrivate = (void *)pSrcInputData->bufferHeader; + } else { + nAllocLen[0] = pSrcInputData->allocSize; + + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + goto EXIT; + } + VP9CodecStart(pOMXComponent, INPUT_PORT_INDEX); + if (pVp9Dec->bSourceStart == OMX_FALSE) { + pVp9Dec->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp9Dec->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + if ((pVp9Dec->bDestinationStart == OMX_FALSE) && + (pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst == OMX_TRUE)) { + pVp9Dec->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp9Dec->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pVp9Dec->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] can't find a start code", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCorruptedFrame; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_SrcOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc == OMX_TRUE) { + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + else + pVideoBuffer = NULL; + } else { + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + pSrcOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == + pVideoDec->pMFCDecInputBuffer[i]->pVirAddr[0]) { + pVideoDec->pMFCDecInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoDec->pMFCDecInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pExynosInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_DstIn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (i = 0; i < nPlaneCnt; i++) { + nAllocLen[i] = pVp9Dec->hMFCVp9Handle.codecOutbufConf.nAlignPlaneSize[i]; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] ADDR[%d]: 0x%x, size[%d]: %d", pExynosComponent, __FUNCTION__, + i, pDstInputData->buffer.addr[i], i, nAllocLen[i]); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + } + + goto EXIT; + } + + VP9CodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_DstOut(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + ExynosVideoGeometry *bufferGeometry = NULL; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + ExynosVideoColorFormatType nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + OMX_COLOR_FORMATTYPE nOMXFormat = OMX_COLOR_FormatUnused; + OMX_U32 nPixelFormat = 0; + + int i; + + FunctionIn(); + + if (pVp9Dec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + Exynos_OSAL_Memset(&videoBuffer, 0, sizeof(ExynosVideoBuffer)); + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO) at ExtensionDequeue", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + displayStatus = pVideoBuffer->displayStatus; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus: 0x%x", pExynosComponent, __FUNCTION__, displayStatus); + + if ((displayStatus == VIDEO_FRAME_STATUS_DISPLAY_DECODING) || + (displayStatus == VIDEO_FRAME_STATUS_DISPLAY_ONLY) || + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + (displayStatus == VIDEO_FRAME_STATUS_DISPLAY_INTER_RESOL_CHANGE) || + (CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL)) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pOutputPort->exceptionFlag = NEED_PORT_FLUSH; + pVideoDec->bReconfigDPB = OMX_TRUE; + Vp9CodecUpdateResolution(pOMXComponent); + pVideoDec->csc_set_format = OMX_FALSE; + } + ret = OMX_ErrorNone; + goto EXIT; + } + + /* inter-frame display resolution change */ + if (displayStatus == VIDEO_FRAME_STATUS_DISPLAY_INTER_RESOL_CHANGE) { + if (pExynosComponent->bUseImgCrop == OMX_TRUE) /* reset ImgCropInfo because resolution change makes ImgCropInfo invalid. */ + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + + Vp9CodecUpdateDisplayResolution(pOMXComponent); + } + + pVp9Dec->hMFCVp9Handle.outputIndexTimestamp++; + pVp9Dec->hMFCVp9Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->allocSize = pDstOutputData->dataLen = 0; + nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + nDataLen[plane] = pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pVp9Dec->hMFCVp9Handle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->cropRect.nLeft = bufferGeometry->cropRect.nLeft; + pBufferInfo->cropRect.nTop = bufferGeometry->cropRect.nTop; + pBufferInfo->cropRect.nWidth = bufferGeometry->cropRect.nWidth; + pBufferInfo->cropRect.nHeight = bufferGeometry->cropRect.nHeight; + pBufferInfo->colorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + if (pOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + + /* calculate each plane info for the application */ + Exynos_OSAL_GetPlaneSize(pOutputPort->portDefinition.format.video.eColorFormat, + PLANE_SINGLE, pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + nDataLen, nAllocLen); + + pDstOutputData->allocSize = nAllocLen[0] + nAllocLen[1] + nAllocLen[2]; + pDstOutputData->dataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + /* update extra info */ + { + /* color aspects : the bitstream has only this */ + if (pVideoBuffer->frameType & VIDEO_FRAME_WITH_HDR_INFO) + Vp9CodecUpdateHdrInfo(pOMXComponent); + + /* SBWC Normal format */ + if (pVideoBuffer->frameType & VIDEO_FRAME_NEED_ACTUAL_FORMAT) { + nVideoFormat = pDecOps->Get_ActualFormat(hMFCHandle); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + nOMXFormat = Exynos_OSAL_Video2OMXFormat((int)nVideoFormat); + + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nPixelFormat = Exynos_OSAL_OMX2HALPixelFormat(nOMXFormat, pOutputPort->ePlaneType); + + if (nPixelFormat != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Normal format at SBWC is 0x%x", + pExynosComponent, __FUNCTION__, nPixelFormat); + pVp9Dec->hMFCVp9Handle.nActualFormat = nPixelFormat; + } + } + } + } + } + + /* update extra information to vendor path for renderer + * if BUFFER_COPY_FORCE is used, it will be updated at Exynos_CSC_OutputData() + */ + if ((pOutputPort->bufferProcessType == BUFFER_SHARE) && + (pVideoBuffer->planes[2].addr != NULL)) { + VP9CodecUpdateExtraInfo(pOMXComponent, pVideoBuffer->planes[2].addr); + } + + indexTimestamp = pDecOps->Get_FrameTag(hMFCHandle); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if ((pExynosComponent->checkTimeStamp.needSetStartTimeStamp != OMX_TRUE) && + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp != OMX_TRUE)) { + if (indexTimestamp == INDEX_AFTER_EOS) { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } else { + pDstOutputData->timeStamp = pExynosComponent->timeStamp[pVp9Dec->hMFCVp9Handle.outputIndexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[pVp9Dec->hMFCVp9Handle.outputIndexTimestamp]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] missing out indexTimestamp: %d", pExynosComponent, __FUNCTION__, indexTimestamp); + } + } else { + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + } + } else { + /* Find HDR10+ info for framework */ + if (pVp9Dec->hMFCVp9Handle.videoInstInfo.supportInfo.dec.bHDRDynamicInfoSupport == VIDEO_TRUE) { + for (i = 0; i < MAX_BUFFER_REF; i++) { + if ((pExynosComponent->HDR10plusList[i].bOccupied == OMX_TRUE) && + (pExynosComponent->HDR10plusList[i].nTag == indexTimestamp)) { + if (Exynos_OSAL_Queue(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].HdrDynamicInfoQ, (void *)pExynosComponent->HDR10plusList[i].pHDR10PlusInfo) != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Failed to Queue HDR10+ info", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pExynosComponent->HDR10plusList[i].pHDR10PlusInfo); + pExynosComponent->HDR10plusList[i].pHDR10PlusInfo = NULL; + pExynosComponent->HDR10plusList[i].bOccupied = OMX_FALSE; + + break; + } + + /* This code is for supporting HDR10Plus vendor path. + * This will be removed if HWC supports official interface for HDR10Plus. + */ + if ((pOutputPort->bufferProcessType == BUFFER_SHARE) && + (pVideoBuffer->planes[2].addr != NULL)) { + VP9CodecUpdateHDR10PlusInfo(pOMXComponent, pVideoBuffer->planes[2].addr, (void *)pExynosComponent->HDR10plusList[i].pHDR10PlusInfo); + } + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] send event(OMX_EventConfigUpdate)", + pExynosComponent, __FUNCTION__); + /** Send ConfigUpdate Event call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventConfigUpdate, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigVideoHdr10PlusInfo, + NULL); + + break; + } + } + } + + /* For timestamp correction. if mfc support frametype detect */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] disp_pic_frame_type: %d", pExynosComponent, __FUNCTION__, pVideoBuffer->frameType); + + /* NEED TIMESTAMP REORDER */ + if (pVideoDec->bDTSMode == OMX_TRUE) { + if ((pVideoBuffer->frameType & VIDEO_FRAME_I) || + ((pVideoBuffer->frameType & VIDEO_FRAME_OTHERS) && + ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) || + (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE)) + pVp9Dec->hMFCVp9Handle.outputIndexTimestamp = indexTimestamp; + else + indexTimestamp = pVp9Dec->hMFCVp9Handle.outputIndexTimestamp; + } + + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp] | OMX_BUFFERFLAG_ENDOFFRAME; + + if (pVideoBuffer->frameType & VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + } + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + + if (pVideoBuffer->frameType & VIDEO_FRAME_WITH_BLACK_BAR) { + if (Vp9CodecUpdateBlackBarCrop(pOMXComponent) != OMX_ErrorNone) + goto EXIT; + } + + if (pVideoBuffer->frameType & VIDEO_FRAME_CONCEALMENT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + if (displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) { + pDstOutputData->remainDataLen = 0; + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp != INDEX_AFTER_EOS) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] tag(%d) is wrong", pExynosComponent, __FUNCTION__, indexTimestamp); + + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + goto EXIT; + } + + if ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) || + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->nFlags[indexTimestamp] &= (~OMX_BUFFERFLAG_EOS); + } + } else if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + pDstOutputData->remainDataLen = 0; + + if (pExynosComponent->bBehaviorEOS == OMX_TRUE) { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = nDataLen[0] + nDataLen[1] + nDataLen[2]; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_srcInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + if ((pVideoDec->bForceHeaderParsing == OMX_FALSE) && + (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX))) { + ret = (OMX_ERRORTYPE)OMX_ErrorInputDataDecodeYet; + goto EXIT; + } + + ret = Exynos_VP9Dec_SrcIn(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorInputDataDecodeYet) && + ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorCorruptedFrame)) { + + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pVideoDec->bDiscardCSDError == OMX_TRUE)) { + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_srcOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosInputPort)) || (!CHECK_PORT_POPULATED(pExynosInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + if ((pVp9Dec->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosInputPort))) { + Exynos_OSAL_SignalWait(pVp9Dec->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp9Dec->hSourceStartEvent); + } + + ret = Exynos_VP9Dec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_dstInputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + if (pExynosComponent->currentState == OMX_StatePause) + ret = (OMX_ERRORTYPE)OMX_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pVp9Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pVp9Dec->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp9Dec->hDestinationInStartEvent); + } + + if (pExynosOutputPort->bufferProcessType == BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pVp9Dec->bypassBufferInfoQ) > 0) { + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pVp9Dec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] do DstSetup", pExynosComponent, __FUNCTION__); + ret = VP9CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Vp9CodecDstSetup(0x%x)", pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + Exynos_OSAL_SignalSet(pVp9Dec->hDestinationOutStartEvent); + } + } + + if (pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_VP9Dec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } else { + if ((pVp9Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Dec_dstOutputBufferProcess(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pExynosOutputPort)) || + (!CHECK_PORT_POPULATED(pExynosOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (((pVp9Dec->bDestinationStart == OMX_FALSE) || + (pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst == OMX_FALSE)) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pVp9Dec->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp9Dec->hDestinationOutStartEvent); + } + + if (pExynosOutputPort->bufferProcessType & (BUFFER_COPY | BUFFER_COPY_FORCE)) { + if (Exynos_OSAL_GetElemNum(&pVp9Dec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pVp9Dec->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_VP9Dec_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && + (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + OMX_BOOL bSecureMode = OMX_FALSE; + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP9_DEC, componentName) == 0) { + bSecureMode = OMX_FALSE; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP9_DRM_DEC, componentName) == 0) { + bSecureMode = OMX_TRUE; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = (bSecureMode == OMX_TRUE)? HW_VIDEO_DEC_SECURE_CODEC:HW_VIDEO_DEC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pVp9Dec = Exynos_OSAL_Malloc(sizeof(EXYNOS_VP9DEC_HANDLE)); + if (pVp9Dec == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x)", pExynosComponent, __FUNCTION__, ret); + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVp9Dec, 0, sizeof(EXYNOS_VP9DEC_HANDLE)); + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoDec->hCodecHandle = (OMX_HANDLETYPE)pVp9Dec; + Exynos_OSAL_Strcpy(pExynosComponent->componentName, componentName); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pExynosPort->portDefinition.nBufferSize = CUSTOM_LIMITED_DRM_INPUT_BUFFER_SIZE; + else +#endif + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + } + + pVideoDec->nMinInBufSize = DEFAULT_VIDEO_MIN_INPUT_BUFFER_SIZE; /* for DRC */ + + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingVP9; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/x-vnd.on2.vp9"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + +#ifdef USE_SINGLE_PLANE_IN_DRM + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pExynosPort->ePlaneType = PLANE_SINGLE; +#endif + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pVp9Dec->VP9Component[i], OMX_VIDEO_PARAM_VP9TYPE); + pVp9Dec->VP9Component[i].nPortIndex = i; + pVp9Dec->VP9Component[i].eProfile = OMX_VIDEO_VP9Profile0; + pVp9Dec->VP9Component[i].eLevel = OMX_VIDEO_VP9Level41; + } + + pOMXComponent->GetParameter = &Exynos_VP9Dec_GetParameter; + pOMXComponent->SetParameter = &Exynos_VP9Dec_SetParameter; + pOMXComponent->GetConfig = &Exynos_VP9Dec_GetConfig; + pOMXComponent->SetConfig = &Exynos_VP9Dec_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_VP9Dec_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_VP9Dec_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_VP9Dec_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_VP9Dec_Terminate; + + pVideoDec->exynos_codec_srcInputProcess = &Exynos_VP9Dec_srcInputBufferProcess; + pVideoDec->exynos_codec_srcOutputProcess = &Exynos_VP9Dec_srcOutputBufferProcess; + pVideoDec->exynos_codec_dstInputProcess = &Exynos_VP9Dec_dstInputBufferProcess; + pVideoDec->exynos_codec_dstOutputProcess = &Exynos_VP9Dec_dstOutputBufferProcess; + + pVideoDec->exynos_codec_start = &VP9CodecStart; + pVideoDec->exynos_codec_stop = &VP9CodecStop; + pVideoDec->exynos_codec_bufferProcessRun = &VP9CodecOutputBufferProcessRun; + pVideoDec->exynos_codec_enqueueAllBuffer = &VP9CodecEnQueueAllBuffer; + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &Vp9CodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &Vp9CodecCheckResolution; + + pVideoDec->exynos_codec_updateExtraInfo = &VP9CodecUpdateExtraInfo; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pVp9Dec); + pVp9Dec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVp9Dec->hMFCVp9Handle.videoInstInfo.eCodecType = VIDEO_CODING_VP9; + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + pVp9Dec->hMFCVp9Handle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pVp9Dec->hMFCVp9Handle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + if (Exynos_Video_GetInstInfo(&(pVp9Dec->hMFCVp9Handle.videoInstInfo), VIDEO_TRUE /* dec */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pVp9Dec); + pVp9Dec = pVideoDec->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pVp9Dec->hMFCVp9Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport == VIDEO_TRUE) + pVideoDec->bDrvDPBManaging = OMX_TRUE; + else + pVideoDec->hRefHandle = Exynos_OSAL_RefCount_Create(); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec DrvDPBManaging(%d)", pExynosComponent, __FUNCTION__, + (pVp9Dec->hMFCVp9Handle.videoInstInfo.supportInfo.dec.bDrvDPBManageSupport)); + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-dec-compressed-color-format", (OMX_INDEXTYPE)OMX_IndexParamVideoCompressedColorFormat); +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit( + OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoDec->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)pVideoDec->hCodecHandle; + if (pVp9Dec != NULL) { + Exynos_OSAL_Free(pVp9Dec); + pVp9Dec = pVideoDec->hCodecHandle = NULL; + } + + ret = Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/dec/vp9/Exynos_OMX_Vp9dec.h b/openmax/component/video/dec/vp9/Exynos_OMX_Vp9dec.h new file mode 100644 index 0000000..e13df97 --- /dev/null +++ b/openmax/component/video/dec/vp9/Exynos_OMX_Vp9dec.h @@ -0,0 +1,97 @@ +/* + * + * Copyright 2014 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Vp9dec.h + * @brief + * @author Taehwan Kim (t_h.kim@samsung.com) + * SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2014.07.24 : Create + */ + +#ifndef EXYNOS_OMX_VP9_DEC_COMPONENT +#define EXYNOS_OMX_VP9_DEC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" +#include "ExynosVideoApi.h" + + +typedef struct _EXYNOS_MFC_VP9DEC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + OMX_S32 maxDPBNum; + + /* extra info which will be shared with renderer */ + ExynosVideoHdrInfo sHdrInfo; + OMX_U32 nActualFormat; + + ExynosVideoColorFormatType MFCOutputColorType; + ExynosVideoDecOps *pDecOps; + ExynosVideoDecBufferOps *pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 5 + OMX_VIDEO_VP9PROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_VP9LEVELTYPE maxLevel; +} EXYNOS_MFC_VP9DEC_HANDLE; + +typedef struct _EXYNOS_VP9DEC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_VP9TYPE VP9Component[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + + /* EXYNOS MFC Codec specific */ + EXYNOS_MFC_VP9DEC_HANDLE hMFCVp9Handle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_VP9DEC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName); +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit( + OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE VP9CodecDstSetup( + OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/dec/vp9/NOTICE b/openmax/component/video/dec/vp9/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/dec/vp9/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/dec/vp9/library_register.c b/openmax/component/video/dec/vp9/library_register.c new file mode 100644 index 0000000..7543742 --- /dev/null +++ b/openmax/component/video/dec/vp9/library_register.c @@ -0,0 +1,65 @@ +/* + * + * Copyright 2014 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author Taehwan Kim (t_h.kim@samsung.com) + * SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2014.07.24 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VP9_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register( + ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - video decoder VP9 */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_VP9_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_VP9_DEC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 2 - video decoder VP9 for DRM */ + Exynos_OSAL_Strcpy(ppExynosComponent[1]->componentName, EXYNOS_OMX_COMPONENT_VP9_DRM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[1]->roles[0], EXYNOS_OMX_COMPONENT_VP9_DEC_ROLE); + ppExynosComponent[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/openmax/component/video/dec/vp9/library_register.h b/openmax/component/video/dec/vp9/library_register.h new file mode 100644 index 0000000..c95b649 --- /dev/null +++ b/openmax/component/video/dec/vp9/library_register.h @@ -0,0 +1,63 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author Taehwan Kim (t_h.kim@samsung.com) + * SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2014.07.24 : Create + */ + +#ifndef EXYNOS_OMX_VP9_DEC_REG +#define EXYNOS_OMX_VP9_DEC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 2 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* VP9 */ +#ifndef USE_CUSTOM_COMPONENT_SUPPORT +#define EXYNOS_OMX_COMPONENT_VP9_DEC "OMX.Exynos.VP9.Decoder" +#define EXYNOS_OMX_COMPONENT_VP9_DRM_DEC "OMX.Exynos.VP9.Decoder.secure" +#else +#define EXYNOS_OMX_COMPONENT_VP9_DEC "OMX.Exynos.vp9.dec" +#define EXYNOS_OMX_COMPONENT_VP9_DRM_DEC "OMX.Exynos.vp9.dec.secure" +#endif + +#define EXYNOS_OMX_COMPONENT_VP9_DEC_ROLE "video_decoder.vp9" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register( + ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/enc/Android.mk b/openmax/component/video/enc/Android.mk new file mode 100644 index 0000000..80d558e --- /dev/null +++ b/openmax/component/video/enc/Android.mk @@ -0,0 +1,73 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + Exynos_OMX_VencControl.c \ + Exynos_OMX_Venc.c + +LOCAL_MODULE := libExynosOMX_Venc +LOCAL_ARM_MODE := arm +LOCAL_MODULE_TAGS := optional +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/enc \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(EXYNOS_OMX_SUPPORT_TUNNELING), true) +LOCAL_CFLAGS += -DTUNNELING_SUPPORT +endif + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_GSC_RGB_ENCODER), true) +LOCAL_CFLAGS += -DUSE_HW_CSC_GRALLOC_SOURCE +endif + +ifeq ($(BOARD_USE_FIMC_RGB_ENCODER), true) +LOCAL_CFLAGS += -DUSE_HW_CSC_GRALLOC_SOURCE +LOCAL_CFLAGS += -DUSE_FIMC_CSC +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_VIDEO_EXT_FOR_WFD_HDCP), true) +LOCAL_CFLAGS += -DUSE_VIDEO_EXT_FOR_WFD_HDCP +endif + +ifeq ($(BOARD_USE_SMALL_SECURE_MEMORY), true) +LOCAL_CFLAGS += -DUSE_SMALL_SECURE_MEMORY +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_STATIC_LIBRARIES := libVendorVideoApi +LOCAL_SHARED_LIBRARIES := liblog libcsc + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label +include $(BUILD_STATIC_LIBRARY) diff --git a/openmax/component/video/enc/Exynos_OMX_Venc.c b/openmax/component/video/enc/Exynos_OMX_Venc.c new file mode 100644 index 0000000..f9444c3 --- /dev/null +++ b/openmax/component/video/enc/Exynos_OMX_Venc.c @@ -0,0 +1,2272 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Venc.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include "Exynos_OMX_Macros.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OMX_Venc.h" +#include "Exynos_OMX_VencControl.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_ETC.h" +#include "ExynosVideoApi.h" +#include "csc.h" + +#include "Exynos_OSAL_Platform.h" + +#ifdef USE_ANDROID +#include +#include "exynos_format.h" +#endif + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VIDEO_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +void Exynos_UpdateFrameSize(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + OMX_U32 width = pInputPort->portDefinition.format.video.nFrameWidth; + OMX_U32 height = pInputPort->portDefinition.format.video.nFrameHeight; + + FunctionIn(); + + if (width && height) { + switch((int)pInputPort->portDefinition.format.video.eColorFormat) { + case OMX_COLOR_FormatYUV420Planar: + case OMX_COLOR_FormatYUV420SemiPlanar: + case OMX_SEC_COLOR_FormatNV12Tiled: + case OMX_SEC_COLOR_FormatYVU420Planar: + case OMX_SEC_COLOR_FormatNV21Linear: + pInputPort->portDefinition.nBufferSize = (ALIGN(width, 16) * ALIGN(height, 16) * 3) / 2; + break; + case OMX_COLOR_FormatYUV420Planar16: /* 10bit format */ + pInputPort->portDefinition.nBufferSize = (ALIGN(width * 2, 16) * ALIGN(height, 16) * 3) / 2; + break; + case OMX_COLOR_Format32bitARGB8888: + case OMX_COLOR_Format32BitRGBA8888: + case OMX_COLOR_Format32bitBGRA8888: + pInputPort->portDefinition.nBufferSize = ALIGN(width, 16) * ALIGN(height, 16) * 4; + + /* the video stream is in YUV domain */ + pOutputPort->portDefinition.format.video.nFrameWidth = width; + pOutputPort->portDefinition.format.video.nFrameHeight = height; + pOutputPort->portDefinition.nBufferSize = (ALIGN(width, 16) * ALIGN(height, 16) * 3) / 2; + break; +#ifdef USE_ANDROID + case OMX_COLOR_FormatAndroidOpaque: + pInputPort->portDefinition.nBufferSize = (ALIGN(width, 16) * ALIGN(height, 16) * 3) / 2; + break; +#endif + default: + pInputPort->portDefinition.nBufferSize = ALIGN(width, 16) * ALIGN(height, 16) * 2; + break; + } + } + + if ((pOutputPort->portDefinition.format.video.nFrameWidth != + pInputPort->portDefinition.format.video.nFrameWidth) || + (pOutputPort->portDefinition.format.video.nFrameHeight != + pInputPort->portDefinition.format.video.nFrameHeight)) { + + pOutputPort->portDefinition.format.video.nFrameWidth = + pInputPort->portDefinition.format.video.nFrameWidth; + pOutputPort->portDefinition.format.video.nFrameHeight = + pInputPort->portDefinition.format.video.nFrameHeight; + pOutputPort->portDefinition.format.video.nStride = + pInputPort->portDefinition.format.video.nStride; + pOutputPort->portDefinition.format.video.nSliceHeight = + pInputPort->portDefinition.format.video.nSliceHeight; + + pOutputPort->portDefinition.nBufferSize = ALIGN(pInputPort->portDefinition.nBufferSize, 512); + } + +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + pOutputPort->portDefinition.nBufferSize = Exynos_OSAL_GetOutBufferSize(width, height, pInputPort->portDefinition.nBufferSize); +#endif + +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) { + if (pOutputPort->portDefinition.nBufferSize > CUSTOM_LIMITED_DRM_OUTPUT_BUFFER_SIZE) { + pOutputPort->portDefinition.nBufferSize = CUSTOM_LIMITED_DRM_OUTPUT_BUFFER_SIZE; + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] use limited buffer size(%d) for output", + pExynosComponent, __FUNCTION__, pOutputPort->portDefinition.nBufferSize); + } + } +#endif + + if (pOutputPort->portDefinition.nBufferSize < MIN_CPB_SIZE) { + pOutputPort->portDefinition.nBufferSize = MIN_CPB_SIZE; + } + + FunctionOut(); + + return; +} + +void Exynos_Input_SetSupportFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_COLOR_FORMATTYPE ret = OMX_COLOR_FormatUnused; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if ((pVideoEnc == NULL) || (pInputPort == NULL)) + return ; + + if (pInputPort->supportFormat != NULL) { + OMX_BOOL ret = OMX_FALSE; + int nLastIndex = INPUT_PORT_SUPPORTFORMAT_DEFAULT_NUM; + int i; + + /* default supported formats */ + pInputPort->supportFormat[0] = OMX_COLOR_FormatYUV420Planar; + pInputPort->supportFormat[1] = OMX_COLOR_FormatYUV420SemiPlanar; + pInputPort->supportFormat[2] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV21Linear; + pInputPort->supportFormat[3] = OMX_COLOR_Format32bitARGB8888; + pInputPort->supportFormat[4] = (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888; +#ifdef USE_ANDROID + pInputPort->supportFormat[nLastIndex++] = OMX_COLOR_FormatAndroidOpaque; +#endif + + /* add extra formats, if It is supported by H/W. (CSC doesn't exist) */ + /* OMX_SEC_COLOR_FormatNV12Tiled */ + ret = pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled); + if (ret == OMX_TRUE) + pInputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled; + + /* OMX_SEC_COLOR_FormatYVU420Planar */ + ret = pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420Planar); + if (ret == OMX_TRUE) + pInputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420Planar; + + /* OMX_COLOR_Format32bitBGRA8888 */ + ret = pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, OMX_COLOR_Format32bitBGRA8888); + if (ret == OMX_TRUE) + pInputPort->supportFormat[nLastIndex++] = OMX_COLOR_Format32bitBGRA8888; + + /* OMX_COLOR_FormatYUV420Planar16 */ + ret = pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatYUV420Planar16); + if (ret == OMX_TRUE) + pInputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatYUV420Planar16; + + for (i = 0; i < nLastIndex; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] Supported Format[%d] : 0x%x", + pExynosComponent, __FUNCTION__, i, pInputPort->supportFormat[i]); + } + + pInputPort->supportFormat[nLastIndex] = OMX_COLOR_FormatUnused; + } + + return ; +} + +OMX_COLOR_FORMATTYPE Exynos_Input_GetActualColorFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_COLOR_FORMATTYPE ret = OMX_COLOR_FormatUnused; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; + +#ifdef USE_ANDROID + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) + eColorFormat = pVideoEnc->surfaceFormat; +#endif + + if (pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, eColorFormat) == OMX_TRUE) { + ret = eColorFormat; + goto EXIT; + } + + switch ((int)eColorFormat) { + case OMX_COLOR_FormatYUV420SemiPlanar: + case OMX_COLOR_FormatYUV420Planar: /* converted to NV12 using CSC */ + case OMX_COLOR_Format32bitARGB8888: /* converted to NV12 using CSC */ + case OMX_COLOR_Format32BitRGBA8888: /* converted to NV12 using CSC */ + ret = OMX_COLOR_FormatYUV420SemiPlanar; + break; + case OMX_SEC_COLOR_FormatNV21Linear: + case OMX_SEC_COLOR_FormatNV12Tiled: + ret = eColorFormat; + break; + case OMX_COLOR_FormatYUV420Planar16: /* TBD: convert 10bit to 8bit */ + default: + ret = OMX_COLOR_FormatUnused; + break; + } + +EXIT: + return ret; +} + +void Exynos_Free_CodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + CODEC_ENC_BUFFER **ppCodecBuffer = NULL; + + int nBufferCnt = 0, nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoEnc->pMFCEncInputBuffer[0]); + nBufferCnt = MFC_INPUT_BUFFER_NUM_MAX; + } else { + ppCodecBuffer = &(pVideoEnc->pMFCEncOutputBuffer[0]); + nBufferCnt = MFC_OUTPUT_BUFFER_NUM_MAX; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + for (i = 0; i < nBufferCnt; i++) { + if (ppCodecBuffer[i] != NULL) { + for (j = 0; j < nPlaneCnt; j++) { + if (ppCodecBuffer[i]->pVirAddr[j] != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] %s codec buffer[%d][%d] : %d", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + i, j, ppCodecBuffer[i]->fd[j]); + Exynos_OSAL_SharedMemory_Free(pVideoEnc->hSharedMemory, ppCodecBuffer[i]->pVirAddr[j]); + } + } + + Exynos_OSAL_Free(ppCodecBuffer[i]); + ppCodecBuffer[i] = NULL; + } + } + + FunctionOut(); +} + +OMX_ERRORTYPE Exynos_Allocate_CodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt, + unsigned int nAllocLen[MAX_BUFFER_PLANE]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + MEMORY_TYPE eMemoryType = CACHED_MEMORY; + CODEC_ENC_BUFFER **ppCodecBuffer = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoEnc->pMFCEncInputBuffer[0]); + } else { + ppCodecBuffer = &(pVideoEnc->pMFCEncOutputBuffer[0]); +#ifdef USE_CSC_HW + eMemoryType = NORMAL_MEMORY; +#endif + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + eMemoryType = SECURE_MEMORY; + + for (i = 0; i < nBufferCnt; i++) { + ppCodecBuffer[i] = (CODEC_ENC_BUFFER *)Exynos_OSAL_Malloc(sizeof(CODEC_ENC_BUFFER)); + if (ppCodecBuffer[i] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(ppCodecBuffer[i], 0, sizeof(CODEC_ENC_BUFFER)); + + for (j = 0; j < nPlaneCnt; j++) { + ppCodecBuffer[i]->pVirAddr[j] = + (void *)Exynos_OSAL_SharedMemory_Alloc(pVideoEnc->hSharedMemory, nAllocLen[j], eMemoryType); + if (ppCodecBuffer[i]->pVirAddr[j] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Alloc for %s codec buffer", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ppCodecBuffer[i]->fd[j] = + Exynos_OSAL_SharedMemory_VirtToION(pVideoEnc->hSharedMemory, ppCodecBuffer[i]->pVirAddr[j]); + ppCodecBuffer[i]->bufferSize[j] = nAllocLen[j]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s codec buffer[%d][%d] : %d / size(%d)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + i, j, ppCodecBuffer[i]->fd[j], ppCodecBuffer[i]->bufferSize[j]); + } + + ppCodecBuffer[i]->dataSize = 0; + } + + return OMX_ErrorNone; + +EXIT: + Exynos_Free_CodecBuffers(pOMXComponent, nPortIndex); + + FunctionOut(); + + return ret; +} + +OMX_BOOL Exynos_Check_BufferProcess_State(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex) +{ + OMX_BOOL ret = OMX_FALSE; + + if ((pExynosComponent == NULL) || + (pExynosComponent->pExynosPort == NULL)) + return OMX_FALSE; + + if ((pExynosComponent->currentState == OMX_StateExecuting) && + ((pExynosComponent->pExynosPort[nPortIndex].portState == EXYNOS_OMX_PortStateIdle) || + (pExynosComponent->pExynosPort[nPortIndex].portState == EXYNOS_OMX_PortStateDisabling)) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateIdleToExecuting)) { + ret = OMX_TRUE; + } else { + ret = OMX_FALSE; + } + + return ret; +} + +OMX_ERRORTYPE Exynos_ResetAllPortConfig(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + /* Input port */ + pInputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pInputPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pInputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pInputPort->portDefinition.format.video.nSliceHeight = 0; + pInputPort->portDefinition.format.video.pNativeRender = 0; + pInputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pInputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + + pInputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + pInputPort->portDefinition.bEnabled = OMX_TRUE; + + pInputPort->bufferProcessType = BUFFER_COPY; + pInputPort->portWayType = WAY2_PORT; + Exynos_SetPlaneToPort(pInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + Exynos_ResetImgCropInfo(pOMXComponent, INPUT_PORT_INDEX); + + /* Output port */ + pOutputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pOutputPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pOutputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pOutputPort->portDefinition.format.video.nSliceHeight = 0; + pOutputPort->portDefinition.format.video.pNativeRender = 0; + pOutputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pOutputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + + pOutputPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM; + pOutputPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM; + pOutputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pOutputPort->portDefinition.bEnabled = OMX_TRUE; + + pOutputPort->bufferProcessType = BUFFER_SHARE; + pOutputPort->portWayType = WAY2_PORT; + pOutputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(OMX_COLOR_FormatYUV420Planar, pOutputPort->ePlaneType)); + Exynos_ResetImgCropInfo(pOMXComponent, OUTPUT_PORT_INDEX); + + /* remove a configuration command that is in piled up */ + while (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + OMX_PTR pDynamicConfigCMD = NULL; + pDynamicConfigCMD = (OMX_PTR)Exynos_OSAL_Dequeue(&pExynosComponent->dynamicConfigQ); + Exynos_OSAL_Free(pDynamicConfigCMD); + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_CodecBufferToData( + CODEC_ENC_BUFFER *pCodecBuffer, + EXYNOS_OMX_DATA *pData, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + int i; + + if (nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pData->allocSize = 0; + pData->usedDataLen = 0; + pData->nFlags = 0; + pData->timeStamp = 0; + pData->pPrivate = pCodecBuffer; + pData->bufferHeader = NULL; + + for (i = 0; i < MAX_BUFFER_PLANE; i++) { + pData->buffer.addr[i] = pCodecBuffer->pVirAddr[i]; + pData->buffer.fd[i] = pCodecBuffer->fd[i]; + + pData->allocSize += pCodecBuffer->bufferSize[i]; + } + + pData->dataLen = 0; + pData->remainDataLen = 0; + +EXIT: + return ret; +} + +void Exynos_Wait_ProcessPause(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosOMXPort = NULL; + + FunctionIn(); + + exynosOMXPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (((pExynosComponent->currentState == OMX_StatePause) || + (pExynosComponent->currentState == OMX_StateIdle) || + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle) || + (pExynosComponent->transientState == EXYNOS_OMX_TransStateExecutingToIdle)) && + (pExynosComponent->transientState != EXYNOS_OMX_TransStateIdleToLoaded) && + (!CHECK_PORT_BEING_FLUSHED(exynosOMXPort))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port -> pause : state(0x%x), transient state(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosComponent->transientState); + Exynos_OSAL_SignalWait(pExynosComponent->pExynosPort[nPortIndex].pauseEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port -> resume : state(0x%x), transient state(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosComponent->transientState); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pExynosComponent->pExynosPort[nPortIndex].pauseEvent); + } + +EXIT: + FunctionOut(); + + return; +} + +OMX_BOOL Exynos_CSC_InputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *pInputUseBuffer = &pInputPort->way.port2WayDataBuffer.inputDataBuffer; + CODEC_ENC_BUFFER *pCodecInputBuffer = (CODEC_ENC_BUFFER *)pSrcInputData->pPrivate; + OMX_COLOR_FORMATTYPE eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; + OMX_COLOR_FORMATTYPE eSrcColorFormat = OMX_COLOR_FormatUnused; + + void *pInputBuf = (void *)pInputUseBuffer->bufferHeader->pBuffer; + void *pSrcBuf[MAX_BUFFER_PLANE] = { NULL, }; + void *pDstBuf[MAX_BUFFER_PLANE] = { NULL, }; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + CSC_MEMTYPE csc_memType = CSC_MEMORY_USERPTR; + CSC_METHOD csc_method = CSC_METHOD_SW; + CSC_ERRORCODE csc_ret = CSC_ErrorNone; + unsigned int csc_src_cacheable = 1; + unsigned int csc_dst_cacheable = 1; + + EXYNOS_OMX_IMG_INFO srcImgInfo, dstImgInfo; + OMX_S32 nTargetWidth, nTargetHeight; + int nDstAlignment = 0; + int i, nPlaneCnt; + OMX_BOOL bVerticalFlip = OMX_FALSE; + OMX_BOOL bHorizontalFlip = OMX_FALSE; + + FunctionIn(); + + + eSrcColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + /* choose csc method */ + csc_get_method(pVideoEnc->csc_handle, &csc_method); + + if (csc_method == CSC_METHOD_SW) { + /* 1. color format is supported by MFC */ + if (eColorFormat == eSrcColorFormat) { + csc_memType = CSC_MEMORY_MFC; /* add padding data, if width is not satisfied with h/w alignment */ + csc_method = CSC_METHOD_SW; + } + + /* 2. blur filtering/rotation/cropping/positioning/mirror are supported by only H/W */ + if ((pExynosComponent->bUseImgCrop == OMX_TRUE) || + (pVideoEnc->bUseBlurFilter == OMX_TRUE) || + (pVideoEnc->eRotationType != ROTATE_0) || + (pVideoEnc->eMirrorType != OMX_MirrorNone)) { + csc_ret = csc_set_method(pVideoEnc->csc_handle, CSC_METHOD_HW); + if (csc_ret != CSC_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] csc_set_method(CSC_METHOD_HW) for blur/rotation is failed", pExynosComponent, __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + + csc_memType = CSC_MEMORY_DMABUF; + csc_method = CSC_METHOD_HW; + csc_src_cacheable = 0; + csc_dst_cacheable = 0; + } + + /* 3. forcefully want to use H/W */ + if (pInputPort->eMetaDataType != METADATA_TYPE_DISABLED) { +#ifdef USE_HW_CSC_GRALLOC_SOURCE + if (pInputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) { +#ifdef USE_FIMC_CSC + if (pVideoEnc->surfaceFormat != (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888) /* FIMC doesn't support RGBA format */ +#endif // USE_FIMC_CSC + { + csc_ret = csc_set_method(pVideoEnc->csc_handle, CSC_METHOD_HW); + if (csc_ret != CSC_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] csc_set_method(CSC_METHOD_HW) for gralloc source is failed", pExynosComponent, __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + + csc_memType = CSC_MEMORY_DMABUF; + csc_method = CSC_METHOD_HW; + csc_src_cacheable = 0; + csc_dst_cacheable = 0; + } + } +#endif // USE_HW_CSC_GRALLOC_SOURCE + } + } else { + csc_memType = CSC_MEMORY_DMABUF; + csc_src_cacheable = 0; + csc_dst_cacheable = 0; + } + + /******************/ + /* get image info */ + /******************/ + /* 1. SRC : OMX INPUT */ + srcImgInfo.nStride = pInputPort->portDefinition.format.video.nFrameWidth; + srcImgInfo.nSliceHeight = pInputPort->portDefinition.format.video.nFrameHeight; + srcImgInfo.nImageWidth = pInputPort->portDefinition.format.video.nFrameWidth; + srcImgInfo.nImageHeight = pInputPort->portDefinition.format.video.nFrameHeight; + if (pInputPort->bUseImgCrop[IMG_CROP_INPUT_PORT] == OMX_FALSE) { + srcImgInfo.nLeft = 0; + srcImgInfo.nTop = 0; + srcImgInfo.nWidth = pInputPort->portDefinition.format.video.nFrameWidth; + srcImgInfo.nHeight = pInputPort->portDefinition.format.video.nFrameHeight; + } else { + srcImgInfo.nLeft = pInputPort->cropRectangle[IMG_CROP_INPUT_PORT].nLeft; + srcImgInfo.nTop = pInputPort->cropRectangle[IMG_CROP_INPUT_PORT].nTop; + srcImgInfo.nWidth = pInputPort->cropRectangle[IMG_CROP_INPUT_PORT].nWidth; + srcImgInfo.nHeight = pInputPort->cropRectangle[IMG_CROP_INPUT_PORT].nHeight; + } + + /* 2. DST : MFC INPUT */ + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + /* use changing output resolution */ + nTargetWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nTargetHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nTargetWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nTargetHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + + switch (pVideoEnc->eRotationType) { + case ROTATE_90: + dstImgInfo.nStride = ALIGN(nTargetHeight, 16); + dstImgInfo.nSliceHeight = nTargetWidth; + dstImgInfo.nImageWidth = nTargetHeight; + dstImgInfo.nImageHeight = nTargetWidth; + + if (pInputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_FALSE) { + dstImgInfo.nLeft = 0; + dstImgInfo.nTop = 0; + dstImgInfo.nWidth = nTargetHeight; + dstImgInfo.nHeight = nTargetWidth; + } else { + dstImgInfo.nLeft = nTargetHeight + - pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nTop + - pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + dstImgInfo.nTop = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nLeft; + dstImgInfo.nWidth = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + dstImgInfo.nHeight = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + } + break; + case ROTATE_180: + dstImgInfo.nStride = ALIGN(nTargetWidth, 16); + dstImgInfo.nSliceHeight = nTargetHeight; + dstImgInfo.nImageWidth = nTargetWidth; + dstImgInfo.nImageHeight = nTargetHeight; + + if (pInputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_FALSE) { + dstImgInfo.nLeft = 0; + dstImgInfo.nTop = 0; + dstImgInfo.nWidth = nTargetWidth; + dstImgInfo.nHeight = nTargetHeight; + } else { + dstImgInfo.nLeft = pInputPort->portDefinition.format.video.nFrameWidth + - pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nLeft + - pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + dstImgInfo.nTop = nTargetHeight + - pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nTop + - pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + dstImgInfo.nWidth = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + dstImgInfo.nHeight = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } + break; + case ROTATE_270: + dstImgInfo.nStride = ALIGN(nTargetHeight, 16); + dstImgInfo.nSliceHeight = nTargetWidth; + dstImgInfo.nImageWidth = nTargetHeight; + dstImgInfo.nImageHeight = nTargetWidth; + + if (pInputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_FALSE) { + dstImgInfo.nLeft = 0; + dstImgInfo.nTop = 0; + dstImgInfo.nWidth = nTargetHeight; + dstImgInfo.nHeight = nTargetWidth; + } else { + dstImgInfo.nLeft = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nTop; + dstImgInfo.nTop = pInputPort->portDefinition.format.video.nFrameWidth + - pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nLeft + - pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + dstImgInfo.nWidth = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + dstImgInfo.nHeight = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + } + break; + case ROTATE_0: + default: + dstImgInfo.nStride = ALIGN(nTargetWidth, 16); + dstImgInfo.nSliceHeight = nTargetHeight; + dstImgInfo.nImageWidth = nTargetWidth; + dstImgInfo.nImageHeight = nTargetHeight; + + if (pInputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_FALSE) { + dstImgInfo.nLeft = 0; + dstImgInfo.nTop = 0; + dstImgInfo.nWidth = nTargetWidth; + dstImgInfo.nHeight = nTargetHeight; + } else { + dstImgInfo.nLeft = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nLeft; + dstImgInfo.nTop = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nTop; + dstImgInfo.nWidth = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + dstImgInfo.nHeight = pInputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } + break; + } + + if ((pVideoEnc->eMirrorType == OMX_MirrorVertical) || + (pVideoEnc->eMirrorType == OMX_MirrorBoth)) + bVerticalFlip = OMX_TRUE; + if ((pVideoEnc->eMirrorType == OMX_MirrorHorizontal) || + (pVideoEnc->eMirrorType == OMX_MirrorBoth)) + bHorizontalFlip = OMX_TRUE; + + if ((eSrcColorFormat == OMX_SEC_COLOR_FormatS10bitYUV420SemiPlanar) || + (eSrcColorFormat == OMX_SEC_COLOR_FormatS10bitYVU420SemiPlanar)) { + dstImgInfo.nStride = ALIGN(dstImgInfo.nStride, S10B_FORMAT_8B_ALIGNMENT); + } + + /*******************/ + /* get buffer info */ + /*******************/ + /* 1. SRC : OMX INPUT */ + if (pInputPort->eMetaDataType != METADATA_TYPE_DISABLED) { + /* 1. meta data is enabled + * 1) blur or rotation is used + * * blur, rotation is supported by HW. + * 2) format is not supported at HW codec + * needs CSC(Color-Space-Conversion). + */ + + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + OMX_ERRORTYPE err = OMX_ErrorNone; + + if (pInputPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) { + /* METADATA_TYPE_GRAPHIC */ + EXYNOS_OMX_LOCK_RANGE range; + OMX_U32 stride = 0; + + range.nWidth = srcImgInfo.nStride; + range.nHeight = srcImgInfo.nSliceHeight; + range.eColorFormat = eColorFormat; /* OMX_COLOR_FormatAndroidOpaque */ + stride = range.nWidth; + + err = Exynos_OSAL_LockMetaData(pInputBuf, + range, + &stride, &bufferInfo, + pInputPort->eMetaDataType); + if (err != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to Exynos_OSAL_LockMetaData (err:0x%x)", + pExynosComponent, __FUNCTION__, err); + goto EXIT; + } + + srcImgInfo.nStride = stride; + + if (csc_method == CSC_METHOD_HW) { + pSrcBuf[0] = (void *)bufferInfo.fd[0]; + pSrcBuf[1] = (void *)bufferInfo.fd[1]; + pSrcBuf[2] = (void *)bufferInfo.fd[2]; + } else { + pSrcBuf[0] = (void *)bufferInfo.addr[0]; + pSrcBuf[1] = (void *)bufferInfo.addr[1]; + pSrcBuf[2] = (void *)bufferInfo.addr[2]; + } + } else { + /* METADATA_TYPE_DATA or METADATA_TYPE_HANDLE */ + err = Exynos_OSAL_GetInfoFromMetaData(pInputBuf, &bufferInfo, pInputPort->eMetaDataType); + if (err != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to Exynos_OSAL_GetInfoFromMetaData (err:0x%x)", + pExynosComponent, __FUNCTION__, err); + ret = OMX_FALSE; + goto EXIT; + } + + if (csc_method == CSC_METHOD_HW) { + pSrcBuf[0] = (void *)bufferInfo.fd[0]; + pSrcBuf[1] = (void *)bufferInfo.fd[1]; + pSrcBuf[2] = (void *)bufferInfo.fd[2]; + } else { + Exynos_OSAL_GetPlaneSize(eSrcColorFormat, pInputPort->ePlaneType, srcImgInfo.nStride, srcImgInfo.nSliceHeight, nDataLen, nAllocLen); + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + + /* get virtual address */ + for (i = 0; i < nPlaneCnt; i++) { + if (bufferInfo.fd[i] != 0) { + pSrcBuf[i] = Exynos_OSAL_SharedMemory_IONToVirt(pVideoEnc->hSharedMemory, bufferInfo.fd[i]); + + if(pSrcBuf[i] == NULL) /* if there isn't addr, try to map using fd (in case of external allocation) */ + pSrcBuf[i] = Exynos_OSAL_SharedMemory_Map(pVideoEnc->hSharedMemory, nAllocLen[i], bufferInfo.fd[i]); + + if (pSrcBuf[i] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to haredMemory_Map(%d) is failed", + pExynosComponent, __FUNCTION__, bufferInfo.fd[i]); + ret = OMX_FALSE; + goto EXIT; + } + } + } + } + } + } else { + /* 2. meta data is not enabled (user application format) + * + * 1) HW codec cound't handle user application format + * separates to each color plan and adds the padding data if it is needed. + * 2) format is not supported at HW codec + * needs CSC(Color-Space-Conversion). + */ + if (csc_method == CSC_METHOD_HW) { + pSrcBuf[0] = (void *)Exynos_OSAL_SharedMemory_VirtToION(pVideoEnc->hSharedMemory, (char *)pInputBuf); + pSrcBuf[1] = NULL; + pSrcBuf[2] = NULL; + } else { + Exynos_OSAL_GetPlaneSize(eColorFormat, PLANE_SINGLE_USER, srcImgInfo.nStride, srcImgInfo.nSliceHeight, nDataLen, nAllocLen); + pSrcBuf[0] = (void *)((char *)pInputBuf); + pSrcBuf[1] = (void *)((char *)pInputBuf + nDataLen[0]); + pSrcBuf[2] = (void *)((char *)pInputBuf + nDataLen[0] + nDataLen[1]); + } + } + + /* 2. DST : MFC INPUT */ + if (csc_method == CSC_METHOD_HW) { + pDstBuf[0] = (void *)pSrcInputData->buffer.fd[0]; + pDstBuf[1] = (void *)pSrcInputData->buffer.fd[1]; + pDstBuf[2] = (void *)pSrcInputData->buffer.fd[2]; + } else { + if (pInputPort->ePlaneType == PLANE_SINGLE) { + /* single-FD. only Y addr is valid */ + int nPlaneCnt = Exynos_OSAL_GetPlaneCount(eSrcColorFormat, PLANE_MULTIPLE); + + if (nPlaneCnt == 2) { + /* Semi-Planar : interleaved */ + pDstBuf[0] = pSrcInputData->buffer.addr[0]; + + pDstBuf[1] = (void *)(((char *)pDstBuf[0]) + GET_UV_OFFSET(dstImgInfo.nImageWidth, dstImgInfo.nImageHeight)); + } else if (nPlaneCnt == 3) { + /* Planar */ + pDstBuf[0] = pSrcInputData->buffer.addr[0]; + + pDstBuf[1] = (void *)(((char *)pDstBuf[0]) + GET_CB_OFFSET(dstImgInfo.nImageWidth, dstImgInfo.nImageHeight)); + pDstBuf[2] = (void *)(((char *)pDstBuf[0]) + GET_CR_OFFSET(dstImgInfo.nImageWidth, dstImgInfo.nImageHeight)); + } + } else { + /* multi-FD */ + pDstBuf[0] = pSrcInputData->buffer.addr[0]; + pDstBuf[1] = pSrcInputData->buffer.addr[1]; + pDstBuf[2] = pSrcInputData->buffer.addr[2]; + } + } + Exynos_OSAL_GetPlaneSize(eSrcColorFormat, pInputPort->ePlaneType, dstImgInfo.nStride, dstImgInfo.nSliceHeight, nDataLen, nAllocLen); + pCodecInputBuffer->dataSize = 0; + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + for (i = 0; i < nPlaneCnt; i++) + pCodecInputBuffer->dataSize += nDataLen[i]; + + + /**************************/ + /* [CSC] setup image info */ + /**************************/ + if (pVideoEnc->csc_set_format == OMX_FALSE) { + /********************/ + /* get color format */ + /********************/ + unsigned int csc_src_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)eColorFormat, PLANE_SINGLE_USER); + unsigned int csc_dst_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)eSrcColorFormat, pInputPort->ePlaneType); + + int colorspace = CSC_EQ_COLORSPACE_SMPTE170M; + int range = (pInputPort->ColorAspects.nRangeType == RANGE_FULL)? CSC_EQ_RANGE_FULL:CSC_EQ_RANGE_NARROW; + + EXYNOS_OMX_VIDEO_COLORASPECTS colorAspects; + colorAspects.nRangeType = (range == CSC_EQ_RANGE_FULL)? RANGE_FULL:RANGE_LIMITED; + + if (pInputPort->eMetaDataType != METADATA_TYPE_DISABLED) { + if (pInputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) + csc_src_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)pVideoEnc->surfaceFormat, pInputPort->ePlaneType); + else + csc_src_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)eColorFormat, pInputPort->ePlaneType); + } + + colorspace = Exynos_OSAL_DataSpaceToColorSpace(pInputPort->ColorAspects.nDataSpace, csc_src_color_format); + Exynos_OSAL_ColorSpaceToColorAspects(colorspace, &colorAspects); + Exynos_OSAL_GetColorAspectsForBitstream(&colorAspects, &(pOutputPort->ColorAspects)); + + csc_set_src_format( + pVideoEnc->csc_handle, /* handle */ + srcImgInfo.nStride, /* width */ + srcImgInfo.nSliceHeight, /* height */ + srcImgInfo.nLeft, /* crop_left */ + srcImgInfo.nTop, /* crop_top */ + srcImgInfo.nWidth, /* crop_width */ + srcImgInfo.nHeight, /* crop_height */ + csc_src_color_format, /* color_format */ + csc_src_cacheable); /* cacheable */ + + csc_set_dst_format( + pVideoEnc->csc_handle, /* handle */ + dstImgInfo.nStride, /* width */ + dstImgInfo.nSliceHeight, /* height */ + dstImgInfo.nLeft, /* crop_left */ + dstImgInfo.nTop, /* crop_top */ + dstImgInfo.nWidth, /* crop_width */ + dstImgInfo.nHeight, /* crop_height */ + csc_dst_color_format, /* color_format */ + csc_dst_cacheable); /* cacheable */ + + csc_set_eq_property( + pVideoEnc->csc_handle, /* handle */ + CSC_EQ_MODE_USER, /* user select */ + range, /* Limited, Full */ + colorspace); /* BT.601, BT.709, BT.2020 */ + + pVideoEnc->csc_set_format = OMX_TRUE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s CSC(%x) %s %s/ [SRC] resol(%d/%d), rect(%d/%d/%d/%d), format(0x%x) -> [DST] resol(%d/%d), rect(%d/%d/%d/%d), format(0x%x), range(0x%x), colorspace(0x%x)", + pExynosComponent, __FUNCTION__, + (csc_method == CSC_METHOD_SW)? "SW":"HW", csc_memType, + (pVideoEnc->eRotationType != ROTATE_0)? "with rotation":"", + (pVideoEnc->eMirrorType != OMX_MirrorNone) ? "with Flip":"", + srcImgInfo.nStride, srcImgInfo.nSliceHeight, + srcImgInfo.nLeft, srcImgInfo.nTop, srcImgInfo.nWidth, srcImgInfo.nHeight, csc_src_color_format, + dstImgInfo.nStride, dstImgInfo.nSliceHeight, + dstImgInfo.nLeft, dstImgInfo.nTop, dstImgInfo.nWidth, dstImgInfo.nHeight, csc_dst_color_format, + range, colorspace); + } + + /********************************/ + /* [CSC] setup blur filter info */ + /********************************/ + if (pVideoEnc->bUseBlurFilter == OMX_TRUE) { + CSC_HW_FILTER filterType = CSC_FT_NONE; + + if (pVideoEnc->eBlurMode & BLUR_MODE_DOWNUP) { + switch (pVideoEnc->eBlurResol) { + case BLUR_RESOL_240: + filterType = CSC_FT_240; + break; + case BLUR_RESOL_480: + filterType = CSC_FT_480; + break; + case BLUR_RESOL_720: + filterType = CSC_FT_720; + break; + case BLUR_RESOL_960: + filterType = CSC_FT_960; + break; + case BLUR_RESOL_1080: + filterType = CSC_FT_1080; + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invliad eBlurResol(%d)", pExynosComponent, __FUNCTION__, pVideoEnc->eBlurResol); + ret = OMX_FALSE; + goto EXIT; + } + } + + if (pVideoEnc->eBlurMode & BLUR_MODE_COEFFICIENT) + filterType = CSC_FT_BLUR; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] blur filter is enabled : type(%x)", pExynosComponent, __FUNCTION__, filterType); + + csc_set_filter_property( + pVideoEnc->csc_handle, + filterType); + } + + /***************************/ + /* [CSC] setup buffer info */ + /***************************/ + csc_set_src_buffer( + pVideoEnc->csc_handle, /* handle */ + pSrcBuf, + csc_memType); + csc_set_dst_buffer( + pVideoEnc->csc_handle, /* handle */ + pDstBuf, + csc_memType); + + /*****************/ + /* [CSC] convert */ + /*****************/ + if ((pVideoEnc->eRotationType != ROTATE_0) || + (pVideoEnc->eMirrorType != OMX_MirrorNone)) + csc_ret = csc_convert_with_rotation(pVideoEnc->csc_handle, (int)pVideoEnc->eRotationType, bHorizontalFlip, bVerticalFlip); + else + csc_ret = csc_convert(pVideoEnc->csc_handle); + ret = (csc_ret != CSC_ErrorNone)? OMX_FALSE:OMX_TRUE; + + if (pInputPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) + Exynos_OSAL_UnlockMetaData(pInputBuf, pInputPort->eMetaDataType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_BOOL Exynos_Preprocessor_InputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *srcInputData) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *inputUseBuffer = &exynosInputPort->way.port2WayDataBuffer.inputDataBuffer; + OMX_U32 nFrameWidth = exynosInputPort->portDefinition.format.video.nFrameWidth; + OMX_U32 nFrameHeight = exynosInputPort->portDefinition.format.video.nFrameHeight; + OMX_COLOR_FORMATTYPE eColorFormat = exynosInputPort->portDefinition.format.video.eColorFormat; + + OMX_U32 copySize = 0; + + FunctionIn(); + + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + if ((srcInputData->buffer.addr[0] == NULL) || + (srcInputData->pPrivate == NULL)) { + ret = OMX_FALSE; + goto EXIT; + } + } + + if (inputUseBuffer->dataValid == OMX_TRUE) { + if (exynosInputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_Shared_BufferToData(exynosInputPort, inputUseBuffer, srcInputData); + + if (exynosInputPort->eMetaDataType != METADATA_TYPE_DISABLED) { + OMX_ERRORTYPE err = OMX_ErrorNone; + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + OMX_COLOR_FORMATTYPE inputColorFormat = OMX_COLOR_FormatUnused; + + int i = 0, nPlaneCnt = 0; + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + Exynos_OSAL_GetPlaneSize(inputColorFormat, exynosInputPort->ePlaneType, nFrameWidth, nFrameHeight, nDataLen, nAllocLen); + nPlaneCnt = Exynos_GetPlaneFromPort(exynosInputPort); + + if (inputUseBuffer->dataLen <= 0) { + /* input data is not valid */ + if (!(inputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS)) { + /* w/o EOS flag */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] dataLen is zero w/o EOS flag(0x%x). this buffer(%p) will be discarded", + pExynosComponent, __FUNCTION__, + inputUseBuffer->nFlags, inputUseBuffer->bufferHeader); + ret = OMX_FALSE; + goto EXIT; + } else { + /* with EOS flag + * makes a buffer for EOS handling needed at MFC Processing scheme. + */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] dataLen is zero with EOS flag(0x%x)", + pExynosComponent, __FUNCTION__, inputUseBuffer->nFlags); + for (i = 0; i < nPlaneCnt; i++) { + srcInputData->buffer.addr[i] = + (void *)Exynos_OSAL_SharedMemory_Alloc(pVideoEnc->hSharedMemory, nAllocLen[i], NORMAL_MEMORY); + srcInputData->buffer.fd[i] = + Exynos_OSAL_SharedMemory_VirtToION(pVideoEnc->hSharedMemory, srcInputData->buffer.addr[i]); + } + } + } else { + /* input data is valid */ +#ifdef USE_ANDROID + for (i = 0; i < nPlaneCnt; i++) { + if ((srcInputData->buffer.fd[i] != 0) && + (srcInputData->buffer.addr[i] == NULL)) { + srcInputData->buffer.addr[i] = + Exynos_OSAL_SharedMemory_IONToVirt(pVideoEnc->hSharedMemory, srcInputData->buffer.fd[i]); + if(srcInputData->buffer.addr[i] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] dynamically regist a buffer(fd[%u])", + pExynosComponent, __FUNCTION__, srcInputData->buffer.fd[i]); + srcInputData->buffer.addr[i] = + Exynos_OSAL_SharedMemory_Map(pVideoEnc->hSharedMemory, nAllocLen[i], srcInputData->buffer.fd[i]); + } + } + } +#endif + } + } + + /* reset dataBuffer */ + Exynos_ResetDataBuffer(inputUseBuffer); + + ret = OMX_TRUE; + } else if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + if (inputUseBuffer->remainDataLen == 0) { + inputUseBuffer->nFlags |= OMX_BUFFERFLAG_EOS; + copySize = 0; + } else { + copySize = inputUseBuffer->remainDataLen; + + if ((eColorFormat == OMX_COLOR_Format32bitARGB8888) || + (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888)) { + copySize = srcInputData->allocSize; + } + + if (exynosInputPort->eMetaDataType & METADATA_TYPE_DATA) + copySize = inputUseBuffer->allocSize; + } + + if (((srcInputData->allocSize) - (srcInputData->dataLen)) < copySize) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] codec buffer's remaining space(%d) is smaller than input data(%d)", + pExynosComponent, __FUNCTION__, + ((srcInputData->allocSize) - (srcInputData->dataLen)), copySize); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + ret = OMX_FALSE; + goto EXIT; + } + + if (copySize > 0) { + ret = Exynos_CSC_InputData(pOMXComponent, srcInputData); + if (ret != OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to CSC_InputData", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + ret = OMX_FALSE; + goto EXIT; + } + } + + inputUseBuffer->dataLen -= copySize; + inputUseBuffer->remainDataLen -= copySize; + inputUseBuffer->usedDataLen += copySize; + + srcInputData->dataLen += copySize; + srcInputData->remainDataLen += copySize; + + srcInputData->timeStamp = inputUseBuffer->timeStamp; + srcInputData->nFlags = inputUseBuffer->nFlags; + srcInputData->bufferHeader = inputUseBuffer->bufferHeader; + + /* return OMX buffer and reset dataBuffer */ + Exynos_InputBufferReturn(pOMXComponent, inputUseBuffer); + + ret = OMX_TRUE; + } + + if ((srcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + if (srcInputData->dataLen != 0) { + pExynosComponent->bBehaviorEOS = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] behavior EOS frame", pExynosComponent, __FUNCTION__); + } + } + + if ((pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) && + ((srcInputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG) != OMX_BUFFERFLAG_CODECCONFIG)) { + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_TRUE; + pExynosComponent->checkTimeStamp.startTimeStamp = srcInputData->timeStamp; + pExynosComponent->checkTimeStamp.nStartFlags = srcInputData->nFlags; + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame timestamp after seeking %lld us (%.2f secs)", + pExynosComponent, __FUNCTION__, srcInputData->timeStamp, (double)(srcInputData->timeStamp / 1E6)); + } + } + +EXIT: + + if (ret != OMX_TRUE) { + /* return OMX buffer and reset dataBuffer */ + Exynos_InputBufferReturn(pOMXComponent, inputUseBuffer); + } + + FunctionOut(); + + return ret; +} + +OMX_BOOL Exynos_Postprocess_OutputData(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *dstOutputData) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *outputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + + OMX_U32 copySize = 0; + + FunctionIn(); + + if (exynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if (Exynos_Shared_DataToBuffer(exynosOutputPort, outputUseBuffer, dstOutputData) == OMX_ErrorNone) + outputUseBuffer->dataValid = OMX_TRUE; + } + + if (outputUseBuffer->dataValid == OMX_TRUE) { + if (pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE) { + if (pExynosComponent->checkTimeStamp.startTimeStamp == dstOutputData->timeStamp) { + pExynosComponent->checkTimeStamp.startTimeStamp = RESET_TIMESTAMP_VAL; + pExynosComponent->checkTimeStamp.nStartFlags = 0x0; + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] drop frame after seeking(in: %lld vs out: %lld)", + pExynosComponent, __FUNCTION__, + pExynosComponent->checkTimeStamp.startTimeStamp, dstOutputData->timeStamp); + if (exynosOutputPort->bufferProcessType & BUFFER_SHARE) + Exynos_OMX_FillThisBufferAgain(pOMXComponent, outputUseBuffer->bufferHeader); + + ret = OMX_TRUE; + goto EXIT; + } + } else if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) { + ret = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] not set check timestamp after seeking", pExynosComponent, __FUNCTION__); + + if (exynosOutputPort->bufferProcessType & BUFFER_SHARE) + Exynos_OMX_FillThisBufferAgain(pOMXComponent, outputUseBuffer->bufferHeader); + + goto EXIT; + } + + if (exynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((dstOutputData->remainDataLen <= (outputUseBuffer->allocSize - outputUseBuffer->dataLen)) && + (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + copySize = dstOutputData->remainDataLen; + if (copySize > 0) { + Exynos_OSAL_Memcpy((outputUseBuffer->bufferHeader->pBuffer + outputUseBuffer->dataLen), + ((char *)dstOutputData->buffer.addr[0] + dstOutputData->usedDataLen), + copySize); + } + + outputUseBuffer->dataLen += copySize; + outputUseBuffer->remainDataLen += copySize; + outputUseBuffer->nFlags = dstOutputData->nFlags; + outputUseBuffer->timeStamp = dstOutputData->timeStamp; + + ret = OMX_TRUE; + + if ((outputUseBuffer->remainDataLen > 0) || + (outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) || + (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer); + } + } else if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) { + outputUseBuffer->dataLen = 0; + outputUseBuffer->remainDataLen = 0; + outputUseBuffer->nFlags = dstOutputData->nFlags; + outputUseBuffer->timeStamp = dstOutputData->timeStamp; + Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] codec buffer's remaining space(%d) is smaller than output data(%d)", + pExynosComponent, __FUNCTION__, + (outputUseBuffer->allocSize - outputUseBuffer->dataLen), dstOutputData->remainDataLen); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + ret = OMX_FALSE; + } + } else if (exynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((outputUseBuffer->remainDataLen > 0) || + (outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) || + (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + + Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer); + } else { + Exynos_OMX_FillThisBufferAgain(pOMXComponent, outputUseBuffer->bufferHeader); + Exynos_ResetDataBuffer(outputUseBuffer); + } + } + } else { + ret = OMX_FALSE; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ExtensionSetup(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *srcInputUseBuffer = &pInputPort->way.port2WayDataBuffer.inputDataBuffer; + OMX_COLOR_FORMATTYPE eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; + OMX_COLOR_FORMATTYPE eActualFormat = OMX_COLOR_FormatUnused; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + int i = 0; + + if (pInputPort->eMetaDataType != METADATA_TYPE_DISABLED) { + if ((srcInputUseBuffer->dataLen == 0) && + (srcInputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS)) { + /* In this case, the metadata is not valid. + * sets dummy info in order to return EOS flag at output port through FBD. + * IL client should do stop sequence. + */ + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] dataLen is zero with EOS flag(0x%x) at first input", + pExynosComponent, __FUNCTION__, srcInputUseBuffer->nFlags); + + if (pInputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) { + pVideoEnc->surfaceFormat = OMX_COLOR_FormatYUV420SemiPlanar; + pInputPort->bufferProcessType = BUFFER_SHARE; + Exynos_SetPlaneToPort(pInputPort, Exynos_OSAL_GetPlaneCount(pVideoEnc->surfaceFormat, pInputPort->ePlaneType)); + } else { + Exynos_SetPlaneToPort(pInputPort, Exynos_OSAL_GetPlaneCount(eColorFormat, pInputPort->ePlaneType)); + } + + goto EXIT; + } else { + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + + ret = Exynos_OSAL_GetInfoFromMetaData(srcInputUseBuffer->bufferHeader->pBuffer, + &bufferInfo, pInputPort->eMetaDataType); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to Exynos_OSAL_GetInfoFromMetaData (err:0x%x)", + pExynosComponent, __FUNCTION__, ret); + goto EXIT; + } + + if (pInputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) { + pVideoEnc->surfaceFormat = bufferInfo.eColorFormat; + eActualFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + if (eActualFormat == OMX_COLOR_FormatUnused) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] unsupported color format : ANB color is 0x%x", + pExynosComponent, __FUNCTION__, pVideoEnc->surfaceFormat); + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + if ((pVideoEnc->surfaceFormat == eActualFormat) && + !(pInputPort->bufferProcessType & BUFFER_COPY_FORCE)) { + pInputPort->bufferProcessType = BUFFER_SHARE; + Exynos_SetPlaneToPort(pInputPort, Exynos_OSAL_GetPlaneCount(pVideoEnc->surfaceFormat, pInputPort->ePlaneType)); + } else { + pInputPort->bufferProcessType = BUFFER_COPY; + } + } else { + Exynos_SetPlaneToPort(pInputPort, Exynos_OSAL_GetPlaneCount(eColorFormat, pInputPort->ePlaneType)); + } + } + } + + /* forcefully have to use BUFFER_COPY mode, if blur filter is used or rotation is needed or image flip is needed*/ + if ((pVideoEnc->bUseBlurFilter == OMX_TRUE) || + (pVideoEnc->eRotationType != ROTATE_0) || + (pVideoEnc->eMirrorType != OMX_MirrorNone)) { + pInputPort->bufferProcessType = BUFFER_COPY; + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] %s %s %s: enabled", pExynosComponent, __FUNCTION__, + (pVideoEnc->bUseBlurFilter == OMX_TRUE)? "blur filter":"", + (pVideoEnc->eRotationType != ROTATE_0)? "rotation":"", + (pVideoEnc->eMirrorType != OMX_MirrorNone)? "image flip":""); + } + + if ((pInputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) { + OMX_U32 nFrameWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + OMX_U32 nFrameHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + + if ((pVideoEnc->eRotationType == ROTATE_90) || + (pVideoEnc->eRotationType == ROTATE_270)) { + nFrameWidth = pOutputPort->portDefinition.format.video.nFrameHeight; + nFrameHeight = pOutputPort->portDefinition.format.video.nFrameWidth; + } + + if (pVideoEnc->bEncDRC == OMX_TRUE) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + pVideoEnc->bEncDRC = OMX_FALSE; + } + + eActualFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + if (eActualFormat == OMX_COLOR_FormatUnused) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] unsupported color format : 0x%x", pExynosComponent, __FUNCTION__, eActualFormat); + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + Exynos_SetPlaneToPort(pInputPort, Exynos_OSAL_GetPlaneCount(eActualFormat, pInputPort->ePlaneType)); + Exynos_OSAL_GetPlaneSize(eActualFormat, pInputPort->ePlaneType, nFrameWidth, nFrameHeight, nDataLen, nAllocLen); + + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX, MFC_INPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Allocate_CodecBuffers", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) + Exynos_CodecBufferEnqueue(pExynosComponent, INPUT_PORT_INDEX, pVideoEnc->pMFCEncInputBuffer[i]); + } else if (pInputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + +EXIT: + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eActualFormat: 0x%x, eColorFormat: 0x%x, eBufferColorFormat: 0x%x, bufferProcessType: 0x%x", + pExynosComponent, __FUNCTION__, + eActualFormat, eColorFormat, pVideoEnc->surfaceFormat, pInputPort->bufferProcessType); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SrcInputBufferProcess(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *srcInputUseBuffer = &exynosInputPort->way.port2WayDataBuffer.inputDataBuffer; + EXYNOS_OMX_DATA *pSrcInputData = &exynosInputPort->processData; + + OMX_BOOL bCheckInputData = OMX_FALSE; + + FunctionIn(); + + while (!pVideoEnc->bExitBufferProcessThread) { + Exynos_OSAL_SleepMillisec(0); + Exynos_Wait_ProcessPause(pExynosComponent, INPUT_PORT_INDEX); + if ((exynosInputPort->semWaitPortEnable[INPUT_WAY_INDEX] != NULL) && + ((CHECK_PORT_BEING_DISABLED(exynosInputPort)) || + (!CHECK_PORT_ENABLED(exynosInputPort)))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> wait(port enable)", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(exynosInputPort->semWaitPortEnable[INPUT_WAY_INDEX]); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> post(port enable)", pExynosComponent, __FUNCTION__); + continue; + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) && + (!pVideoEnc->bExitBufferProcessThread)) { + Exynos_OSAL_SleepMillisec(0); + + if (CHECK_PORT_BEING_FLUSHED(exynosInputPort)) + break; + + Exynos_OSAL_MutexLock(srcInputUseBuffer->bufferMutex); + if (pVideoEnc->bFirstInput == OMX_FALSE) { + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + OMX_PTR codecBuffer; + if ((pSrcInputData->buffer.addr[0] == NULL) || + (pSrcInputData->pPrivate == NULL)) { + Exynos_CodecBufferDequeue(pExynosComponent, INPUT_PORT_INDEX, &codecBuffer); + if (pVideoEnc->bExitBufferProcessThread) { + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + goto EXIT; + } + + if (codecBuffer != NULL) { + Exynos_CodecBufferToData(codecBuffer, pSrcInputData, INPUT_PORT_INDEX); + } + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + break; + } + } + + if (srcInputUseBuffer->dataValid == OMX_TRUE) { + bCheckInputData = Exynos_Preprocessor_InputData(pOMXComponent, pSrcInputData); + } else { + bCheckInputData = OMX_FALSE; + } + } + + if ((bCheckInputData == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(exynosInputPort))) { + ret = Exynos_InputBufferGetQueue(pExynosComponent); + if (pVideoEnc->bExitBufferProcessThread) { + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + goto EXIT; + } + + if (ret != OMX_ErrorNone) { + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + break; + } + + if ((pVideoEnc->bFirstInput == OMX_TRUE) && + (!CHECK_PORT_BEING_FLUSHED(exynosInputPort))) { + ret = Exynos_OMX_ExtensionSetup(hComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + (*(pExynosComponent->pCallbacks->EventHandler)) (pOMXComponent, + pExynosComponent->callbackData, + (OMX_U32)OMX_EventError, + (OMX_U32)OMX_ErrorNotImplemented, + INPUT_PORT_INDEX, NULL); + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + break; + } + + pVideoEnc->bFirstInput = OMX_FALSE; + } + + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + break; + } + + if (CHECK_PORT_BEING_FLUSHED(exynosInputPort)) { + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + break; + } + + ret = pVideoEnc->exynos_codec_srcInputProcess(pOMXComponent, pSrcInputData); + + Exynos_ResetCodecData(pSrcInputData); + Exynos_OSAL_MutexUnlock(srcInputUseBuffer->bufferMutex); + + if ((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCodecInit) + pVideoEnc->bExitBufferProcessThread = OMX_TRUE; + } + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SrcOutputBufferProcess(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *srcOutputUseBuffer = &exynosInputPort->way.port2WayDataBuffer.outputDataBuffer; + EXYNOS_OMX_DATA srcOutputData; + + FunctionIn(); + + Exynos_ResetCodecData(&srcOutputData); + + while (!pVideoEnc->bExitBufferProcessThread) { + Exynos_OSAL_SleepMillisec(0); + if ((exynosInputPort->semWaitPortEnable[OUTPUT_WAY_INDEX] != NULL) && + ((CHECK_PORT_BEING_DISABLED(exynosInputPort)) || + (!CHECK_PORT_ENABLED(exynosInputPort)))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> wait(port enable)", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(exynosInputPort->semWaitPortEnable[OUTPUT_WAY_INDEX]); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> post(port enable)", pExynosComponent, __FUNCTION__); + continue; + } + + while (!pVideoEnc->bExitBufferProcessThread) { + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + if (Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX) == OMX_FALSE) + break; + } + Exynos_OSAL_SleepMillisec(0); + + if (CHECK_PORT_BEING_FLUSHED(exynosInputPort)) + break; + + Exynos_OSAL_MutexLock(srcOutputUseBuffer->bufferMutex); + Exynos_OSAL_Memset(&srcOutputData, 0, sizeof(EXYNOS_OMX_DATA)); + + ret = pVideoEnc->exynos_codec_srcOutputProcess(pOMXComponent, &srcOutputData); + + if (ret == OMX_ErrorNone) { + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + OMX_PTR codecBuffer; + codecBuffer = srcOutputData.pPrivate; + if (codecBuffer != NULL) + Exynos_CodecBufferEnqueue(pExynosComponent, INPUT_PORT_INDEX, codecBuffer); + } + if (exynosInputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_Shared_DataToBuffer(exynosInputPort, srcOutputUseBuffer, &srcOutputData); + Exynos_InputBufferReturn(pOMXComponent, srcOutputUseBuffer); + } + Exynos_ResetCodecData(&srcOutputData); + } + Exynos_OSAL_MutexUnlock(srcOutputUseBuffer->bufferMutex); + } + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_DstInputBufferProcess(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *dstInputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.inputDataBuffer; + EXYNOS_OMX_DATA dstInputData; + + FunctionIn(); + + Exynos_ResetCodecData(&dstInputData); + + while (!pVideoEnc->bExitBufferProcessThread) { + Exynos_OSAL_SleepMillisec(0); + if ((exynosOutputPort->semWaitPortEnable[INPUT_WAY_INDEX] != NULL) && + ((CHECK_PORT_BEING_DISABLED(exynosOutputPort)) || + (!CHECK_PORT_ENABLED(exynosOutputPort)))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> wait(port enable)", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(exynosOutputPort->semWaitPortEnable[INPUT_WAY_INDEX]); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> post(port enable)", pExynosComponent, __FUNCTION__); + continue; + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) && + (!pVideoEnc->bExitBufferProcessThread)) { + Exynos_OSAL_SleepMillisec(0); + + if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) + break; + + Exynos_OSAL_MutexLock(dstInputUseBuffer->bufferMutex); + + if (exynosOutputPort->bufferProcessType & BUFFER_COPY) { + CODEC_ENC_BUFFER *pCodecBuffer = NULL; + ret = Exynos_CodecBufferDequeue(pExynosComponent, OUTPUT_PORT_INDEX, (OMX_PTR *)&pCodecBuffer); + if (pVideoEnc->bExitBufferProcessThread) { + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + goto EXIT; + } + + if (ret != OMX_ErrorNone) { + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + Exynos_CodecBufferToData(pCodecBuffer, &dstInputData, OUTPUT_PORT_INDEX); + } + + if (exynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((dstInputUseBuffer->dataValid != OMX_TRUE) && + (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + ret = Exynos_OutputBufferGetQueue(pExynosComponent); + if (pVideoEnc->bExitBufferProcessThread) { + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + goto EXIT; + } + + if (ret != OMX_ErrorNone) { + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + + ret = Exynos_Shared_BufferToData(exynosOutputPort, dstInputUseBuffer, &dstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to GetBufferFdFromMetaData from %p", + pExynosComponent, __FUNCTION__, dstInputUseBuffer->bufferHeader); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + + if (exynosOutputPort->eMetaDataType == METADATA_TYPE_HANDLE) { + OMX_PTR dataBuffer = NULL; + + dataBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoEnc->hSharedMemory, dstInputData.buffer.fd[0]); + if (dataBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid data buffer(%u)", + pExynosComponent, __FUNCTION__, dstInputData.buffer.fd[0]); + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + + dstInputData.buffer.addr[0] = dataBuffer; + } else { + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) { + unsigned long ionFD = (unsigned long)dstInputData.buffer.addr[0]; + + OMX_PTR dataBuffer = NULL; + dataBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoEnc->hSharedMemory, ionFD); + if (dataBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid data buffer(%u)", + pExynosComponent, __FUNCTION__, ionFD); + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + + dstInputData.buffer.fd[0] = ionFD; + dstInputData.buffer.addr[0] = dataBuffer; + } else { + dstInputData.buffer.fd[0] = + Exynos_OSAL_SharedMemory_VirtToION(pVideoEnc->hSharedMemory, + dstInputData.buffer.addr[0]); + } + } + + Exynos_ResetDataBuffer(dstInputUseBuffer); + } + } + + if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) { + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + + ret = pVideoEnc->exynos_codec_dstInputProcess(pOMXComponent, &dstInputData); + + Exynos_ResetCodecData(&dstInputData); + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + } + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_DstOutputBufferProcess(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &exynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + EXYNOS_OMX_DATA *pDstOutputData = &exynosOutputPort->processData; + + FunctionIn(); + + while (!pVideoEnc->bExitBufferProcessThread) { + Exynos_OSAL_SleepMillisec(0); + Exynos_Wait_ProcessPause(pExynosComponent, OUTPUT_PORT_INDEX); + if ((exynosOutputPort->semWaitPortEnable[OUTPUT_WAY_INDEX] != NULL) && + ((CHECK_PORT_BEING_DISABLED(exynosOutputPort)) || + (!CHECK_PORT_ENABLED(exynosOutputPort)))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> wait(port enable)", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(exynosOutputPort->semWaitPortEnable[OUTPUT_WAY_INDEX]); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> post(port enable)", pExynosComponent, __FUNCTION__); + continue; + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) && + (!pVideoEnc->bExitBufferProcessThread)) { + Exynos_OSAL_SleepMillisec(0); + + if (CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) + break; + + Exynos_OSAL_MutexLock(dstOutputUseBuffer->bufferMutex); + + if (exynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((dstOutputUseBuffer->dataValid != OMX_TRUE) && + (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + ret = Exynos_OutputBufferGetQueue(pExynosComponent); + if (pVideoEnc->bExitBufferProcessThread) { + Exynos_OSAL_MutexUnlock(dstOutputUseBuffer->bufferMutex); + goto EXIT; + } + + if (ret != OMX_ErrorNone) { + Exynos_OSAL_MutexUnlock(dstOutputUseBuffer->bufferMutex); + break; + } + } + } + + if ((dstOutputUseBuffer->dataValid == OMX_TRUE) || + (exynosOutputPort->bufferProcessType & BUFFER_SHARE)) + ret = pVideoEnc->exynos_codec_dstOutputProcess(pOMXComponent, pDstOutputData); + + if (exynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if (ret == OMX_ErrorNoneReuseBuffer) + Exynos_OMX_FillThisBufferAgain(hComponent, pDstOutputData->bufferHeader); + else + Exynos_Postprocess_OutputData(pOMXComponent, pDstOutputData); + } + + if (exynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((ret == OMX_ErrorNone) && + (dstOutputUseBuffer->dataValid == OMX_TRUE)) { + Exynos_Postprocess_OutputData(pOMXComponent, pDstOutputData); + } + + if (pDstOutputData->pPrivate != NULL) { + Exynos_CodecBufferEnqueue(pExynosComponent, OUTPUT_PORT_INDEX, pDstOutputData->pPrivate); + pDstOutputData->pPrivate = NULL; + } + } + + /* reset outputData */ + Exynos_ResetCodecData(pDstOutputData); + Exynos_OSAL_MutexUnlock(dstOutputUseBuffer->bufferMutex); + } + } + +EXIT: + + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_SrcInputProcessThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + + FunctionIn(); + + if (threadData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_OMX_SrcInputBufferProcess(pOMXComponent); + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_SrcOutputProcessThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + + FunctionIn(); + + if (threadData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_OMX_SrcOutputBufferProcess(pOMXComponent); + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_DstInputProcessThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + + FunctionIn(); + + if (threadData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_OMX_DstInputBufferProcess(pOMXComponent); + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_OMX_DstOutputProcessThread(OMX_PTR threadData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + + FunctionIn(); + + if (threadData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)threadData; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_OMX_DstOutputBufferProcess(pOMXComponent); + + Exynos_OSAL_ThreadExit(NULL); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferProcess_Create(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + FunctionIn(); + + pVideoEnc->bExitBufferProcessThread = OMX_FALSE; + + ret = Exynos_OSAL_ThreadCreate(&pVideoEnc->hDstOutputThread, + Exynos_OMX_DstOutputProcessThread, + pOMXComponent); + if (ret == OMX_ErrorNone) + ret = Exynos_OSAL_ThreadCreate(&pVideoEnc->hSrcOutputThread, + Exynos_OMX_SrcOutputProcessThread, + pOMXComponent); + if (ret == OMX_ErrorNone) + ret = Exynos_OSAL_ThreadCreate(&pVideoEnc->hDstInputThread, + Exynos_OMX_DstInputProcessThread, + pOMXComponent); + if (ret == OMX_ErrorNone) + ret = Exynos_OSAL_ThreadCreate(&pVideoEnc->hSrcInputThread, + Exynos_OMX_SrcInputProcessThread, + pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferProcess_Terminate(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + OMX_S32 countValue = 0; + + FunctionIn(); + + pVideoEnc->bExitBufferProcessThread = OMX_TRUE; + + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bufferSemID, &countValue); + if (countValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bufferSemID); + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].codecSemID, &countValue); + if (countValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].codecSemID); + pVideoEnc->exynos_codec_bufferProcessRun(pOMXComponent, OUTPUT_PORT_INDEX); + + /* srcInput */ + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].pauseEvent); + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].semWaitPortEnable[INPUT_WAY_INDEX]); + Exynos_OSAL_ThreadTerminate(pVideoEnc->hSrcInputThread); + pVideoEnc->hSrcInputThread = NULL; + Exynos_OSAL_Set_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].semWaitPortEnable[INPUT_WAY_INDEX], 0); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] src input thread is terminated", pExynosComponent, __FUNCTION__); + + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bufferSemID, &countValue); + if (countValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bufferSemID); + Exynos_OSAL_Get_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].codecSemID, &countValue); + if (countValue == 0) + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].codecSemID); + + /* dstInput */ + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].pauseEvent); + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].semWaitPortEnable[INPUT_WAY_INDEX]); + Exynos_OSAL_ThreadTerminate(pVideoEnc->hDstInputThread); + pVideoEnc->hDstInputThread = NULL; + Exynos_OSAL_Set_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].semWaitPortEnable[INPUT_WAY_INDEX], 0); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] dst input thread is terminated", pExynosComponent, __FUNCTION__); + + pVideoEnc->exynos_codec_stop(pOMXComponent, INPUT_PORT_INDEX); + pVideoEnc->exynos_codec_bufferProcessRun(pOMXComponent, INPUT_PORT_INDEX); + + /* srcOutput */ + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].pauseEvent); + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].semWaitPortEnable[OUTPUT_WAY_INDEX]); + Exynos_OSAL_ThreadTerminate(pVideoEnc->hSrcOutputThread); + pVideoEnc->hSrcOutputThread = NULL; + Exynos_OSAL_Set_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].semWaitPortEnable[OUTPUT_WAY_INDEX], 0); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] src output thread is terminated", pExynosComponent, __FUNCTION__); + + pVideoEnc->exynos_codec_stop(pOMXComponent, OUTPUT_PORT_INDEX); + pVideoEnc->exynos_codec_bufferProcessRun(pOMXComponent, OUTPUT_PORT_INDEX); + + /* dstOutput */ + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].pauseEvent); + Exynos_OSAL_SemaphorePost(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].semWaitPortEnable[OUTPUT_WAY_INDEX]); + Exynos_OSAL_ThreadTerminate(pVideoEnc->hDstOutputThread); + pVideoEnc->hDstOutputThread = NULL; + Exynos_OSAL_Set_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].semWaitPortEnable[OUTPUT_WAY_INDEX], 0); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] dst output thread is terminated", pExynosComponent, __FUNCTION__); + + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = Exynos_OMX_BaseComponent_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to BaseComponent_Constructor", __FUNCTION__); + goto EXIT; + } + + ret = Exynos_OMX_Port_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Port_Constructor", __FUNCTION__); + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pVideoEnc = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_VIDEOENC_COMPONENT)); + if (pVideoEnc == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_Port_Destructor(pOMXComponent); + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Memset(pVideoEnc, 0, sizeof(EXYNOS_OMX_VIDEOENC_COMPONENT)); + pExynosComponent->hComponentHandle = (OMX_HANDLETYPE)pVideoEnc; + + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + pVideoEnc->bFirstInput = OMX_TRUE; + pVideoEnc->bFirstOutput = OMX_FALSE; + pVideoEnc->bQosChanged = OMX_FALSE; + pVideoEnc->nQosRatio = 0; + pVideoEnc->quantization.nQpI = 4; // I frame quantization parameter + pVideoEnc->quantization.nQpP = 5; // P frame quantization parameter + pVideoEnc->quantization.nQpB = 5; // B frame quantization parameter + + pVideoEnc->bDropControl = OMX_TRUE; + pVideoEnc->bUseBlurFilter = OMX_FALSE; + pVideoEnc->eBlurMode = BLUR_MODE_NONE; + pVideoEnc->eBlurResol = BLUR_RESOL_240; + pVideoEnc->eMirrorType = OMX_MirrorNone; + + pVideoEnc->eRotationType = ROTATE_0; + +#ifdef USE_ANDROID + pVideoEnc->pPerfHandle = Exynos_OSAL_CreatePerformanceHandle(OMX_TRUE /* bIsEncoder = true */); +#endif + + Exynos_OSAL_SignalCreate(&(pVideoEnc->hEncDRCSyncEvent)); + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->supportFormat = Exynos_OSAL_Malloc(sizeof(OMX_COLOR_FORMATTYPE) * INPUT_PORT_SUPPORTFORMAT_NUM_MAX); + if (pExynosPort->supportFormat == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort->supportFormat, 0, (sizeof(OMX_COLOR_FORMATTYPE) * INPUT_PORT_SUPPORTFORMAT_NUM_MAX)); + + pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MAX_VIDEO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = 0; + pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo; + + pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + if (pExynosPort->portDefinition.format.video.cMIMEType == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + + pExynosPort->portDefinition.format.video.nFrameWidth = 0; + pExynosPort->portDefinition.format.video.nFrameHeight= 0; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.format.video.nBitrate = 1000000; + pExynosPort->portDefinition.format.video.xFramerate = (15 << 16); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.format.video.pNativeWindow = NULL; + pVideoEnc->eControlRate[INPUT_PORT_INDEX] = OMX_Video_ControlRateVariable; + + pExynosPort->eMetaDataType = METADATA_TYPE_DISABLED; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->supportFormat = Exynos_OSAL_Malloc(sizeof(OMX_COLOR_FORMATTYPE) * OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX); + if (pExynosPort->supportFormat == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort->supportFormat, 0, (sizeof(OMX_COLOR_FORMATTYPE) * OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX)); + + pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo; + + pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + if (pExynosPort->portDefinition.format.video.cMIMEType == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + + pExynosPort->portDefinition.format.video.nFrameWidth = 0; + pExynosPort->portDefinition.format.video.nFrameHeight= 0; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.format.video.nBitrate = 1000000; + pExynosPort->portDefinition.format.video.xFramerate = (15 << 16); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.format.video.pNativeWindow = NULL; + pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] = OMX_Video_ControlRateVariable; + + pExynosPort->eMetaDataType = METADATA_TYPE_DISABLED; + + pOMXComponent->UseBuffer = &Exynos_OMX_UseBuffer; + pOMXComponent->AllocateBuffer = &Exynos_OMX_AllocateBuffer; + pOMXComponent->FreeBuffer = &Exynos_OMX_FreeBuffer; + +#ifdef TUNNELING_SUPPORT + pOMXComponent->ComponentTunnelRequest = &Exynos_OMX_ComponentTunnelRequest; + pExynosComponent->exynos_AllocateTunnelBuffer = &Exynos_OMX_AllocateTunnelBuffer; + pExynosComponent->exynos_FreeTunnelBuffer = &Exynos_OMX_FreeTunnelBuffer; +#endif + + pExynosComponent->exynos_BufferProcessCreate = &Exynos_OMX_BufferProcess_Create; + pExynosComponent->exynos_BufferProcessTerminate = &Exynos_OMX_BufferProcess_Terminate; + pExynosComponent->exynos_BufferFlush = &Exynos_OMX_BufferFlush; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + + int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + +#ifdef USE_ANDROID + Exynos_OSAL_ReleasePerformanceHandle(pVideoEnc->pPerfHandle); +#endif + + if (pVideoEnc->bEncDRCSync == OMX_TRUE) { + Exynos_OSAL_SignalSet(pVideoEnc->hEncDRCSyncEvent); + } + Exynos_OSAL_SignalTerminate(pVideoEnc->hEncDRCSyncEvent); + + Exynos_OSAL_Free(pVideoEnc); + pExynosComponent->hComponentHandle = pVideoEnc = NULL; + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + if (pExynosPort->processData.extInfo != NULL) { + Exynos_OSAL_Free(pExynosPort->processData.extInfo); + pExynosPort->processData.extInfo = NULL; + } + + for(i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + Exynos_OSAL_Free(pExynosPort->portDefinition.format.video.cMIMEType); + pExynosPort->portDefinition.format.video.cMIMEType = NULL; + + Exynos_OSAL_Free(pExynosPort->supportFormat); + pExynosPort->supportFormat = NULL; + } + + ret = Exynos_OMX_Port_Destructor(pOMXComponent); + + ret = Exynos_OMX_BaseComponent_Destructor(hComponent); + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/enc/Exynos_OMX_Venc.h b/openmax/component/video/enc/Exynos_OMX_Venc.h new file mode 100644 index 0000000..8f24212 --- /dev/null +++ b/openmax/component/video/enc/Exynos_OMX_Venc.h @@ -0,0 +1,184 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Venc.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_VIDEO_ENCODE +#define EXYNOS_OMX_VIDEO_ENCODE + +#include "OMX_Component.h" +#include "Exynos_OMX_Def.h" +#include "Exynos_OSAL_Queue.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Basecomponent.h" + +#define MAX_VIDEO_INPUTBUFFER_NUM 5 +#define MAX_VIDEO_OUTPUTBUFFER_NUM 4 + +#define MAX_FRAME_WIDTH 1920 +#define MAX_FRAME_HEIGHT 1080 + +#define DEFAULT_VIDEO_INPUT_BUFFER_SIZE (ALIGN_TO_16B(DEFAULT_FRAME_WIDTH) * ALIGN_TO_16B(DEFAULT_FRAME_HEIGHT) + \ + ALIGN((ALIGN_TO_16B(DEFAULT_FRAME_WIDTH) * ALIGN_TO_16B(DEFAULT_FRAME_HEIGHT))/2,256)) +#define DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE (DEFAULT_FRAME_WIDTH * DEFAULT_FRAME_HEIGHT) * 3 / 2 + +#define MFC_INPUT_BUFFER_NUM_MAX 5 +#define MFC_OUTPUT_BUFFER_NUM_MAX 4 + +#define DEFAULT_MFC_INPUT_YBUFFER_SIZE ALIGN_TO_16B(MAX_FRAME_WIDTH) * ALIGN_TO_16B(MAX_FRAME_HEIGHT) +#define DEFAULT_MFC_INPUT_CBUFFER_SIZE ALIGN((DEFAULT_MFC_INPUT_YBUFFER_SIZE / 2), 256) +#define DEFAULT_MFC_OUTPUT_BUFFER_SIZE MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2 + +#define MIN_CPB_SIZE (1024 * 1024) +#define CUSTOM_LIMITED_DRM_OUTPUT_BUFFER_SIZE (1024 * 1024 * 3) /* 3MB : For projects which has small vstream heap */ + +#define INPUT_PORT_SUPPORTFORMAT_DEFAULT_NUM 5 /* I42P, NV12, NV21, BGRA8888, RGBA8888 */ +#define INPUT_PORT_SUPPORTFORMAT_NUM_MAX (INPUT_PORT_SUPPORTFORMAT_DEFAULT_NUM + 5) /* Opaque, NV12T, YV12, ARGB8888, UNUSED */ +#define OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX 1 + +#define MFC_DEFAULT_INPUT_BUFFER_PLANE 2 +#define MFC_DEFAULT_OUTPUT_BUFFER_PLANE 1 + +#define MAX_INPUTBUFFER_NUM_DYNAMIC 0 /* Dynamic number of metadata buffer */ +#define MAX_OUTPUTBUFFER_NUM_DYNAMIC 0 /* Dynamic number of metadata buffer */ + +#define OMX_VIDEO_MAX_REF_FRAMES 3 +#define OMX_VIDEO_MAX_LTR_FRAMES 4 /* LTR */ + +#define ENC_BLOCKS_PER_SECOND 979200 /* remove it and have to read a capability at media_codecs.xml */ + +#define GENERAL_TSVC_ENABLE (1 << 16) + +typedef struct +{ + void *pAddrY; + void *pAddrC; +} CODEC_ENC_ADDR_INFO; + +typedef struct _BYPASS_BUFFER_INFO +{ + OMX_U32 nFlags; + OMX_TICKS timeStamp; +} BYPASS_BUFFER_INFO; + +typedef struct _CODEC_ENC_BUFFER +{ + void *pVirAddr[MAX_BUFFER_PLANE]; /* virtual address */ + unsigned int bufferSize[MAX_BUFFER_PLANE]; /* buffer alloc size */ + unsigned long fd[MAX_BUFFER_PLANE]; /* buffer FD */ + int dataSize; /* total data length */ +} CODEC_ENC_BUFFER; + +typedef struct _EXYNOS_OMX_VIDEOENC_COMPONENT +{ + OMX_HANDLETYPE hCodecHandle; + OMX_BOOL bQosChanged; + OMX_U32 nQosRatio; + OMX_U32 nOperatingRate; + OMX_U32 nPriority; + CODEC_ENC_BUFFER *pMFCEncInputBuffer[MFC_INPUT_BUFFER_NUM_MAX]; + CODEC_ENC_BUFFER *pMFCEncOutputBuffer[MFC_OUTPUT_BUFFER_NUM_MAX]; + + /* Buffer Process */ + OMX_BOOL bExitBufferProcessThread; + OMX_HANDLETYPE hSrcInputThread; + OMX_HANDLETYPE hSrcOutputThread; + OMX_HANDLETYPE hDstInputThread; + OMX_HANDLETYPE hDstOutputThread; + + /* Shared Memory Handle */ + OMX_HANDLETYPE hSharedMemory; + + OMX_BOOL IntraRefreshVOP; + OMX_VIDEO_CONTROLRATETYPE eControlRate[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_QUANTIZATIONTYPE quantization; + OMX_VIDEO_PARAM_INTRAREFRESHTYPE intraRefresh; + + OMX_BOOL bPVCMode; /* true: PVC mode on false: PVC mode off + Only h264 hevc vp8 vp9 codec valid */ + OMX_BOOL bDropControl; + OMX_BOOL bDisableDFR; + + OMX_BOOL bUseBlurFilter; + EXYNOS_OMX_BLUR_MODE eBlurMode; /* Down/Up or Coefficient mothod */ + EXYNOS_OMX_BLUR_RESOL eBlurResol; + + EXYNOS_OMX_ROTATION_TYPE eRotationType; + OMX_MIRRORTYPE eMirrorType; + + OMX_BOOL bFirstInput; + OMX_BOOL bFirstOutput; + OMX_BOOL bEncDRC; + OMX_BOOL bEncDRCSync; + OMX_HANDLETYPE hEncDRCSyncEvent; + + OMX_COLOR_FORMATTYPE surfaceFormat; + + /* CSC handle */ + OMX_PTR csc_handle; + OMX_BOOL csc_set_format; + + /* Performance handle */ + OMX_HANDLETYPE pPerfHandle; + + OMX_ERRORTYPE (*exynos_codec_srcInputProcess) (OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData); + OMX_ERRORTYPE (*exynos_codec_srcOutputProcess) (OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pInputData); + OMX_ERRORTYPE (*exynos_codec_dstInputProcess) (OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pOutputData); + OMX_ERRORTYPE (*exynos_codec_dstOutputProcess) (OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATA *pOutputData); + + OMX_ERRORTYPE (*exynos_codec_start)(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex); + OMX_ERRORTYPE (*exynos_codec_stop)(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex); + OMX_ERRORTYPE (*exynos_codec_bufferProcessRun)(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex); + OMX_ERRORTYPE (*exynos_codec_enqueueAllBuffer)(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex); + + OMX_ERRORTYPE (*exynos_codec_getCodecOutputPrivateData) (OMX_PTR codecBuffer, OMX_PTR *addr, OMX_U32 *size); + + OMX_BOOL (*exynos_codec_checkFormatSupport)(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_COLOR_FORMATTYPE eColorFormat); +} EXYNOS_OMX_VIDEOENC_COMPONENT; + +#ifdef __cplusplus +extern "C" { +#endif + +void Exynos_UpdateFrameSize(OMX_COMPONENTTYPE *pOMXComponent); +void Exynos_Input_SetSupportFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +OMX_COLOR_FORMATTYPE Exynos_Input_GetActualColorFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +OMX_BOOL Exynos_Check_BufferProcess_State(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_CodecBufferToData(CODEC_ENC_BUFFER *codecBuffer, EXYNOS_OMX_DATA *pData, OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_SrcInputBufferProcess(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_SrcOutputBufferProcess(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_DstInputBufferProcess(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_DstOutputBufferProcess(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_Allocate_CodecBuffers(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex, int nBufferCnt, unsigned int nAllocLen[MAX_BUFFER_PLANE]); +void Exynos_Free_CodecBuffers(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_ResetAllPortConfig(OMX_COMPONENTTYPE *pOMXComponent); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/component/video/enc/Exynos_OMX_VencControl.c b/openmax/component/video/enc/Exynos_OMX_VencControl.c new file mode 100644 index 0000000..6292f1e --- /dev/null +++ b/openmax/component/video/enc/Exynos_OMX_VencControl.c @@ -0,0 +1,2712 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_VencControl.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.5.0 + * @history + * 2012.02.20 : Create + * 2017.08.03 : Change event handling + */ + +#include +#include +#include +#include "Exynos_OMX_Macros.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OMX_Venc.h" +#include "Exynos_OMX_VencControl.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_SharedMemory.h" + +#include "Exynos_OSAL_Platform.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VIDEO_ENCCONTROL" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pTempBufferHdr = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (pExynosPort->portState != EXYNOS_OMX_PortStateEnabling) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && + CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pTempBufferHdr = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (pTempBufferHdr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pTempBufferHdr, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = pTempBufferHdr; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ASSIGNED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(pTempBufferHdr, OMX_BUFFERHEADERTYPE); + + pTempBufferHdr->pBuffer = pBuffer; + pTempBufferHdr->nAllocLen = nSizeBytes; + pTempBufferHdr->pAppPrivate = pAppPrivate; + + if (nPortIndex == INPUT_PORT_INDEX) + pTempBufferHdr->nInputPortIndex = INPUT_PORT_INDEX; + else + pTempBufferHdr->nOutputPortIndex = OUTPUT_PORT_INDEX; + + pExynosPort->assignedBufferNum++; + + *ppBufferHdr = pTempBufferHdr; + + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + + if ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle)) { + if (CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OMX_SendEventCommand(pExynosComponent, EVENT_CMD_STATE_TO_IDLE_STATE, NULL); + } + } else if((!CHECK_PORT_ENABLED(pExynosPort)) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + Exynos_OMX_SendEventCommand(pExynosComponent, + ((nPortIndex == INPUT_PORT_INDEX)? EVENT_CMD_ENABLE_INPUT_PORT:EVENT_CMD_ENABLE_OUTPUT_PORT), + NULL); + } + } + + ret = OMX_ErrorNone; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p), size(%d)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + (*ppBufferHdr), nSizeBytes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pTempBufferHdr); + ret = OMX_ErrorInsufficientResources; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pTempBufferHdr = NULL; + OMX_U8 *pTempBuffer = NULL; + unsigned long fdTempBuffer = 0; + MEMORY_TYPE eMemType = NORMAL_MEMORY; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (pExynosPort->portState != EXYNOS_OMX_PortStateEnabling) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && + CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) && + (nPortIndex == OUTPUT_PORT_INDEX)) + eMemType |= SECURE_MEMORY; + + if (pExynosPort->bNeedContigMem == OMX_TRUE) + eMemType |= CONTIG_MEMORY; + + if (!((nPortIndex == INPUT_PORT_INDEX) && + (pExynosPort->bufferProcessType & BUFFER_SHARE))) + eMemType |= CACHED_MEMORY; + + if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pExynosPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + eMemType |= CONTIG_MEMORY; /* always set for HDCP */ + +#ifdef USE_VIDEO_EXT_FOR_WFD_HDCP + if ((eMemType & SECURE_MEMORY) || // secure component + (eMemType & CONTIG_MEMORY)) { // Normal DRM + eMemType |= EXT_MEMORY; + } +#endif + pTempBuffer = Exynos_OSAL_AllocMetaDataBuffer(pVideoEnc->hSharedMemory, + pExynosPort->eMetaDataType, + nSizeBytes, + eMemType); + if (pTempBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Alloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else { + pTempBuffer = Exynos_OSAL_SharedMemory_Alloc(pVideoEnc->hSharedMemory, nSizeBytes, eMemType); + if (pTempBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Alloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + fdTempBuffer = Exynos_OSAL_SharedMemory_VirtToION(pVideoEnc->hSharedMemory, pTempBuffer); + } + + pTempBufferHdr = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (pTempBufferHdr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pTempBufferHdr, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = pTempBufferHdr; + pExynosPort->extendBufferHeader[i].buf_fd[0] = fdTempBuffer; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ALLOCATED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(pTempBufferHdr, OMX_BUFFERHEADERTYPE); + + if ((pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) && + (pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + pTempBufferHdr->pBuffer = (void *)fdTempBuffer; + } else { + pTempBufferHdr->pBuffer = pTempBuffer; + } + + pTempBufferHdr->nAllocLen = nSizeBytes; + pTempBufferHdr->pAppPrivate = pAppPrivate; + + if (nPortIndex == INPUT_PORT_INDEX) + pTempBufferHdr->nInputPortIndex = INPUT_PORT_INDEX; + else + pTempBufferHdr->nOutputPortIndex = OUTPUT_PORT_INDEX; + + pExynosPort->assignedBufferNum++; + + *ppBufferHdr = pTempBufferHdr; + + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + + if ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle)) { + if (CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OMX_SendEventCommand(pExynosComponent, EVENT_CMD_STATE_TO_IDLE_STATE, NULL); + } + } else if((!CHECK_PORT_ENABLED(pExynosPort)) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + Exynos_OMX_SendEventCommand(pExynosComponent, + ((nPortIndex == INPUT_PORT_INDEX)? EVENT_CMD_ENABLE_INPUT_PORT:EVENT_CMD_ENABLE_OUTPUT_PORT), + NULL); + } + } + + ret = OMX_ErrorNone; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p), size(%d)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + (*ppBufferHdr), nSizeBytes); + goto EXIT; + } + } + + ret = OMX_ErrorInsufficientResources; + +EXIT: + if (ret == OMX_ErrorInsufficientResources) { + if (pTempBufferHdr != NULL) + Exynos_OSAL_Free(pTempBufferHdr); + + if (pTempBuffer != NULL) { + if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pExynosPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + Exynos_OSAL_FreeMetaDataBuffer(pVideoEnc->hSharedMemory, pExynosPort->eMetaDataType, pTempBuffer); + } else if ((pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) && + (pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + OMX_PTR mapBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoEnc->hSharedMemory, fdTempBuffer); + + Exynos_OSAL_SharedMemory_Free(pVideoEnc->hSharedMemory, pTempBuffer); + } else { + Exynos_OSAL_SharedMemory_Free(pVideoEnc->hSharedMemory, pTempBuffer); + } + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pOMXBufferHdr = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (CHECK_PORT_TUNNELED(pExynosPort) && + CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosPort->portState != EXYNOS_OMX_PortStateDisabling) && + (pExynosPort->portState != EXYNOS_OMX_PortStateFlushingForDisable) && + (pExynosPort->portState != EXYNOS_OMX_PortStateInvalid)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + + (*(pExynosComponent->pCallbacks->EventHandler)) (pOMXComponent, + pExynosComponent->callbackData, + (OMX_U32)OMX_EventError, + (OMX_U32)OMX_ErrorPortUnpopulated, + nPortIndex, NULL); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + for (i = 0; i < /*pExynosPort->portDefinition.nBufferCountActual*/MAX_BUFFER_NUM; i++) { + if ((pExynosPort->bufferStateAllocate[i] != BUFFER_STATE_FREE) && + (pExynosPort->extendBufferHeader[i].OMXBufferHeader != NULL)) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Buffer can't be freed because this(%p) is already in component", pExynosComponent, __FUNCTION__, pBufferHdr); + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + } + + pOMXBufferHdr = pExynosPort->extendBufferHeader[i].OMXBufferHeader; + + if (pOMXBufferHdr->pBuffer == pBufferHdr->pBuffer) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pOMXBufferHdr); + if (pExynosPort->bufferStateAllocate[i] & BUFFER_STATE_ALLOCATED) { + if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pExynosPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + Exynos_OSAL_FreeMetaDataBuffer(pVideoEnc->hSharedMemory, + pExynosPort->eMetaDataType, + pOMXBufferHdr->pBuffer); + } else if ((pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) && + (pExynosPort->eMetaDataType == OUTPUT_PORT_INDEX)) { + unsigned long ionFD = (unsigned long)pOMXBufferHdr->pBuffer; + + OMX_PTR mapBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoEnc->hSharedMemory, ionFD); + Exynos_OSAL_SharedMemory_Free(pVideoEnc->hSharedMemory, mapBuffer); + } else { + Exynos_OSAL_SharedMemory_Free(pVideoEnc->hSharedMemory, pOMXBufferHdr->pBuffer); + } + + pOMXBufferHdr->pBuffer = NULL; + pBufferHdr->pBuffer = NULL; + } else if (pExynosPort->bufferStateAllocate[i] & BUFFER_STATE_ASSIGNED) { + ; /* None*/ + } + + pExynosPort->assignedBufferNum--; + + if (pExynosPort->bufferStateAllocate[i] & HEADER_STATE_ALLOCATED) { + Exynos_OSAL_Free(pOMXBufferHdr); + pExynosPort->extendBufferHeader[i].OMXBufferHeader = NULL; + pExynosPort->extendBufferHeader[i].bBufferInOMX = OMX_FALSE; + pBufferHdr = NULL; + } + + pExynosPort->bufferStateAllocate[i] = BUFFER_STATE_FREE; + ret = OMX_ErrorNone; + goto EXIT; + } + } + } + +EXIT: + if (ret == OMX_ErrorNone) { + if (pExynosPort->assignedBufferNum < (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) + pExynosPort->portDefinition.bPopulated = OMX_FALSE; + + if (pExynosPort->assignedBufferNum == 0) { + if ((pExynosComponent->currentState == OMX_StateIdle) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateIdleToLoaded)) { + if (!CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + !CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OMX_SendEventCommand(pExynosComponent, EVENT_CMD_STATE_TO_LOAD_STATE, NULL); + } + } else if((CHECK_PORT_ENABLED(pExynosPort)) && + (pExynosPort->portState == EXYNOS_OMX_PortStateDisabling)) { + Exynos_OMX_SendEventCommand(pExynosComponent, + ((nPortIndex == INPUT_PORT_INDEX)? EVENT_CMD_DISABLE_INPUT_PORT:EVENT_CMD_DISABLE_OUTPUT_PORT), + NULL); + } + } + } + + FunctionOut(); + + return ret; +} + +#ifdef TUNNELING_SUPPORT +OMX_ERRORTYPE Exynos_OMX_AllocateTunnelBuffer( + EXYNOS_OMX_BASEPORT *pOMXBasePort, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pTempBufferHdr = NULL; + OMX_U8 *pTempBuffer = NULL; + OMX_U32 nBufferSize = 0; + OMX_PARAM_PORTDEFINITIONTYPE portDefinition; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FreeTunnelBuffer( + EXYNOS_OMX_BASEPORT *pOMXBasePort, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pTempBufferHdr = NULL; + OMX_U8 *pTempBuffer = NULL; + OMX_U32 nBufferSize = 0; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentTunnelRequest( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 nPort, + OMX_IN OMX_HANDLETYPE hTunneledComp, + OMX_IN OMX_U32 nTunneledPort, + OMX_INOUT OMX_TUNNELSETUPTYPE *pTunnelSetup) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + ret = OMX_ErrorTunnelingUnsupported; +EXIT: + return ret; +} +#endif + +OMX_ERRORTYPE Exynos_OMX_GetFlushBuffer( + EXYNOS_OMX_BASEPORT *pExynosPort, + EXYNOS_OMX_DATABUFFER *pDataBuffer[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + *pDataBuffer = NULL; + + if (pExynosPort->portWayType == WAY1_PORT) { + *pDataBuffer = &pExynosPort->way.port1WayDataBuffer.dataBuffer; + } else if (pExynosPort->portWayType == WAY2_PORT) { + pDataBuffer[0] = &(pExynosPort->way.port2WayDataBuffer.inputDataBuffer); + pDataBuffer[1] = &(pExynosPort->way.port2WayDataBuffer.outputDataBuffer); + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FlushPort( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pBufferHdr = NULL; + EXYNOS_OMX_DATABUFFER *pDataBuffer[2] = {NULL, NULL}; + EXYNOS_OMX_MESSAGE *pMessage = NULL; + OMX_S32 nSemaCnt = 0; + int i = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if ((nPortIndex < 0) || + (nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + while (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > 0) { + Exynos_OSAL_Get_SemaphoreCount(pExynosPort->bufferSemID, &nSemaCnt); + if (nSemaCnt == 0) + Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + pMessage = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if ((pMessage != NULL) && + (pMessage->type != EXYNOS_OMX_CommandFakeBuffer)) { + pBufferHdr = (OMX_BUFFERHEADERTYPE *)pMessage->pCmdData; + pBufferHdr->nFilledLen = 0; + + if (nPortIndex == OUTPUT_PORT_INDEX) { + Exynos_OMX_OutputBufferReturn(pOMXComponent, pBufferHdr); + } else if (nPortIndex == INPUT_PORT_INDEX) { + Exynos_OMX_InputBufferReturn(pOMXComponent, pBufferHdr); + } + } + Exynos_OSAL_Free(pMessage); + pMessage = NULL; + } + + Exynos_OMX_GetFlushBuffer(pExynosPort, pDataBuffer); + if ((pDataBuffer[0] != NULL) && + (pDataBuffer[0]->dataValid == OMX_TRUE)) { + if (nPortIndex == INPUT_PORT_INDEX) + Exynos_InputBufferReturn(pOMXComponent, pDataBuffer[0]); + else if (nPortIndex == OUTPUT_PORT_INDEX) + Exynos_OutputBufferReturn(pOMXComponent, pDataBuffer[0]); + } + if ((pDataBuffer[1] != NULL) && + (pDataBuffer[1]->dataValid == OMX_TRUE)) { + if (nPortIndex == INPUT_PORT_INDEX) + Exynos_InputBufferReturn(pOMXComponent, pDataBuffer[1]); + else if (nPortIndex == OUTPUT_PORT_INDEX) + Exynos_OutputBufferReturn(pOMXComponent, pDataBuffer[1]); + } + + if (pExynosPort->bufferProcessType & BUFFER_SHARE) { + if (pExynosPort->processData.bufferHeader != NULL) { + if (nPortIndex == INPUT_PORT_INDEX) { + if (pExynosPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) + Exynos_OSAL_UnlockMetaData(pExynosPort->processData.bufferHeader->pBuffer, pExynosPort->eMetaDataType); + + Exynos_OMX_InputBufferReturn(pOMXComponent, pExynosPort->processData.bufferHeader); + } else if (nPortIndex == OUTPUT_PORT_INDEX) { + Exynos_OMX_OutputBufferReturn(pOMXComponent, pExynosPort->processData.bufferHeader); + } + } + Exynos_ResetCodecData(&pExynosPort->processData); + + for (i = 0; i < (OMX_S32)pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->extendBufferHeader[i].bBufferInOMX == OMX_TRUE) { + if (nPortIndex == OUTPUT_PORT_INDEX) { + Exynos_OMX_OutputBufferReturn(pOMXComponent, + pExynosPort->extendBufferHeader[i].OMXBufferHeader); + } else if (nPortIndex == INPUT_PORT_INDEX) { + if (pExynosPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) + Exynos_OSAL_UnlockMetaData(pExynosPort->extendBufferHeader[i].OMXBufferHeader->pBuffer, pExynosPort->eMetaDataType); + + Exynos_OMX_InputBufferReturn(pOMXComponent, + pExynosPort->extendBufferHeader[i].OMXBufferHeader); + } + } + } + } + + if (pExynosPort->bufferSemID != NULL) { + while (1) { + OMX_S32 cnt = 0; + Exynos_OSAL_Get_SemaphoreCount(pExynosPort->bufferSemID, &cnt); + if (cnt == 0) + break; + else if (cnt > 0) + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + else if (cnt < 0) + Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + Exynos_OSAL_SleepMillisec(0); + } + } + Exynos_OSAL_ResetQueue(&pExynosPort->bufferQ); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferFlush( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex, + OMX_BOOL bEvent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_DATABUFFER *pDataBuffer[2] = {NULL, NULL}; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if ((nPortIndex < 0) || + (nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] OMX_CommandFlush start, port:%d, event:%d", + pExynosComponent, __FUNCTION__, nPortIndex, bEvent); + + Exynos_OSAL_SignalSet(pExynosPort->pauseEvent); + + Exynos_OMX_GetFlushBuffer(pExynosPort, pDataBuffer); + if (pDataBuffer[0] == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pExynosPort->bufferProcessType & BUFFER_COPY) + Exynos_OSAL_SemaphorePost(pExynosPort->codecSemID); + + if (pExynosPort->bufferSemID != NULL) { + while (1) { + OMX_S32 cnt = 0; + Exynos_OSAL_Get_SemaphoreCount(pExynosPort->bufferSemID, &cnt); + if (cnt > 0) + break; + else + Exynos_OSAL_SemaphorePost(pExynosPort->bufferSemID); + Exynos_OSAL_SleepMillisec(0); + } + } + + pVideoEnc->exynos_codec_bufferProcessRun(pOMXComponent, nPortIndex); + + Exynos_OSAL_MutexLock(pDataBuffer[0]->bufferMutex); + pVideoEnc->exynos_codec_stop(pOMXComponent, nPortIndex); + + if (pDataBuffer[1] != NULL) + Exynos_OSAL_MutexLock(pDataBuffer[1]->bufferMutex); + + ret = Exynos_OMX_FlushPort(pOMXComponent, nPortIndex); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pExynosPort->bufferProcessType & BUFFER_COPY) + pVideoEnc->exynos_codec_enqueueAllBuffer(pOMXComponent, nPortIndex); + + Exynos_ResetCodecData(&pExynosPort->processData); + + if (ret == OMX_ErrorNone) { + if (nPortIndex == INPUT_PORT_INDEX) { + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_TRUE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, OMX_FALSE, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + pExynosComponent->reInputData = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_CountReset(pExynosPort->hBufferCount); +#endif + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] OMX_CommandFlush end, port:%d, event:%d", + pExynosComponent, __FUNCTION__, nPortIndex, bEvent); + +EXIT: + if (pDataBuffer[1] != NULL) + Exynos_OSAL_MutexUnlock(pDataBuffer[1]->bufferMutex); + + if (pDataBuffer[0] != NULL) + Exynos_OSAL_MutexUnlock(pDataBuffer[0]->bufferMutex); + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_InputBufferReturn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATABUFFER *pDataBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pBufferHdr = NULL; + + FunctionIn(); + + if ((pOMXComponent == NULL) || + (pDataBuffer == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosPort = &(pExynosComponent->pExynosPort[INPUT_PORT_INDEX]); + + pBufferHdr = pDataBuffer->bufferHeader; + + if (pBufferHdr != NULL) { + if (pExynosPort->markType.hMarkTargetComponent != NULL) { + pBufferHdr->hMarkTargetComponent = pExynosPort->markType.hMarkTargetComponent; + pBufferHdr->pMarkData = pExynosPort->markType.pMarkData; + pExynosPort->markType.hMarkTargetComponent = NULL; + pExynosPort->markType.pMarkData = NULL; + } + + if (pBufferHdr->hMarkTargetComponent != NULL) { + if (pBufferHdr->hMarkTargetComponent == pOMXComponent) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventMark, + 0, 0, pBufferHdr->pMarkData); + } else { + pExynosComponent->propagateMarkType.hMarkTargetComponent = pBufferHdr->hMarkTargetComponent; + pExynosComponent->propagateMarkType.pMarkData = pBufferHdr->pMarkData; + } + } + + pBufferHdr->nFilledLen = 0; + pBufferHdr->nOffset = 0; + + Exynos_OMX_InputBufferReturn(pOMXComponent, pBufferHdr); + } + + /* reset dataBuffer */ + Exynos_ResetDataBuffer(pDataBuffer); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_InputBufferGetQueue( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorUndefined; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *pMessage = NULL; + EXYNOS_OMX_DATABUFFER *pDataBuffer = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosPort = &(pExynosComponent->pExynosPort[INPUT_PORT_INDEX]); + pDataBuffer = &(pExynosPort->way.port2WayDataBuffer.inputDataBuffer); + + if (pExynosComponent->currentState != OMX_StateExecuting) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorUndefined; + goto EXIT; + } else if ((pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (!CHECK_PORT_BEING_FLUSHED(pExynosPort))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> wait(bufferSemID)", + pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input port -> post(bufferSemID)", + pExynosComponent, __FUNCTION__); + + if (pDataBuffer->dataValid != OMX_TRUE) { + pMessage = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (pMessage == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + if (pMessage->type == EXYNOS_OMX_CommandFakeBuffer) { + Exynos_OSAL_Free(pMessage); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecFlush; + goto EXIT; + } + + pDataBuffer->bufferHeader = (OMX_BUFFERHEADERTYPE *)(pMessage->pCmdData); + pDataBuffer->allocSize = pDataBuffer->bufferHeader->nAllocLen; + pDataBuffer->dataLen = pDataBuffer->bufferHeader->nFilledLen; + pDataBuffer->remainDataLen = pDataBuffer->dataLen; + pDataBuffer->usedDataLen = 0; + pDataBuffer->dataValid = OMX_TRUE; + pDataBuffer->nFlags = pDataBuffer->bufferHeader->nFlags; + pDataBuffer->timeStamp = pDataBuffer->bufferHeader->nTimeStamp; + + Exynos_OSAL_Free(pMessage); + + if (pDataBuffer->allocSize < pDataBuffer->dataLen) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] buffer size(%d) is smaller than dataLen(%d)", + pExynosComponent, __FUNCTION__, + pDataBuffer->allocSize, pDataBuffer->dataLen); + } + } + + ret = OMX_ErrorNone; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OutputBufferReturn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATABUFFER *pDataBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pBufferHdr = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + + if (pDataBuffer != NULL) + pBufferHdr = pDataBuffer->bufferHeader; + + if (pBufferHdr != NULL) { + pBufferHdr->nFilledLen = pDataBuffer->remainDataLen; + pBufferHdr->nOffset = 0; + pBufferHdr->nFlags = pDataBuffer->nFlags; + pBufferHdr->nTimeStamp = pDataBuffer->timeStamp; + + if ((pExynosPort->eMetaDataType & METADATA_TYPE_DATA) && + (pBufferHdr->nFilledLen > 0)) { + pBufferHdr->nFilledLen = pBufferHdr->nAllocLen; + } + + if (pExynosComponent->propagateMarkType.hMarkTargetComponent != NULL) { + pBufferHdr->hMarkTargetComponent = pExynosComponent->propagateMarkType.hMarkTargetComponent; + pBufferHdr->pMarkData = pExynosComponent->propagateMarkType.pMarkData; + pExynosComponent->propagateMarkType.hMarkTargetComponent = NULL; + pExynosComponent->propagateMarkType.pMarkData = NULL; + } + + if ((pBufferHdr->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] send event(OMX_EventBufferFlag)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventBufferFlag, + OUTPUT_PORT_INDEX, + pBufferHdr->nFlags, NULL); + } + + Exynos_OMX_OutputBufferReturn(pOMXComponent, pBufferHdr); + } + + /* reset dataBuffer */ + Exynos_ResetDataBuffer(pDataBuffer); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OutputBufferGetQueue( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorUndefined; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *pMessage = NULL; + EXYNOS_OMX_DATABUFFER *pDataBuffer = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + + if (pExynosPort->bufferProcessType & BUFFER_COPY) { + pDataBuffer = &(pExynosPort->way.port2WayDataBuffer.outputDataBuffer); + } else if (pExynosPort->bufferProcessType & BUFFER_SHARE) { + pDataBuffer = &(pExynosPort->way.port2WayDataBuffer.inputDataBuffer); + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if (pExynosComponent->currentState != OMX_StateExecuting) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorUndefined; + goto EXIT; + } else if ((pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (!CHECK_PORT_BEING_FLUSHED(pExynosPort))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> wait(bufferSemID)", + pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> post(bufferSemID)", + pExynosComponent, __FUNCTION__); + if (pDataBuffer->dataValid != OMX_TRUE) { + pMessage = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (pMessage == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + if (pMessage->type == EXYNOS_OMX_CommandFakeBuffer) { + Exynos_OSAL_Free(pMessage); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecFlush; + goto EXIT; + } + + pDataBuffer->bufferHeader = (OMX_BUFFERHEADERTYPE *)(pMessage->pCmdData); + pDataBuffer->allocSize = pDataBuffer->bufferHeader->nAllocLen; + pDataBuffer->dataLen = 0; //dataBuffer->bufferHeader->nFilledLen; + pDataBuffer->remainDataLen = pDataBuffer->dataLen; + pDataBuffer->usedDataLen = 0; //dataBuffer->bufferHeader->nOffset; + pDataBuffer->dataValid = OMX_TRUE; + /* pDataBuffer->nFlags = pDataBuffer->bufferHeader->nFlags; */ + /* pDtaBuffer->nTimeStamp = pDataBuffer->bufferHeader->nTimeStamp; */ +/* + if (pExynosPort->bufferProcessType & BUFFER_SHARE) + pDataBuffer->pPrivate = pDataBuffer->bufferHeader->pOutputPortPrivate; + else if (pExynosPort->bufferProcessType & BUFFER_COPY) { + pExynosPort->processData.dataBuffer = pDataBuffer->bufferHeader->pBuffer; + pExynosPort->processData.allocSize = pDataBuffer->bufferHeader->nAllocLen; + } +*/ + Exynos_OSAL_Free(pMessage); + } + + ret = OMX_ErrorNone; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_BUFFERHEADERTYPE *Exynos_OutputBufferGetQueue_Direct( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_BUFFERHEADERTYPE *pBufferHdr = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_MESSAGE *pMessage = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + pBufferHdr = NULL; + goto EXIT; + } + pExynosPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + + if (pExynosComponent->currentState != OMX_StateExecuting) { + pBufferHdr = NULL; + goto EXIT; + } else if ((pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (!CHECK_PORT_BEING_FLUSHED(pExynosPort))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> wait(bufferSemID)", + pExynosComponent, __FUNCTION__); + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output port -> post(bufferSemID)", + pExynosComponent, __FUNCTION__); + + pMessage = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (pMessage == NULL) { + pBufferHdr = NULL; + goto EXIT; + } + if (pMessage->type == EXYNOS_OMX_CommandFakeBuffer) { + Exynos_OSAL_Free(pMessage); + pBufferHdr = NULL; + goto EXIT; + } + + pBufferHdr = (OMX_BUFFERHEADERTYPE *)(pMessage->pCmdData); + Exynos_OSAL_Free(pMessage); + } + +EXIT: + FunctionOut(); + + return pBufferHdr; +} + +OMX_ERRORTYPE Exynos_CodecBufferEnqueue( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nPortIndex, + OMX_PTR pData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &(pExynosComponent->pExynosPort[nPortIndex]); + + if (pData == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = Exynos_OSAL_Queue(&pExynosPort->codecBufferQ, (void *)pData); + if (ret != 0) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + Exynos_OSAL_SemaphorePost(pExynosPort->codecSemID); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_CodecBufferDequeue( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nPortIndex, + OMX_PTR *pData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_PTR pTempData = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &(pExynosComponent->pExynosPort[nPortIndex]); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port -> wait(codecSemID)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + Exynos_OSAL_SemaphoreWait(pExynosPort->codecSemID); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port -> post(codecSemID)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + + pTempData = (OMX_PTR)Exynos_OSAL_Dequeue(&pExynosPort->codecBufferQ); + if (pTempData != NULL) { + *pData = (OMX_PTR)pTempData; + ret = OMX_ErrorNone; + } else { + *pData = NULL; + ret = OMX_ErrorUndefined; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_CodecBufferReset( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &(pExynosComponent->pExynosPort[nPortIndex]); + + ret = Exynos_OSAL_ResetQueue(&pExynosPort->codecBufferQ); + if (ret != 0) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + while (1) { + OMX_S32 cnt = 0; + Exynos_OSAL_Get_SemaphoreCount(pExynosPort->codecSemID, &cnt); + if (cnt > 0) + Exynos_OSAL_SemaphoreWait(pExynosPort->codecSemID); + else + break; + } + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeGetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *pPortParam = (OMX_PORT_PARAM_TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pPortParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pPortParam->nPorts = pExynosComponent->portParam.nPorts; + pPortParam->nStartPortNumber = pExynosComponent->portParam.nStartPortNumber; + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *pPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortFormat->nPortIndex; + OMX_U32 nIndex = pPortFormat->nIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (nIndex > (INPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pPortDef = &pExynosPort->portDefinition; + + pPortFormat->eCompressionFormat = OMX_VIDEO_CodingUnused; + pPortFormat->xFramerate = pPortDef->format.video.xFramerate; + + if (pExynosPort->supportFormat[nIndex] == OMX_COLOR_FormatUnused) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + pPortFormat->eColorFormat = pExynosPort->supportFormat[nIndex]; + } else if (nPortIndex == OUTPUT_PORT_INDEX) { + if (nIndex > (OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pPortDef = &pExynosPort->portDefinition; + + pPortFormat->eCompressionFormat = pPortDef->format.video.eCompressionFormat; + pPortFormat->xFramerate = pPortDef->format.video.xFramerate; + pPortFormat->eColorFormat = pPortDef->format.video.eColorFormat; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE *pVideoBitrate = (OMX_VIDEO_PARAM_BITRATETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoBitrate->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pPortDef = &pExynosPort->portDefinition; + + pVideoBitrate->eControlRate = pVideoEnc->eControlRate[nPortIndex]; + pVideoBitrate->nTargetBitrate = pPortDef->format.video.nBitrate; + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoQuantization: + { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *pVideoQuantization = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoQuantization->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pPortDef = &pExynosPort->portDefinition; + + pVideoQuantization->nQpI = pVideoEnc->quantization.nQpI; + pVideoQuantization->nQpP = pVideoEnc->quantization.nQpP; + pVideoQuantization->nQpB = pVideoEnc->quantization.nQpB; + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortDef->nPortIndex; + ret = Exynos_OMX_GetParameter(hComponent, nParamIndex, pComponentParameterStructure); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = Exynos_OSAL_GetParameter(hComponent, nParamIndex, pComponentParameterStructure); + if (ret != OMX_ErrorNone) + goto EXIT; + } + break; + case OMX_IndexVendorNeedContigMemory: + { + EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *pPortMemType = (EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortMemType->nPortIndex; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortMemType, sizeof(EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + pPortMemType->bNeedContigMem = pExynosPort->bNeedContigMem; + } + break; + case OMX_IndexParamVideoIntraRefresh: + { + OMX_VIDEO_PARAM_INTRAREFRESHTYPE *pIntraRefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pIntraRefresh->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pIntraRefresh, sizeof(OMX_VIDEO_PARAM_INTRAREFRESHTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pIntraRefresh->eRefreshMode = pVideoEnc->intraRefresh.eRefreshMode; + pIntraRefresh->nAirMBs = pVideoEnc->intraRefresh.nAirMBs; + pIntraRefresh->nAirRef = pVideoEnc->intraRefresh.nAirRef; + pIntraRefresh->nCirMBs = pVideoEnc->intraRefresh.nCirMBs; + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamRotationInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *pRotationInfo = (EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *)pComponentParameterStructure; + OMX_U32 nPortIndex = pRotationInfo->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pRotationInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pRotationInfo->eRotationType = pVideoEnc->eRotationType; + } + break; + case OMX_IndexParamVideoDropControl: + { + OMX_CONFIG_BOOLEANTYPE *pDropControl = (OMX_CONFIG_BOOLEANTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDropControl, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDropControl->bEnabled = pVideoEnc->bDropControl; + } + break; + case OMX_IndexParamVideoDisableDFR: + { + OMX_CONFIG_BOOLEANTYPE *pDisableDFR = (OMX_CONFIG_BOOLEANTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDisableDFR, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDisableDFR->bEnabled = pVideoEnc->bDisableDFR; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamConsumerUsageBits: + { + ret = Exynos_OSAL_GetParameter(hComponent, nParamIndex, pComponentParameterStructure); + } + break; +#endif + default: + { + ret = Exynos_OMX_GetParameter(hComponent, nParamIndex, pComponentParameterStructure); + } + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeSetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *pPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortFormat->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pPortDef = &(pExynosComponent->pExynosPort[nPortIndex].portDefinition); + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pPortFormat->xFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] xFramerate is invalid(%d)", + pExynosComponent, __FUNCTION__, pPortFormat->xFramerate >> 16); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pPortDef->format.video.eColorFormat = pPortFormat->eColorFormat; + pPortDef->format.video.eCompressionFormat = pPortFormat->eCompressionFormat; + pPortDef->format.video.xFramerate = pPortFormat->xFramerate; + } + break; + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE *pVideoBitrate = (OMX_VIDEO_PARAM_BITRATETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoBitrate->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pPortDef = &(pExynosComponent->pExynosPort[nPortIndex].portDefinition); + pVideoEnc->eControlRate[nPortIndex] = pVideoBitrate->eControlRate; + pPortDef->format.video.nBitrate = pVideoBitrate->nTargetBitrate; + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoQuantization: + { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *pVideoQuantization = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoQuantization->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pPortDef = &pExynosPort->portDefinition; + + pVideoEnc->quantization.nQpI = pVideoQuantization->nQpI; + pVideoEnc->quantization.nQpP = pVideoQuantization->nQpP; + pVideoEnc->quantization.nQpB = pVideoQuantization->nQpB; + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortDef->nPortIndex; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + if (pPortDef->nBufferCountActual < pExynosPort->portDefinition.nBufferCountMin) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pPortDef->format.video.xFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s[%x] xFramerate is invalid(%d)", + __FUNCTION__, OMX_IndexParamPortDefinition, pPortDef->format.video.xFramerate >> 16); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Memcpy(((char *)&pExynosPort->portDefinition) + nOffset, + ((char *)pPortDef) + nOffset, + pPortDef->nSize - nOffset); + if (nPortIndex == INPUT_PORT_INDEX) { + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + Exynos_UpdateFrameSize(pOMXComponent); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] the size of output buffer is %d", + pExynosComponent, __FUNCTION__, pExynosPort->portDefinition.nBufferSize); + } + ret = OMX_ErrorNone; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamStoreMetaDataBuffer: + case OMX_IndexParamAllocateNativeHandle: + { + ret = Exynos_OSAL_SetParameter(hComponent, nParamIndex, pComponentParameterStructure); + } + break; +#endif + case OMX_IndexVendorNeedContigMemory: + { + EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *pPortMemType = (EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortMemType->nPortIndex; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortMemType, sizeof(EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + pExynosPort->bNeedContigMem = pPortMemType->bNeedContigMem; + } + break; + case OMX_IndexParamVideoIntraRefresh: + { + OMX_VIDEO_PARAM_INTRAREFRESHTYPE *pIntraRefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pIntraRefresh->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pIntraRefresh, sizeof(OMX_VIDEO_PARAM_INTRAREFRESHTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pIntraRefresh->eRefreshMode == OMX_VIDEO_IntraRefreshCyclic) { + pVideoEnc->intraRefresh.eRefreshMode = pIntraRefresh->eRefreshMode; + pVideoEnc->intraRefresh.nCirMBs = pIntraRefresh->nCirMBs; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX_VIDEO_IntraRefreshCyclic Enable, nCirMBs: %d", + pVideoEnc->intraRefresh.nCirMBs); + } else { + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamEnableBlurFilter: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_BLURFILTER *pBlurMode = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_BLURFILTER *)pComponentParameterStructure; + OMX_U32 nPortIndex = pBlurMode->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pBlurMode, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_BLURFILTER)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pVideoEnc->bUseBlurFilter = pBlurMode->bUseBlurFilter; + } + break; + case OMX_IndexParamRotationInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *pRotationInfo = (EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *)pComponentParameterStructure; + OMX_U32 nPortIndex = pRotationInfo->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pRotationInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pVideoEnc->bFirstInput != OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] can't change a rotation info", pExynosComponent, __FUNCTION__); + } else { + if ((pRotationInfo->eRotationType != ROTATE_0) && + (pRotationInfo->eRotationType != ROTATE_90) && + (pRotationInfo->eRotationType != ROTATE_180) && + (pRotationInfo->eRotationType != ROTATE_270)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] can't accecpt a rotation value(%d)", pExynosComponent, __FUNCTION__, + pRotationInfo->eRotationType); + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + pVideoEnc->eRotationType = pRotationInfo->eRotationType; + } + } + break; + case OMX_IndexExynosParamImageCrop: + { + EXYNOS_OMX_VIDEO_PARAM_IMAGE_CROP *pImageCrop = (EXYNOS_OMX_VIDEO_PARAM_IMAGE_CROP *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pImageCrop, sizeof(EXYNOS_OMX_VIDEO_PARAM_IMAGE_CROP)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + pExynosComponent->bUseImgCrop = pImageCrop->bEnabled; + + if (pExynosComponent->bUseImgCrop == OMX_TRUE) { + pExynosPort->bufferProcessType |= BUFFER_COPY_FORCE; + } else { + pExynosPort->bufferProcessType &= (~BUFFER_COPY_FORCE); + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoDropControl: + { + OMX_CONFIG_BOOLEANTYPE *pDropControl = (OMX_CONFIG_BOOLEANTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDropControl, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoEnc->bDropControl = pDropControl->bEnabled; + } + break; + case OMX_IndexParamVideoDisableDFR: + { + OMX_CONFIG_BOOLEANTYPE *pDisableDFR = (OMX_CONFIG_BOOLEANTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDisableDFR, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoEnc->bDisableDFR = pDisableDFR->bEnabled; + } + break; + default: + { + ret = Exynos_OMX_SetParameter(hComponent, nParamIndex, pComponentParameterStructure); + } + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeGetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nParamIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigBitrate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pConfigBitrate->nEncodeBitrate = pExynosPort->portDefinition.format.video.nBitrate; + } + } + break; + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pConfigFramerate->xEncodeFramerate = pExynosPort->portDefinition.format.video.xFramerate; + } + break; + case OMX_IndexVendorGetBufferFD: + { + EXYNOS_OMX_VIDEO_CONFIG_BUFFERINFO *pBufferInfo = (EXYNOS_OMX_VIDEO_CONFIG_BUFFERINFO *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pBufferInfo, sizeof(EXYNOS_OMX_VIDEO_CONFIG_BUFFERINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pBufferInfo->fd = Exynos_OSAL_SharedMemory_VirtToION(pVideoEnc->hSharedMemory, pBufferInfo->pVirAddr); + } + break; + case OMX_IndexConfigCommonInputCrop: + { + OMX_CONFIG_RECTTYPE *pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pSrcRectType = &(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].cropRectangle[IMG_CROP_INPUT_PORT]); + + if (pDstRectType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + ret = OMX_ErrorIncorrectStateOperation; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Need OMX_IndexExynosParamEnableCrop set", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + break; + case OMX_IndexConfigCommonOutputCrop: + { + OMX_CONFIG_RECTTYPE *pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pSrcRectType = &(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].cropRectangle[IMG_CROP_OUTPUT_PORT]); + + if (pDstRectType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] image cropping is not enabled.", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + break; + case OMX_IndexConfigCommonMirror: + { + OMX_CONFIG_MIRRORTYPE *pMirror = (OMX_CONFIG_MIRRORTYPE *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pMirror, sizeof(OMX_CONFIG_MIRRORTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pMirror->eMirror = pVideoEnc->eMirrorType; + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigVideoColorAspects: + { + ret = Exynos_OSAL_GetConfig(hComponent, nParamIndex, pComponentConfigStructure); + } + break; + case OMX_IndexConfigAndroidVendorExtension: + { + ret = Exynos_OSAL_GetVendorExt(hComponent, pComponentConfigStructure); + } + break; +#endif + default: + { + ret = Exynos_OMX_GetConfig(hComponent, nParamIndex, pComponentConfigStructure); + } + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeSetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nParamIndex, + OMX_PTR pComponentConfigStructure) + { + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigBitrate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + if (pVideoEnc->eControlRate[nPortIndex] == OMX_Video_ControlRateDisable) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Rate control(eControlRate) is disable. can not change a bitrate", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pExynosPort->portDefinition.format.video.nBitrate = pConfigBitrate->nEncodeBitrate; + } + } + break; + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pConfigFramerate->xEncodeFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] xFramerate is invalid(%d)", + pExynosComponent, __FUNCTION__, pConfigFramerate->xEncodeFramerate >> 16); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pExynosPort->portDefinition.format.video.xFramerate = pConfigFramerate->xEncodeFramerate; + } + break; + case OMX_IndexConfigVideoIntraVOPRefresh: + { + OMX_CONFIG_INTRAREFRESHVOPTYPE *pIntraRefreshVOP = (OMX_CONFIG_INTRAREFRESHVOPTYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pIntraRefreshVOP->nPortIndex; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pVideoEnc->IntraRefreshVOP = pIntraRefreshVOP->IntraRefreshVOP; + } + } + break; + case OMX_IndexConfigOperatingRate: /* since M version */ + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pComponentConfigStructure; + OMX_U32 xFramerate = 0; + + ret = Exynos_OMX_Check_SizeVersion(pConfigRate, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + pVideoEnc->nQosRatio = pConfigRate->nU32 >> 16; + + if (pVideoEnc->nQosRatio == (((OMX_U32)INT_MAX) >> 16)) { + pVideoEnc->nQosRatio = 1000; + } else { + pVideoEnc->nQosRatio = ((xFramerate >> 16) == 0)? 100:(OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + } + + pVideoEnc->bQosChanged = OMX_TRUE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qos ratio: 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->nQosRatio); + + ret = OMX_ErrorNone; + } + case OMX_IndexConfigPriority: + { + OMX_PARAM_U32TYPE *pPriority = (OMX_PARAM_U32TYPE *)pComponentConfigStructure; + OMX_U32 priority = 0; + + ret = Exynos_OMX_Check_SizeVersion(pPriority, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoEnc->nPriority = pPriority->nU32;; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] priority : 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->nPriority); + + ret = OMX_ErrorNone; + } + break; + break; + case OMX_IndexConfigBlurInfo: + { + EXYNOS_OMX_VIDEO_CONFIG_BLURINFO *pBlurMode = (EXYNOS_OMX_VIDEO_CONFIG_BLURINFO *)pComponentConfigStructure; + OMX_U32 nPortIndex = pBlurMode->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + int nEncResol; + + ret = Exynos_OMX_Check_SizeVersion(pBlurMode, sizeof(EXYNOS_OMX_VIDEO_CONFIG_BLURINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + nEncResol = pExynosPort->portDefinition.format.video.nFrameWidth * pExynosPort->portDefinition.format.video.nFrameHeight; + + if (pVideoEnc->bUseBlurFilter == OMX_TRUE) { + if ((pBlurMode->eBlurMode & BLUR_MODE_DOWNUP) && + (nEncResol < (int)pBlurMode->eTargetResol)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Resolution(%d x %d) is smaller than target resolution", + pExynosComponent, __FUNCTION__, + pExynosPort->portDefinition.format.video.nFrameWidth, + pExynosPort->portDefinition.format.video.nFrameHeight); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc->eBlurMode = pBlurMode->eBlurMode; + pVideoEnc->eBlurResol = pBlurMode->eTargetResol; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Blur Filter is not enabled, it will be discard", + pExynosComponent, __FUNCTION__); + } + + ret = (OMX_ERRORTYPE)OMX_ErrorNoneExpiration; + } + break; + case OMX_IndexConfigCommonInputCrop: + { + OMX_CONFIG_RECTTYPE *pSrcRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pDstRectType = &(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].cropRectangle[IMG_CROP_INPUT_PORT]); + + if (pSrcRectType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] image cropping is not enabled.", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bUseImgCrop[IMG_CROP_INPUT_PORT] = OMX_TRUE; + } + break; + case OMX_IndexConfigCommonOutputCrop: + { + OMX_CONFIG_RECTTYPE *pSrcRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pDstRectType = &(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].cropRectangle[IMG_CROP_OUTPUT_PORT]); + + if (pSrcRectType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] image cropping is not enabled.", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + /* positioning is not supported yet when DRC is required */ + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] positioning is not supported yet when DRC is required", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bUseImgCrop[IMG_CROP_OUTPUT_PORT] = OMX_TRUE; + } + break; + case OMX_IndexConfigCommonOutputSize: + { + OMX_FRAMESIZETYPE *pFrameSize = (OMX_FRAMESIZETYPE *)pComponentConfigStructure; + OMX_CONFIG_RECTTYPE *pTargetFrame = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pFrameSize, sizeof(OMX_FRAMESIZETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pFrameSize->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pOutputPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + pTargetFrame = &(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT]); + + /* the size of target resolution can not be bigger than the size set on output port */ + if ((pFrameSize->nWidth > pOutputPort->portDefinition.format.video.nFrameWidth) || + (pFrameSize->nHeight > pOutputPort->portDefinition.format.video.nFrameHeight)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] target size(%d x %d) is bigger than output(%d x %d)", + pExynosComponent, __FUNCTION__, + pFrameSize->nWidth, + pFrameSize->nHeight, + pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight); + goto EXIT; + } + + if (pVideoEnc->bFirstInput == OMX_TRUE) { + pExynosComponent->bUseImgCrop = OMX_TRUE; + pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] = OMX_TRUE; + + /* must use BUFFER_COPY */ + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bufferProcessType |= BUFFER_COPY_FORCE; + /* positioning is not supported yet when DRC is required */ + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].bUseImgCrop[IMG_CROP_OUTPUT_PORT] = OMX_FALSE; + + /* update target size */ + pTargetFrame->nTop = 0; + pTargetFrame->nLeft = 0; + pTargetFrame->nWidth = pFrameSize->nWidth; + pTargetFrame->nHeight = pFrameSize->nHeight; + + ret = (OMX_ERRORTYPE)OMX_ErrorNoneExpiration; + } else { + if (pExynosComponent->bUseImgCrop == OMX_FALSE) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] CommonOutputSize must be enabled before sending first input", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + /* + * postpone to update target size. + * it will be updated at dynamic config Q with DRC handling + */ + ret = OMX_ErrorNone; + } + } + break; + case OMX_IndexConfigCommonRotate: + { + OMX_CONFIG_ROTATIONTYPE *pRotationInfo = (OMX_CONFIG_ROTATIONTYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pRotationInfo->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pRotationInfo, sizeof(OMX_CONFIG_ROTATIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pVideoEnc->bFirstInput != OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] can't change a rotation info", pExynosComponent, __FUNCTION__); + } else { + if ((pRotationInfo->nRotation != ROTATE_0) && + (pRotationInfo->nRotation != ROTATE_90) && + (pRotationInfo->nRotation != ROTATE_180) && + (pRotationInfo->nRotation != ROTATE_270)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] can't accecpt a rotation value(%d)", pExynosComponent, __FUNCTION__, + pRotationInfo->nRotation); + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + pVideoEnc->eRotationType = (EXYNOS_OMX_ROTATION_TYPE)pRotationInfo->nRotation; + } + } + break; + case OMX_IndexConfigCommonMirror: + { + OMX_CONFIG_MIRRORTYPE *pMirror = (OMX_CONFIG_MIRRORTYPE *)pComponentConfigStructure; + OMX_BOOL bVerticalFlip; + + ret = Exynos_OMX_Check_SizeVersion(pMirror, sizeof(OMX_CONFIG_MIRRORTYPE)); + if (pMirror->nPortIndex != INPUT_PORT_INDEX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid port index", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StateInvalid) || + (pExynosComponent->transientState == EXYNOS_OMX_TransStateIdleToLoaded)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid state(0x%x)", pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((pMirror->eMirror != OMX_MirrorHorizontal) && + (pMirror->eMirror != OMX_MirrorVertical) && + (pMirror->eMirror != OMX_MirrorBoth)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + pVideoEnc->eMirrorType = pMirror->eMirror; + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigVideoColorAspects: + { + ret = Exynos_OSAL_SetConfig(hComponent, nParamIndex, pComponentConfigStructure); + } + break; + case OMX_IndexConfigAndroidVendorExtension: + { + ret = Exynos_OSAL_SetVendorExt(hComponent, pComponentConfigStructure); + if (ret == OMX_ErrorNone) + ret = (OMX_ERRORTYPE)OMX_ErrorNoneExpiration; + } + break; +#endif + default: + { + ret = Exynos_OMX_SetConfig(hComponent, nParamIndex, pComponentConfigStructure); + } + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeGetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING szParamName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (szParamName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_CONFIG_VIDEO_INTRAPERIOD) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigVideoIntraPeriod; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_PARAM_NEED_CONTIG_MEMORY) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorNeedContigMemory; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_CONFIG_GET_BUFFER_FD) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorGetBufferFD; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_PARAM_VIDEO_QPRANGE_TYPE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamVideoQPRange; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_CONFIG_VIDEO_QPRANGE_TYPE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoQPRange; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_PARAM_ENABLE_BLUR_FILTER) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamEnableBlurFilter; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_CONFIG_BLUR_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigBlurInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_PARAM_ROATION_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamRotationInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_ANDROID + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_PARAM_STORE_METADATA_BUFFER) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamStoreMetaDataBuffer; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_CONFIG_VIDEO_COLOR_ASPECTS_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoColorAspects; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_PARAM_ALLOCATE_NATIVE_HANDLE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamAllocateNativeHandle; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + ret = Exynos_OMX_GetExtensionIndex(hComponent, szParamName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Shared_BufferToData( + EXYNOS_OMX_BASEPORT *pExynosPort, + EXYNOS_OMX_DATABUFFER *pUseBuffer, + EXYNOS_OMX_DATA *pData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((pExynosPort == NULL) || + (pUseBuffer == NULL) || + (pData == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((pUseBuffer->bufferHeader == NULL) || + (pUseBuffer->bufferHeader->pBuffer == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pExynosPort->exceptionFlag != GENERAL_STATE) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if (pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED) { + pData->buffer.addr[0] = pUseBuffer->bufferHeader->pBuffer; + } else { + /* metadata type */ + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + + if (pExynosPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) { + EXYNOS_OMX_LOCK_RANGE range; + OMX_U32 stride; + + range.nWidth = pExynosPort->portDefinition.format.video.nFrameWidth; + range.nHeight = pExynosPort->portDefinition.format.video.nFrameHeight; + range.eColorFormat = pExynosPort->portDefinition.format.video.eColorFormat; + stride = range.nWidth; + + ret = Exynos_OSAL_LockMetaData(pUseBuffer->bufferHeader->pBuffer, + range, + &stride, &bufferInfo, + pExynosPort->eMetaDataType); + if (ret != OMX_ErrorNone) { + /* if dataLen is zero with EOS flag, it is not an error. + * in this case, buffer handle can be null by framework. + */ + if ((pUseBuffer->dataLen <= 0) && + (pUseBuffer->nFlags & OMX_BUFFERFLAG_EOS)) { + pData->allocSize = pUseBuffer->allocSize; + pData->dataLen = pUseBuffer->dataLen; + pData->usedDataLen = pUseBuffer->usedDataLen; + pData->remainDataLen = pUseBuffer->remainDataLen; + pData->timeStamp = pUseBuffer->timeStamp; + pData->nFlags = pUseBuffer->nFlags; + pData->pPrivate = pUseBuffer->pPrivate; + pData->bufferHeader = pUseBuffer->bufferHeader; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s]: Failed to Exynos_OSAL_LockMetaData() but, this buffer is for EOS handling.", __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s]: Failed to Exynos_OSAL_LockMetaData (err:0x%x)", + __FUNCTION__, ret); + goto EXIT; + } + } else { + ret = Exynos_OSAL_GetInfoFromMetaData(pUseBuffer->bufferHeader->pBuffer, + &bufferInfo, pExynosPort->eMetaDataType); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s]: Failed to Exynos_OSAL_GetInfoFromMetaData (err:0x%x)", + __FUNCTION__, ret); + goto EXIT; + } + } + + pData->buffer.addr[0] = bufferInfo.addr[0]; + pData->buffer.addr[1] = bufferInfo.addr[1]; + pData->buffer.addr[2] = bufferInfo.addr[2]; + + pData->buffer.fd[0] = bufferInfo.fd[0]; + pData->buffer.fd[1] = bufferInfo.fd[1]; + pData->buffer.fd[2] = bufferInfo.fd[2]; + } + + pData->allocSize = pUseBuffer->allocSize; + pData->dataLen = pUseBuffer->dataLen; + pData->usedDataLen = pUseBuffer->usedDataLen; + pData->remainDataLen = pUseBuffer->remainDataLen; + pData->timeStamp = pUseBuffer->timeStamp; + pData->nFlags = pUseBuffer->nFlags; + pData->pPrivate = pUseBuffer->pPrivate; + pData->bufferHeader = pUseBuffer->bufferHeader; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Shared_DataToBuffer( + EXYNOS_OMX_BASEPORT *pExynosPort, + EXYNOS_OMX_DATABUFFER *pUseBuffer, + EXYNOS_OMX_DATA *pData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((pExynosPort == NULL) || + (pUseBuffer == NULL) || + (pData == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((pData->bufferHeader == NULL) || + (pData->bufferHeader->pBuffer == NULL)) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pUseBuffer->bufferHeader = pData->bufferHeader; + pUseBuffer->allocSize = pData->allocSize; + pUseBuffer->dataLen = pData->dataLen; + pUseBuffer->usedDataLen = pData->usedDataLen; + pUseBuffer->remainDataLen = pData->remainDataLen; + pUseBuffer->timeStamp = pData->timeStamp; + pUseBuffer->nFlags = pData->nFlags; + pUseBuffer->pPrivate = pData->pPrivate; + + if (pExynosPort->eMetaDataType & METADATA_TYPE_BUFFER_LOCK) + Exynos_OSAL_UnlockMetaData(pUseBuffer->bufferHeader->pBuffer, pExynosPort->eMetaDataType); + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/enc/Exynos_OMX_VencControl.h b/openmax/component/video/enc/Exynos_OMX_VencControl.h new file mode 100644 index 0000000..985446a --- /dev/null +++ b/openmax/component/video/enc/Exynos_OMX_VencControl.h @@ -0,0 +1,118 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_VencControl.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.5.0 + * @history + * 2012.02.20 : Create + * 2017.08.03 : Change event handling + */ + +#ifndef EXYNOS_OMX_VIDEO_ENCODECONTROL +#define EXYNOS_OMX_VIDEO_ENCODECONTROL + +#include "OMX_Component.h" +#include "Exynos_OMX_Def.h" +#include "Exynos_OSAL_Queue.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Basecomponent.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer); +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes); +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr); + +#ifdef TUNNELING_SUPPORT +OMX_ERRORTYPE Exynos_OMX_AllocateTunnelBuffer( + EXYNOS_OMX_BASEPORT *pOMXBasePort, + OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_FreeTunnelBuffer( + EXYNOS_OMX_BASEPORT *pOMXBasePort, + OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_OMX_ComponentTunnelRequest( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 nPort, + OMX_IN OMX_HANDLETYPE hTunneledComp, + OMX_IN OMX_U32 nTunneledPort, + OMX_INOUT OMX_TUNNELSETUPTYPE *pTunnelSetup); +#endif + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeGetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure); +OMX_ERRORTYPE Exynos_OMX_VideoEncodeSetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure); +OMX_ERRORTYPE Exynos_OMX_VideoEncodeGetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure); +OMX_ERRORTYPE Exynos_OMX_VideoEncodeSetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure); +OMX_ERRORTYPE Exynos_OMX_VideoEncodeGetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING szParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType); + +OMX_ERRORTYPE Exynos_InputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATABUFFER *pDataBuffer); +OMX_ERRORTYPE Exynos_OutputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, EXYNOS_OMX_DATABUFFER *pDataBuffer); + +OMX_ERRORTYPE Exynos_OMX_BufferFlush(OMX_COMPONENTTYPE *pOMXComponent, OMX_S32 nPortIndex, OMX_BOOL bEvent); + +OMX_BUFFERHEADERTYPE *Exynos_OutputBufferGetQueue_Direct(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +OMX_ERRORTYPE Exynos_InputBufferGetQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +OMX_ERRORTYPE Exynos_OutputBufferGetQueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); + +OMX_ERRORTYPE Exynos_CodecBufferEnqueue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex, OMX_PTR pData); +OMX_ERRORTYPE Exynos_CodecBufferDequeue(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex, OMX_PTR *pData); +OMX_ERRORTYPE Exynos_CodecBufferReset(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nPortIndex); + +OMX_ERRORTYPE Exynos_Shared_BufferToData(EXYNOS_OMX_BASEPORT *pExynosPort, EXYNOS_OMX_DATABUFFER *pUseBuffer, EXYNOS_OMX_DATA *pData); +OMX_ERRORTYPE Exynos_Shared_DataToBuffer(EXYNOS_OMX_BASEPORT *pExynosPort, EXYNOS_OMX_DATABUFFER *pUseBuffer, EXYNOS_OMX_DATA *pData); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/openmax/component/video/enc/NOTICE b/openmax/component/video/enc/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/enc/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/enc/h264/Android.mk b/openmax/component/video/enc/h264/Android.mk new file mode 100644 index 0000000..df65723 --- /dev/null +++ b/openmax/component/video/enc/h264/Android.mk @@ -0,0 +1,89 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_H264enc.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.AVC.Encoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Venc libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/enc \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_SKYPE_HD), true) +LOCAL_CFLAGS += -DUSE_SKYPE_HD +LOCAL_CFLAGS += -DBUILD_ENC +LOCAL_STATIC_LIBRARIES += libExynosOMX_SkypeHD_Enc +endif + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_SMALL_SECURE_MEMORY), true) +LOCAL_CFLAGS += -DUSE_SMALL_SECURE_MEMORY +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/enc/h264/Exynos_OMX_H264enc.c b/openmax/component/video/enc/h264/Exynos_OMX_H264enc.c new file mode 100644 index 0000000..c092c7c --- /dev/null +++ b/openmax/component/video/enc/h264/Exynos_OMX_H264enc.c @@ -0,0 +1,4567 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_H264enc.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Venc.h" +#include "Exynos_OMX_VencControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OMX_H264enc.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OSAL_Queue.h" + +#include "Exynos_OSAL_Platform.h" + +#include "VendorVideoAPI.h" + +#ifdef USE_SKYPE_HD +#include "Exynos_OSAL_SkypeHD.h" +#endif + +/* To use CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */ +/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_H264_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.profiles[nProfileCnt++] = OMX_VIDEO_AVCProfileBaseline; + pH264Enc->hMFCH264Handle.profiles[nProfileCnt++] = OMX_VIDEO_AVCProfileMain; + pH264Enc->hMFCH264Handle.profiles[nProfileCnt++] = OMX_VIDEO_AVCProfileHigh; + pH264Enc->hMFCH264Handle.profiles[nProfileCnt++] = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedBaseline; + pH264Enc->hMFCH264Handle.profiles[nProfileCnt++] = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedHigh; + pH264Enc->hMFCH264Handle.nProfileCnt = nProfileCnt; + + switch (pH264Enc->hMFCH264Handle.videoInstInfo.HwVersion) { + case MFC_1501: + case MFC_150: + pH264Enc->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel6; + break; + case MFC_1400: + case MFC_1410: + case MFC_140: + case MFC_130: + case MFC_120: + case MFC_1220: + case MFC_110: + case MFC_100: + case MFC_101: + pH264Enc->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel52; + break; + case MFC_80: + case MFC_90: + case MFC_1010: + case MFC_1120: + pH264Enc->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel51; + break; + case MFC_61: + case MFC_65: + case MFC_72: + case MFC_723: + case MFC_77: + case MFC_1011: + case MFC_1021: + pH264Enc->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel42; + break; + case MFC_51: + case MFC_78: + case MFC_78D: + case MFC_92: + case MFC_1020: + default: + pH264Enc->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel4; + break; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + int nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pH264Enc->hMFCH264Handle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pH264Enc->hMFCH264Handle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pH264Enc->hMFCH264Handle.maxLevel; +#else + while ((pH264Enc->hMFCH264Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pH264Enc->hMFCH264Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pH264Enc->hMFCH264Handle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pH264Enc->hMFCH264Handle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) + goto EXIT; + + while ((pH264Enc->hMFCH264Handle.maxLevel >> nLevelCnt++) > 0); + + if ((pH264Enc->hMFCH264Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pH264Enc->hMFCH264Handle.nProfileCnt; i++) { + if (pH264Enc->hMFCH264Handle.profiles[i] == pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +static OMX_U32 OMXAVCProfileToProfileIDC(OMX_VIDEO_AVCPROFILETYPE profile) +{ + OMX_U32 ret = 0; + + if (profile == OMX_VIDEO_AVCProfileBaseline) + ret = 0; + else if ((OMX_VIDEO_AVCPROFILEEXTTYPE)profile == OMX_VIDEO_AVCProfileConstrainedBaseline) + ret = 1; + else if (profile == OMX_VIDEO_AVCProfileMain) + ret = 2; + else if (profile == OMX_VIDEO_AVCProfileHigh) + ret = 4; + else if ((OMX_VIDEO_AVCPROFILEEXTTYPE)profile == OMX_VIDEO_AVCProfileConstrainedHigh) + ret = 17; + + return ret; +} + +static OMX_U32 OMXAVCLevelToLevelIDC(OMX_VIDEO_AVCLEVELTYPE level) +{ + OMX_U32 ret = 11; //default OMX_VIDEO_AVCLevel4 + + if (level == OMX_VIDEO_AVCLevel1) + ret = 0; + else if (level == OMX_VIDEO_AVCLevel1b) + ret = 1; + else if (level == OMX_VIDEO_AVCLevel11) + ret = 2; + else if (level == OMX_VIDEO_AVCLevel12) + ret = 3; + else if (level == OMX_VIDEO_AVCLevel13) + ret = 4; + else if (level == OMX_VIDEO_AVCLevel2) + ret = 5; + else if (level == OMX_VIDEO_AVCLevel21) + ret = 6; + else if (level == OMX_VIDEO_AVCLevel22) + ret = 7; + else if (level == OMX_VIDEO_AVCLevel3) + ret = 8; + else if (level == OMX_VIDEO_AVCLevel31) + ret = 9; + else if (level == OMX_VIDEO_AVCLevel32) + ret = 10; + else if (level == OMX_VIDEO_AVCLevel4) + ret = 11; + else if (level == OMX_VIDEO_AVCLevel41) + ret = 12; + else if (level == OMX_VIDEO_AVCLevel42) + ret = 13; + else if (level == OMX_VIDEO_AVCLevel5) + ret = 14; + else if (level == OMX_VIDEO_AVCLevel51) + ret = 15; + else if (level == OMX_VIDEO_AVCLevel52) + ret = 16; + else if (level == OMX_VIDEO_AVCLevel6) + ret = 17; + + return ret; +} + +static OMX_U8 *FindDelimiter(OMX_U8 *pBuffer, OMX_U32 size) +{ + OMX_U32 i; + + for (i = 0; i < size - 3; i++) { + if ((pBuffer[i] == 0x00) && + (pBuffer[i + 1] == 0x00) && + (pBuffer[i + 2] == 0x00) && + (pBuffer[i + 3] == 0x01)) + return (pBuffer + i); + } + + return NULL; +} + +static void Print_H264Enc_Param(ExynosVideoEncParam *pEncParam) +{ + ExynosVideoEncCommonParam *pCommonParam = &pEncParam->commonParam; + ExynosVideoEncH264Param *pH264Param = &pEncParam->codecParam.h264; + + /* common parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceWidth : %d", pCommonParam->SourceWidth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceHeight : %d", pCommonParam->SourceHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "IDRPeriod : %d", pCommonParam->IDRPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SliceMode : %d", pCommonParam->SliceMode); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RandomIntraMBRefresh : %d", pCommonParam->RandomIntraMBRefresh); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Bitrate : %d", pCommonParam->Bitrate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp : %d", pCommonParam->FrameQp); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_P : %d", pCommonParam->FrameQp_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(I) ranege : %d / %d", pCommonParam->QpRange.QpMin_I, pCommonParam->QpRange.QpMax_I); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(P) ranege : %d / %d", pCommonParam->QpRange.QpMin_P, pCommonParam->QpRange.QpMax_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(B) ranege : %d / %d", pCommonParam->QpRange.QpMin_B, pCommonParam->QpRange.QpMax_B); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DropControl : %d", pCommonParam->bDropControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DisableDFR : %d", pCommonParam->bDisableDFR); + + /* H.264 specific parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "ProfileIDC : %d", pH264Param->ProfileIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LevelIDC : %d", pH264Param->LevelIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_B : %d", pH264Param->FrameQp_B); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameRate : %d", pH264Param->FrameRate); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SliceArgument : %d", pH264Param->SliceArgument); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberBFrames : %d", pH264Param->NumberBFrames); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberReferenceFrames : %d", pH264Param->NumberReferenceFrames); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberRefForPframes : %d", pH264Param->NumberRefForPframes); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterDisable : %d", pH264Param->LoopFilterDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterAlphaC0Offset : %d", pH264Param->LoopFilterAlphaC0Offset); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterBetaOffset : %d", pH264Param->LoopFilterBetaOffset); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SymbolMode : %d", pH264Param->SymbolMode); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PictureInterlace : %d", pH264Param->PictureInterlace); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Transform8x8Mode : %d", pH264Param->Transform8x8Mode); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "DarkDisable : %d", pH264Param->DarkDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SmoothDisable : %d", pH264Param->SmoothDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "StaticDisable : %d", pH264Param->StaticDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "ActivityDisable : %d", pH264Param->ActivityDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "HierarType: : %d", pH264Param->HierarType); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "VuiRestrictionEnable: : %d", pH264Param->VuiRestrictionEnable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "HeaderWithIFrame: : %d", pH264Param->HeaderWithIFrame); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SarEnable: : %d", pH264Param->SarEnable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SarIndex: : %d", pH264Param->SarIndex); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SarWidth: : %d", pH264Param->SarWidth); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SarHeight: : %d", pH264Param->SarHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LTRFrames: : %d", pH264Param->LTRFrames); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "ROIEnable: : %d", pH264Param->ROIEnable); + + /* rate control related parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableFRMRateControl : %d", pCommonParam->EnableFRMRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableMBRateControl : %d", pCommonParam->EnableMBRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CBRPeriodRf : %d", pCommonParam->CBRPeriodRf); +} + +static void Set_H264Enc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncInitParam *pInitParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH264Param *pH264Param = NULL; + + OMX_S32 nWidth, nHeight; + int i; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pEncParam = &pMFCH264Handle->encParam; + pInitParam = &pEncParam->initParam; + pCommonParam = &pEncParam->commonParam; + pH264Param = &pEncParam->codecParam.h264; + pEncParam->eCompressionFormat = VIDEO_CODING_AVC; + + /* uses specified target size instead of size on output port */ + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + nWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + + /* common parameters */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + pCommonParam->SourceWidth = nWidth; + pCommonParam->SourceHeight = nHeight; + } else { + pCommonParam->SourceWidth = nHeight; + pCommonParam->SourceHeight = nWidth; + } + pCommonParam->IDRPeriod = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames + 1; + pCommonParam->SliceMode = pH264Enc->AVCSliceFmo.eSliceMode; + pCommonParam->Bitrate = pOutputPort->portDefinition.format.video.nBitrate; + pCommonParam->FrameQp = pVideoEnc->quantization.nQpI; + pCommonParam->FrameQp_P = pVideoEnc->quantization.nQpP; + + pCommonParam->QpRange.QpMin_I = pH264Enc->qpRangeI.nMinQP; + pCommonParam->QpRange.QpMax_I = pH264Enc->qpRangeI.nMaxQP; + pCommonParam->QpRange.QpMin_P = pH264Enc->qpRangeP.nMinQP; + pCommonParam->QpRange.QpMax_P = pH264Enc->qpRangeP.nMaxQP; + pCommonParam->QpRange.QpMin_B = pH264Enc->qpRangeB.nMinQP; + pCommonParam->QpRange.QpMax_B = pH264Enc->qpRangeB.nMaxQP; + + pCommonParam->PadControlOn = 0; /* 0: disable, 1: enable */ + pCommonParam->LumaPadVal = 0; + pCommonParam->CbPadVal = 0; + pCommonParam->CrPadVal = 0; + + if (pVideoEnc->intraRefresh.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic) { + /* Cyclic Mode */ + pCommonParam->RandomIntraMBRefresh = pVideoEnc->intraRefresh.nCirMBs; + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + + /* Perceptual Mode */ + pCommonParam->PerceptualMode = (pVideoEnc->bPVCMode)? VIDEO_TRUE:VIDEO_FALSE; + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + pCommonParam->bDropControl = (pVideoEnc->bDropControl)? VIDEO_TRUE:VIDEO_FALSE; + pCommonParam->bDisableDFR = (pVideoEnc->bDisableDFR)? VIDEO_TRUE:VIDEO_FALSE; + + /* H.264 specific parameters */ + pH264Param->ProfileIDC = OMXAVCProfileToProfileIDC(pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].eProfile); /*0: OMX_VIDEO_AVCProfileMain */ + pH264Param->LevelIDC = OMXAVCLevelToLevelIDC(pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].eLevel); /*40: OMX_VIDEO_AVCLevel4 */ + pH264Param->FrameQp_B = pVideoEnc->quantization.nQpB; + pH264Param->FrameRate = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + if (pH264Enc->AVCSliceFmo.eSliceMode == OMX_VIDEO_SLICEMODE_AVCDefault) { + pH264Param->SliceArgument = 0; /* Slice mb/byte size number */ + + if (pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nSliceHeaderSpacing > 0) { + pCommonParam->SliceMode = OMX_VIDEO_SLICEMODE_AVCMBSlice; + pH264Param->SliceArgument = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nSliceHeaderSpacing; + } + } else { + pH264Param->SliceArgument = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nSliceHeaderSpacing; + } + + pH264Param->NumberBFrames = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nBFrames; /* 0 ~ 2 */ + pH264Param->NumberRefForPframes = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nRefFrames; /* 1 ~ 2 */ + pH264Param->NumberReferenceFrames = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nRefFrames; + + pH264Param->LoopFilterDisable = 0; /* 1: Loop Filter Disable, 0: Filter Enable */ + pH264Param->LoopFilterAlphaC0Offset = 0; + pH264Param->LoopFilterBetaOffset = 0; + pH264Param->SymbolMode = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].bEntropyCodingCABAC; /* 0: CAVLC, 1: CABAC */ + pH264Param->PictureInterlace = 0; + pH264Param->Transform8x8Mode = 1; /* 0: 4x4, 1: allow 8x8 */ + pH264Param->DarkDisable = 1; + pH264Param->SmoothDisable = 1; + pH264Param->StaticDisable = 1; + pH264Param->ActivityDisable = 1; + + /* Chroma QP Offset */ + pH264Param->chromaQPOffset.Cr = pH264Enc->chromaQPOffset.nCr; + pH264Param->chromaQPOffset.Cb = pH264Enc->chromaQPOffset.nCb; + + /* Temporal SVC */ + /* If MaxTemporalLayerCount value is 0, codec supported max value will be set */ + pH264Param->MaxTemporalLayerCount = 0; + pH264Param->TemporalSVC.nTemporalLayerCount = (unsigned int)pH264Enc->nTemporalLayerCount; + +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.bEnableSkypeHD == OMX_TRUE) { + pH264Param->TemporalSVC.nTemporalLayerCount |= GENERAL_TSVC_ENABLE; /* always uses short-term reference */ + pH264Param->MaxTemporalLayerCount = (unsigned int)pH264Enc->nMaxTemporalLayerCount; /* max layer count on short-term reference */ + } +#endif + + if (pH264Enc->bUseTemporalLayerBitrateRatio == OMX_TRUE) { + for (i = 0; i < OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; i++) + pH264Param->TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pH264Enc->nTemporalLayerBitrateRatio[i]; + } else { + for (i = 0; i < OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; i++) + pH264Param->TemporalSVC.nTemporalLayerBitrateRatio[i] = pOutputPort->portDefinition.format.video.nBitrate; + } + + /* Hierarchal P & B */ + if (pH264Enc->nTemporalLayerCountForB > 0) + pH264Param->HierarType = EXYNOS_OMX_Hierarchical_B; + else + pH264Param->HierarType = pH264Enc->hMFCH264Handle.eHierarchicalType; + + /* SPS VUI */ + if (pH264Enc->hMFCH264Handle.stSarParam.SarEnable == OMX_TRUE) { + pH264Param->SarEnable = 1; + pH264Param->SarIndex = pH264Enc->hMFCH264Handle.stSarParam.SarIndex; + pH264Param->SarWidth = pH264Enc->hMFCH264Handle.stSarParam.SarWidth; + pH264Param->SarHeight = pH264Enc->hMFCH264Handle.stSarParam.SarHeight; + } else { + pH264Param->SarEnable = 0; + pH264Param->SarIndex = 0; + pH264Param->SarWidth = 0; + pH264Param->SarHeight = 0; + } + +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.bLowLatency == OMX_TRUE) { + pH264Param->HeaderWithIFrame = 0; /* 1: header + first frame */ + pH264Param->LoopFilterDisable = 0; /* 1: disable, 0: enable */ + pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] = OMX_Video_ControlRateDisable; + pCommonParam->EnableFRMQpControl = 1; /* 0: Disable, 1: Per frame QP */ + } +#endif + pH264Param->VuiRestrictionEnable = (int)OMX_TRUE; + + pH264Param->LTRFrames = pMFCH264Handle->nLTRFrames; + + pH264Param->ROIEnable = (pMFCH264Handle->bRoiInfo == OMX_TRUE)? 1:0; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eControlRate: 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]); + /* rate control related parameters */ + switch ((int)pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]) { + case OMX_Video_ControlRateDisable: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode DBR"); + pCommonParam->EnableFRMRateControl = 0; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 0; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + case OMX_Video_ControlRateConstantVTCall: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR VT Call"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 5; + pCommonParam->bFixedSlice = VIDEO_TRUE; + break; + case OMX_Video_ControlRateConstantSkipFrames: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR VT Call with Skip frame"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 5; + pCommonParam->bFixedSlice = VIDEO_TRUE; + pInitParam->FrameSkip = VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT; + break; + case OMX_Video_ControlRateConstant: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 10; + break; + case OMX_Video_ControlRateVariable: + default: /*Android default */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode VBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + } + +// Print_H264Enc_Param(pEncParam); +} + +static OMX_ERRORTYPE Change_H264Enc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + OMX_PTR pDynamicConfigCMD = NULL; + OMX_PTR pConfigData = NULL; + OMX_S32 nCmdIndex = 0; + ExynosVideoEncOps *pEncOps = NULL; + int nValue = 0; + + int i; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncOps = pMFCH264Handle->pEncOps; + + pDynamicConfigCMD = (OMX_PTR)Exynos_OSAL_Dequeue(&pExynosComponent->dynamicConfigQ); + if (pDynamicConfigCMD == NULL) + goto EXIT; + + nCmdIndex = *(OMX_S32 *)pDynamicConfigCMD; + pConfigData = (OMX_PTR)((OMX_U8 *)pDynamicConfigCMD + sizeof(OMX_S32)); + + switch ((int)nCmdIndex) { + case OMX_IndexConfigVideoIntraVOPRefresh: + { + nValue = VIDEO_FRAME_I; + pEncOps->Set_FrameType(pMFCH264Handle->hMFCHandle, nValue); + pVideoEnc->IntraRefreshVOP = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] VOP Refresh", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_S32 nPFrames = (*((OMX_S32 *)pConfigData)) - 1; + + nValue = nPFrames + 1; + pEncOps->Set_IDRPeriod(pH264Enc->hMFCH264Handle.hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] IDR period: %d", pExynosComponent, __FUNCTION__, nValue); + } + break; + case OMX_IndexConfigVideoAVCIntraPeriod: + { + OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pAVCIntraPeriod = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pConfigData; + + nValue = pAVCIntraPeriod->nIDRPeriod; + pEncOps->Set_IDRPeriod(pMFCH264Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] IDR period: %d", pExynosComponent, __FUNCTION__, nValue); + } + break; + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pConfigData; + + if (pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] != OMX_Video_ControlRateDisable) { + nValue = pConfigBitrate->nEncodeBitrate; + pEncOps->Set_BitRate(pH264Enc->hMFCH264Handle.hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bitrate: %d", pExynosComponent, __FUNCTION__, nValue); + } + } + break; + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pConfigData; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + + if (nPortIndex == INPUT_PORT_INDEX) { + nValue = (pConfigFramerate->xEncodeFramerate) >> 16; + pEncOps->Set_FrameRate(pH264Enc->hMFCH264Handle.hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] framerate: %d", pExynosComponent, __FUNCTION__, nValue); + } + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pConfigData; + ExynosVideoQPRange qpRange; + + qpRange.QpMin_I = pQpRange->qpRangeI.nMinQP; + qpRange.QpMax_I = pQpRange->qpRangeI.nMaxQP; + qpRange.QpMin_P = pQpRange->qpRangeP.nMinQP; + qpRange.QpMax_P = pQpRange->qpRangeP.nMaxQP; + qpRange.QpMin_B = pQpRange->qpRangeB.nMinQP; + qpRange.QpMax_B = pQpRange->qpRangeB.nMaxQP; + + pEncOps->Set_QpRange(pMFCH264Handle->hMFCHandle, qpRange); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qp range: I(%d, %d), P(%d, %d), B(%d, %d)", + pExynosComponent, __FUNCTION__, + qpRange.QpMin_I, qpRange.QpMax_I, + qpRange.QpMin_P, qpRange.QpMax_P, + qpRange.QpMin_B, qpRange.QpMax_B); + } + break; + case OMX_IndexConfigOperatingRate: + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pConfigData; + OMX_U32 xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + + nValue = pConfigRate->nU32 >> 16; + + if (pMFCH264Handle->videoInstInfo.supportInfo.enc.bOperatingRateSupport == VIDEO_TRUE) { + if (nValue == ((OMX_U32)INT_MAX >> 16)) { + nValue = (OMX_U32)INT_MAX; + } else { + nValue = nValue * 1000; + } + + pEncOps->Set_OperatingRate(pMFCH264Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] operating rate: 0x%x", pExynosComponent, __FUNCTION__, nValue); + } else { + if (nValue == (((OMX_U32)INT_MAX) >> 16)) { + nValue = 1000; + } else { + nValue = ((xFramerate >> 16) == 0)? 100:(OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + } + + pEncOps->Set_QosRatio(pMFCH264Handle->hMFCHandle, nValue); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qos ratio: 0x%x", pExynosComponent, __FUNCTION__, nValue); + } + + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pConfigData; + ExynosVideoQPRange qpRange; + TemporalLayerShareBuffer TemporalSVC; + + qpRange.QpMin_I = pTemporalSVC->nMinQuantizer; + qpRange.QpMax_I = pTemporalSVC->nMaxQuantizer; + qpRange.QpMin_P = pTemporalSVC->nMinQuantizer; + qpRange.QpMax_P = pTemporalSVC->nMaxQuantizer; + qpRange.QpMin_B = pTemporalSVC->nMinQuantizer; + qpRange.QpMax_B = pTemporalSVC->nMaxQuantizer; + + pEncOps->Set_QpRange(pMFCH264Handle->hMFCHandle, qpRange); + pEncOps->Set_IDRPeriod(pMFCH264Handle->hMFCHandle, pTemporalSVC->nKeyFrameInterval); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // qp range: I(%d, %d), P(%d, %d), B(%d, %d)", + pExynosComponent, __FUNCTION__, + qpRange.QpMin_I, qpRange.QpMax_I, + qpRange.QpMin_P, qpRange.QpMax_P, + qpRange.QpMin_B, qpRange.QpMax_B); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // IDR period: %d", pExynosComponent, __FUNCTION__, nValue); + + /* Temporal SVC */ + Exynos_OSAL_Memset(&TemporalSVC, 0, sizeof(TemporalLayerShareBuffer)); + + TemporalSVC.nTemporalLayerCount = (unsigned int)pTemporalSVC->nTemporalLayerCount; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // layer count: %d", pExynosComponent, __FUNCTION__, TemporalSVC.nTemporalLayerCount); + + for (i = 0; i < OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; i++) { + TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pTemporalSVC->nTemporalLayerBitrateRatio[i]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // bitrate ratio[%d]: %d", + pExynosComponent, __FUNCTION__, + i, TemporalSVC.nTemporalLayerBitrateRatio[i]); + } + if (pEncOps->Set_LayerChange(pMFCH264Handle->hMFCHandle, TemporalSVC) != VIDEO_ERROR_NONE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Not supported control: Set_LayerChange", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigVideoRoiInfo: + { + EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *pRoiInfo = (EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *)pConfigData; + + /* ROI INFO */ + RoiInfoShareBuffer RoiInfo; + + Exynos_OSAL_Memset(&RoiInfo, 0, sizeof(RoiInfo)); + RoiInfo.pRoiMBInfo = (OMX_U64)(unsigned long)(((OMX_U8 *)pConfigData) + sizeof(EXYNOS_OMX_VIDEO_CONFIG_ROIINFO)); + RoiInfo.nRoiMBInfoSize = pRoiInfo->nRoiMBInfoSize; + RoiInfo.nUpperQpOffset = pRoiInfo->nUpperQpOffset; + RoiInfo.nLowerQpOffset = pRoiInfo->nLowerQpOffset; + RoiInfo.bUseRoiInfo = (pRoiInfo->bUseRoiInfo == OMX_TRUE)? VIDEO_TRUE:VIDEO_FALSE; + + if (pEncOps->Set_RoiInfo(pMFCH264Handle->hMFCHandle, &RoiInfo) != VIDEO_ERROR_NONE) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Set_RoiInfo()", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigIFrameRatio: + { + OMX_PARAM_U32TYPE *pIFrameRatio = (OMX_PARAM_U32TYPE *)pConfigData; + + pEncOps->Set_IFrameRatio(pMFCH264Handle->hMFCHandle, pIFrameRatio->nU32); + } + break; + case OMX_IndexConfigCommonOutputSize: + { + OMX_FRAMESIZETYPE *pFrameSize = (OMX_FRAMESIZETYPE *)pConfigData; + OMX_CONFIG_RECTTYPE *pTargetFrame = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].cropRectangle[IMG_CROP_OUTPUT_PORT]); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] resolution(%d x %d) is changed to (%d x %d)", pExynosComponent, __FUNCTION__, + pTargetFrame->nWidth, pTargetFrame->nHeight, + pFrameSize->nWidth, pFrameSize->nHeight); + + /* update target size */ + pTargetFrame->nTop = 0; + pTargetFrame->nLeft = 0; + pTargetFrame->nWidth = pFrameSize->nWidth; + pTargetFrame->nHeight = pFrameSize->nHeight; + + pVideoEnc->bEncDRC = OMX_TRUE; + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigAndroidVideoTemporalLayering: + { + OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *pTemporalLayering = (OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *)pConfigData; + + TemporalLayerShareBuffer TemporalSVC; + + /* Temporal SVC */ + Exynos_OSAL_Memset(&TemporalSVC, 0, sizeof(TemporalLayerShareBuffer)); + + TemporalSVC.nTemporalLayerCount = (unsigned int)(pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual); + + if (pTemporalLayering->bBitrateRatiosSpecified == OMX_TRUE) { + for (i = 0; i < (int)pH264Enc->nMaxTemporalLayerCount; i++) { + + TemporalSVC.nTemporalLayerBitrateRatio[i] = (pTemporalLayering->nBitrateRatios[i] >> 16); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // bitrate ratio[%d]: %d", + pExynosComponent, __FUNCTION__, + i, TemporalSVC.nTemporalLayerBitrateRatio[i]); + } + } else { + EXYNOS_OMX_BASEPORT *pOutputPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + + for (i = 0; i < (int)pH264Enc->nMaxTemporalLayerCount; i++) { + TemporalSVC.nTemporalLayerBitrateRatio[i] = pOutputPort->portDefinition.format.video.nBitrate; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // bitrate ratio[%d]: %d", + pExynosComponent, __FUNCTION__, + i, TemporalSVC.nTemporalLayerBitrateRatio[i]); + } + } + + if (pEncOps->Set_LayerChange(pMFCH264Handle->hMFCHandle, TemporalSVC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Not supported control: Set_LayerChange", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Max(%d), layer(%d), B-layer(%d)", pExynosComponent, __FUNCTION__, + pH264Enc->nMaxTemporalLayerCount, TemporalSVC.nTemporalLayerCount, pTemporalLayering->nBLayerCountActual); + } + break; +#endif + default: +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bSkypeSupport == VIDEO_TRUE) { + ret = Change_H264Enc_SkypeHDParam(pExynosComponent, pDynamicConfigCMD); + if (ret != OMX_ErrorNone) + goto EXIT; + } +#endif + break; + } + + Exynos_OSAL_Free(pDynamicConfigCMD); + + Set_H264Enc_Param(pExynosComponent); + +EXIT: + return ret; +} + +OMX_ERRORTYPE GetCodecOutputPrivateData( + OMX_PTR pCodecBuffer, + OMX_PTR *pVirtAddr, + OMX_U32 *pDataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pVideoBuffer = NULL; + + if (pCodecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoBuffer = (ExynosVideoBuffer *)pCodecBuffer; + + if (pVirtAddr != NULL) + *pVirtAddr = pVideoBuffer->planes[0].addr; + + if (pDataSize != NULL) + *pDataSize = pVideoBuffer->planes[0].allocSize; + +EXIT: + return ret; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) + goto EXIT; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE H264CodecOpen( + EXYNOS_H264ENC_HANDLE *pH264Enc, + ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pH264Enc == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pEncOps = (ExynosVideoEncOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncOps)); + pInbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + pOutbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + + if ((pEncOps == NULL) || + (pInbufOps == NULL) || + (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.pEncOps = pEncOps; + pH264Enc->hMFCH264Handle.pInbufOps = pInbufOps; + pH264Enc->hMFCH264Handle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pEncOps->nSize = sizeof(ExynosVideoEncOps); + pInbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + + if (Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for encoder ops */ + if ((pEncOps->Init == NULL) || + (pEncOps->Finalize == NULL) || + (pEncOps->Set_FrameTag == NULL) || + (pEncOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pH264Enc->hMFCH264Handle.hMFCHandle = pH264Enc->hMFCH264Handle.pEncOps->Init(pVideoInstInfo); + if (pH264Enc->hMFCH264Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pH264Enc->hMFCH264Handle.pEncOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pH264Enc->hMFCH264Handle.pInbufOps = NULL; + } + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pH264Enc->hMFCH264Handle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecClose(EXYNOS_H264ENC_HANDLE *pH264Enc) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pH264Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + + if (hMFCHandle != NULL) { + pEncOps->Finalize(hMFCHandle); + hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle = NULL; + pH264Enc->hMFCH264Handle.bConfiguredMFCSrc = OMX_FALSE; + pH264Enc->hMFCH264Handle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Encoder(pEncOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps = NULL; + } + + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pEncOps = pH264Enc->hMFCH264Handle.pEncOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecStart( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + + if (nPortIndex == INPUT_PORT_INDEX) + pInbufOps->Run(hMFCHandle); + else if (nPortIndex == OUTPUT_PORT_INDEX) + pOutbufOps->Run(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecStop( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) + pInbufOps->Stop(hMFCHandle); + else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) + pOutbufOps->Stop(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecOutputBufferProcessRun( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pH264Enc->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pH264Enc->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pH264Enc->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pH264Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pH264Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecEnqueueAllBuffer( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + + int i; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && + (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pH264Enc->bSourceStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x), size(%d)", + pExynosComponent, __FUNCTION__, + i, pVideoEnc->pMFCEncInputBuffer[i]->fd[0], pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0], + pVideoEnc->pMFCEncInputBuffer[i]->bufferSize[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, INPUT_PORT_INDEX, pVideoEnc->pMFCEncInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pH264Enc->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoEnc->pMFCEncOutputBuffer[i]->fd[0], pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoEnc->pMFCEncOutputBuffer[i]); + } + + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + +void H264CodecSetHdrInfo(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = &pH264Enc->hMFCH264Handle; + void *hMFCHandle = pMFCH264Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + + OMX_COLOR_FORMATTYPE eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + if (pMFCH264Handle->videoInstInfo.supportInfo.enc.bColorAspectsSupport == VIDEO_TRUE) { + ExynosVideoColorAspects BSCA; + Exynos_OSAL_Memset(&BSCA, 0, sizeof(BSCA)); + +#ifdef USE_ANDROID + if (pVideoEnc->surfaceFormat == eColorFormat) { + Exynos_OSAL_GetColorAspectsForBitstream(&(pInputPort->ColorAspects), &(pOutputPort->ColorAspects)); + + /* in case of RGBA, re-update suitable values(transfer) */ + if (pVideoEnc->surfaceFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888) { + /* Eventhough frameworks already sent ColorAspects, + * sometimes dataspace has not set to OMX component because of timing. + * So get dataspace from frameworks ColorAspects. + */ + if (pInputPort->ColorAspects.nDataSpace == 0) { + Exynos_OSAL_UpdateDataSpaceFromAspects(&(pInputPort->ColorAspects)); + } + Exynos_OSAL_GetRGBColorTypeForBitStream(&pOutputPort->ColorAspects, pInputPort->ColorAspects.nDataSpace, eColorFormat); + } + } else { + /* in case of RGBA->YUV, color aspects for bitstream is already updated */ + if (pVideoEnc->surfaceFormat != (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888) + Exynos_OSAL_GetColorAspectsForBitstream(&(pInputPort->ColorAspects), &(pOutputPort->ColorAspects)); + } +#endif + + BSCA.eRangeType = (ExynosRangeType)pOutputPort->ColorAspects.nRangeType; + BSCA.ePrimariesType = (ExynosPrimariesType)pOutputPort->ColorAspects.nPrimaryType; + BSCA.eTransferType = (ExynosTransferType)pOutputPort->ColorAspects.nTransferType; + BSCA.eCoeffType = (ExynosMatrixCoeffType)pOutputPort->ColorAspects.nCoeffType; + + pEncOps->Set_ColorAspects(hMFCHandle, &BSCA); + } + + return ; +} + +OMX_ERRORTYPE H264CodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = &pH264Enc->hMFCH264Handle; + void *hMFCHandle = pMFCH264Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + ExynosVideoGeometry bufferConf; + + FunctionIn(); + + pVideoEnc->bEncDRCSync = OMX_TRUE; + + /* stream off */ + ret = H264CodecStop(pOMXComponent, INPUT_PORT_INDEX); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to H264CodecStop() about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_SignalWait(pVideoEnc->hEncDRCSyncEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pVideoEnc->hEncDRCSyncEvent); + + /* get input buffer geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + if (pInbufOps->Get_Geometry) { + if (pInbufOps->Get_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + /* clear information */ + pInbufOps->Clear_RegisteredBuffer(hMFCHandle); + pInbufOps->Cleanup_Buffer(hMFCHandle); + + /* set input buffer geometry */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + bufferConf.nFrameHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + bufferConf.nStride = ALIGN(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth, 16); + } else { + bufferConf.nFrameWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + bufferConf.nFrameHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + bufferConf.nStride = ALIGN(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight, 16); + } + + if (pInbufOps->Set_Geometry) { + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, MAX_INPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + /* header with IDR */ + if (pEncOps->Set_HeaderMode(hMFCHandle, VIDEO_FALSE) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set header mode", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + /* stream on */ + H264CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + /* reset buffer queue */ + H264CodecEnqueueAllBuffer(pOMXComponent, INPUT_PORT_INDEX); + + /* clear timestamp */ + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + + /* reinitialize a value for reconfiguring CSC */ + pVideoEnc->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecSrcSetup( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = &pH264Enc->hMFCH264Handle; + void *hMFCHandle = pMFCH264Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + ExynosVideoEncParam *pEncParam = NULL; + + ExynosVideoGeometry bufferConf; + OMX_U32 inputBufferNumber = 0; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pH264Enc->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pH264Enc->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_OSAL_SignalSet(pH264Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + Set_H264Enc_Param(pExynosComponent); + + pEncParam = &pMFCH264Handle->encParam; + if (pEncOps->Set_EncParam) { + if(pEncOps->Set_EncParam(pH264Enc->hMFCH264Handle.hMFCHandle, pEncParam) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set encParam", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + Print_H264Enc_Param(pEncParam); + + if (pMFCH264Handle->bPrependSpsPpsToIdr == OMX_TRUE) { + if (pEncOps->Enable_PrependSpsPpsToIdr) + pEncOps->Enable_PrependSpsPpsToIdr(pH264Enc->hMFCH264Handle.hMFCHandle); + else + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Not supported control: Enable_PrependSpsPpsToIdr", pExynosComponent, __FUNCTION__); + } + + if ((pInputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) && + ((pInputPort->bufferProcessType & BUFFER_SHARE) && + (pSrcInputData->buffer.addr[2] != NULL))) { + ExynosVideoMeta *pMeta = (ExynosVideoMeta *)pSrcInputData->buffer.addr[2]; + + if (pMeta->eType & VIDEO_INFO_TYPE_YSUM_DATA) { + if (VIDEO_ERROR_NONE == pEncOps->Enable_WeightedPrediction(hMFCHandle)) + pMFCH264Handle->bWeightedPrediction = OMX_TRUE; + } + } + + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bAdaptiveLayerBitrateSupport == VIDEO_TRUE) { + if (pH264Enc->bUseTemporalLayerBitrateRatio == OMX_TRUE) { + pEncOps->Enable_AdaptiveLayerBitrate(pMFCH264Handle->hMFCHandle, 0); /* Disable : Use layer bitrate from framework */ + } else { + pEncOps->Enable_AdaptiveLayerBitrate(pMFCH264Handle->hMFCHandle, 1); /* Enable : Use adaptive layer bitrate from H/W */ + } + } + +#ifdef USE_ANDROID + H264CodecSetHdrInfo(pOMXComponent); +#endif + + if (pMFCH264Handle->videoInstInfo.supportInfo.enc.bPrioritySupport == VIDEO_TRUE) + pEncOps->Set_Priority(hMFCHandle, pVideoEnc->nPriority); + + if (pEncParam->commonParam.bDisableDFR == VIDEO_TRUE) + pEncOps->Disable_DynamicFrameRate(pMFCH264Handle->hMFCHandle, VIDEO_TRUE); + + /* input buffer info: only 3 config values needed */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eColorFormat = pEncParam->commonParam.FrameMap; + + { + OMX_S32 nTargetWidth, nTargetHeight; + + /* uses specified target size instead of size on output port */ + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + /* use specified resolution */ + nTargetWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nTargetHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nTargetWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nTargetHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = nTargetWidth; + bufferConf.nFrameHeight = nTargetHeight; + bufferConf.nStride = ALIGN(nTargetWidth, 16); + } else { + bufferConf.nFrameWidth = nTargetHeight; + bufferConf.nFrameHeight = nTargetWidth; + bufferConf.nStride = ALIGN(nTargetHeight, 16); + } + } + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + pInbufOps->Set_Shareable(hMFCHandle); + inputBufferNumber = MAX_INPUTBUFFER_NUM_DYNAMIC; + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry) { + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, inputBufferNumber) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pInputPort->bufferProcessType & BUFFER_SHARE) && + (pInputPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + /* data buffer */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.bConfiguredMFCSrc = OMX_TRUE; + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = &pH264Enc->hMFCH264Handle; + void *hMFCHandle = pMFCH264Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + unsigned int nDataLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + int i, nOutBufSize = 0, nOutputBufferCnt = 0; + + FunctionIn(); + + nOutBufSize = pOutputPort->portDefinition.nBufferSize; + if ((pOutputPort->bufferProcessType & BUFFER_COPY) || + (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nOutBufSize = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * + pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nOutBufSize = Exynos_OSAL_GetOutBufferSize(pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.nBufferSize); +#endif + +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) { + if (nOutBufSize > CUSTOM_LIMITED_DRM_OUTPUT_BUFFER_SIZE) { + nOutBufSize = CUSTOM_LIMITED_DRM_OUTPUT_BUFFER_SIZE; + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] set limited output buffer size to MFC dst: %d", + pExynosComponent, __FUNCTION__, nOutBufSize); + } + } +#endif + } + + /* set geometry for output (dst) */ + if (pOutbufOps->Set_Geometry) { + /* output buffer info: only 2 config values needed */ + bufferConf.eCompressionFormat = VIDEO_CODING_AVC; + bufferConf.nSizeImage = nOutBufSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + + if (pOutbufOps->Set_Geometry(pH264Enc->hMFCH264Handle.hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pOutputPort->bufferProcessType & BUFFER_COPY) + nOutputBufferCnt = MFC_OUTPUT_BUFFER_NUM_MAX; + else + nOutputBufferCnt = pOutputPort->portDefinition.nBufferCountActual; + + if (pOutbufOps->Setup(pH264Enc->hMFCH264Handle.hMFCHandle, nOutputBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + nAllocLen[0] = nOutBufSize; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, MFC_OUTPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Allocate_CodecBuffers for output", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + /* Enqueue output buffer */ + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoEnc->pMFCEncOutputBuffer[i]->fd, + pVideoEnc->pMFCEncOutputBuffer[i]->bufferSize, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + NULL); + } + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /* Register output buffer */ + /*************/ + /* TBD */ + /*************/ + } + + pH264Enc->hMFCH264Handle.bConfiguredMFCDst = OMX_TRUE; + + if (H264CodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nParamIndex %x", pExynosComponent, __FUNCTION__, (int)nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = (OMX_VIDEO_PARAM_AVCTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCTYPE *pSrcAVCComponent = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstAVCComponent, sizeof(OMX_VIDEO_PARAM_AVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstAVCComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcAVCComponent = &pH264Enc->AVCComponent[pDstAVCComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstAVCComponent) + nOffset, + ((char *)pSrcAVCComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_AVCTYPE) - nOffset); + } + break; + case OMX_IndexParamVideoSliceFMO: + { + OMX_VIDEO_PARAM_AVCSLICEFMO *pDstSliceFmo = (OMX_VIDEO_PARAM_AVCSLICEFMO *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCSLICEFMO *pSrcSliceFmo = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstSliceFmo, sizeof(OMX_VIDEO_PARAM_AVCSLICEFMO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pSrcSliceFmo = &pH264Enc->AVCSliceFmo; + + Exynos_OSAL_Memcpy(((char *)pDstSliceFmo) + nOffset, + ((char *)pSrcSliceFmo) + nOffset, + sizeof(OMX_VIDEO_PARAM_AVCSLICEFMO) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H264_DRM_ENC_ROLE); + else + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H264_ENC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCTYPE *pSrcAVCComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcAVCComponent = &pH264Enc->AVCComponent[pDstProfileLevel->nPortIndex]; + pDstProfileLevel->eProfile = pSrcAVCComponent->eProfile; + pDstProfileLevel->eLevel = pSrcAVCComponent->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pH264Enc->errorCorrectionType[OUTPUT_PORT_INDEX]; + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pH264Enc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pH264Enc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pH264Enc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pH264Enc->qpRangeP.nMaxQP; + pQpRange->qpRangeB.nMinQP = pH264Enc->qpRangeB.nMinQP; + pQpRange->qpRangeB.nMaxQP = pH264Enc->qpRangeB.nMaxQP; + } + break; + case OMX_IndexParamVideoAVCEnableTemporalSVC: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *pDstEnableTemporalSVC = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstEnableTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstEnableTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstEnableTemporalSVC->bEnableTemporalSVC = pH264Enc->hMFCH264Handle.bTemporalSVC; + } + break; + case OMX_IndexParamVideoEnableRoiInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *pDstEnableRoiInfo = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstEnableRoiInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstEnableRoiInfo->bEnableRoiInfo = pH264Enc->hMFCH264Handle.bRoiInfo; + } + break; + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pEnablePVC->nU32 = pVideoEnc->bPVCMode; + } + break; + case OMX_IndexParamVideoChromaQP: + { + OMX_VIDEO_PARAM_CHROMA_QP_OFFSET *pChromaQP = (OMX_VIDEO_PARAM_CHROMA_QP_OFFSET *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pChromaQP, sizeof(OMX_VIDEO_PARAM_CHROMA_QP_OFFSET)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pChromaQP->nCr = pH264Enc->chromaQPOffset.nCr; + pChromaQP->nCb = pH264Enc->chromaQPOffset.nCb; + } + break; + case OMX_IndexParamVideoDisableHBEncoding: + { + OMX_CONFIG_BOOLEANTYPE *pDisableHBEncoding = (OMX_CONFIG_BOOLEANTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDisableHBEncoding, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDisableHBEncoding->bEnabled = pH264Enc->bDisableHBEncoding; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamAndroidVideoTemporalLayering: + { + OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pTemporalLayering = (OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pTemporalLayering, sizeof(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pTemporalLayering->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) { + pTemporalLayering->eSupportedPatterns = OMX_VIDEO_AndroidTemporalLayeringPatternNone; + pTemporalLayering->nLayerCountMax = 1; /* not supported */ + pTemporalLayering->nBLayerCountMax = 0; + pTemporalLayering->ePattern = OMX_VIDEO_AndroidTemporalLayeringPatternNone; + } else { + pTemporalLayering->eSupportedPatterns = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; + + if (pH264Enc->hMFCH264Handle.bTemporalSVC == OMX_TRUE) { /* already enabled */ + pTemporalLayering->nLayerCountMax = pH264Enc->nMaxTemporalLayerCount; + pTemporalLayering->nBLayerCountMax = pH264Enc->nMaxTemporalLayerCountForB; + pTemporalLayering->ePattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; + } else { + pTemporalLayering->nLayerCountMax = OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; + pTemporalLayering->nBLayerCountMax = OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS_FOR_B; + pTemporalLayering->ePattern = OMX_VIDEO_AndroidTemporalLayeringPatternNone; + + if (pH264Enc->bDisableHBEncoding == OMX_TRUE) { + pTemporalLayering->nBLayerCountMax = 0; + } + } + } + + pTemporalLayering->nPLayerCountActual = pH264Enc->nTemporalLayerCount; + pTemporalLayering->nBLayerCountActual = pH264Enc->nTemporalLayerCountForB; + + pTemporalLayering->bBitrateRatiosSpecified = pH264Enc->bUseTemporalLayerBitrateRatio; + if (pTemporalLayering->bBitrateRatiosSpecified == OMX_TRUE) { + for (i = 0; i < OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; i++) + pTemporalLayering->nBitrateRatios[i] = (pH264Enc->nTemporalLayerBitrateRatio[i] << 16); + } + } + break; +#endif + default: +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bSkypeSupport == VIDEO_TRUE) { + ret = Exynos_H264Enc_GetParameter_SkypeHD(hComponent, nParamIndex, pComponentParameterStructure); + if (ret == OMX_ErrorNone) + goto EXIT; + } +#endif + ret = Exynos_OMX_VideoEncodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = NULL; + OMX_VIDEO_PARAM_AVCTYPE *pSrcAVCComponent = (OMX_VIDEO_PARAM_AVCTYPE *)pComponentParameterStructure; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcAVCComponent, sizeof(OMX_VIDEO_PARAM_AVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcAVCComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstAVCComponent = &pH264Enc->AVCComponent[pSrcAVCComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstAVCComponent) + nOffset, + ((char *)pSrcAVCComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_AVCTYPE) - nOffset); + + if (pDstAVCComponent->nBFrames > 2) { /* 0 ~ 2 */ + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] nBFrames(%d) is over a maximum value(2). it is limited to max", + pExynosComponent, __FUNCTION__, pDstAVCComponent->nBFrames); + pDstAVCComponent->nBFrames = 2; + } + + if (pDstAVCComponent->nRefFrames > 2) { /* 1 ~ 2 */ + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] nRefFrames(%d) is over a maximum value(2). it is limited to max", + pExynosComponent, __FUNCTION__, pDstAVCComponent->nRefFrames); + pDstAVCComponent->nRefFrames = 2; + } else if (pDstAVCComponent->nRefFrames == 0) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] nRefFrames(%d) is smaller than minimum value(1). it is limited to min", + pExynosComponent, __FUNCTION__, pDstAVCComponent->nRefFrames); + pDstAVCComponent->nRefFrames = 1; + } + } + break; + case OMX_IndexParamVideoSliceFMO: + { + OMX_VIDEO_PARAM_AVCSLICEFMO *pSrcSliceFmo = (OMX_VIDEO_PARAM_AVCSLICEFMO *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCSLICEFMO *pDstSliceFmo = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcSliceFmo, sizeof(OMX_VIDEO_PARAM_AVCSLICEFMO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDstSliceFmo = &pH264Enc->AVCSliceFmo; + + Exynos_OSAL_Memcpy(((char *)pDstSliceFmo) + nOffset, + ((char *)pSrcSliceFmo) + nOffset, + sizeof(OMX_VIDEO_PARAM_AVCSLICEFMO) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H264_ENC_ROLE) || + !Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H264_DRM_ENC_ROLE)) { + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstAVCComponent = &pH264Enc->AVCComponent[pSrcProfileLevel->nPortIndex]; + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstAVCComponent->eProfile = pSrcProfileLevel->eProfile; + pDstAVCComponent->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pH264Enc->errorCorrectionType[OUTPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP) || + (pQpRange->qpRangeB.nMinQP > pQpRange->qpRangeB.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d], B[min:%d, max:%d])", __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP, + pQpRange->qpRangeB.nMinQP, pQpRange->qpRangeB.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pH264Enc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pH264Enc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pH264Enc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + pH264Enc->qpRangeB.nMinQP = pQpRange->qpRangeB.nMinQP; + pH264Enc->qpRangeB.nMaxQP = pQpRange->qpRangeB.nMaxQP; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamPrependSPSPPSToIDR: + { + ret = Exynos_OSAL_SetPrependSPSPPSToIDR(pComponentParameterStructure, &(pH264Enc->hMFCH264Handle.bPrependSpsPpsToIdr)); + } + break; + case OMX_IndexParamAndroidVideoTemporalLayering: + { + OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pTemporalLayering = (OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pTemporalLayering, sizeof(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pTemporalLayering->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pTemporalLayering->ePattern != OMX_VIDEO_AndroidTemporalLayeringPatternNone) { + /* ENABLE */ + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Temporal SVC is not supported", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + + if (pTemporalLayering->nLayerCountMax > OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] total layer : Max value(%d) > supportable Max value(%d)", + pExynosComponent, __FUNCTION__, pTemporalLayering->nLayerCountMax, OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pTemporalLayering->nBLayerCountMax > OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS_FOR_B) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] B layer : Max value(%d) > supportable Max value(%d)", + pExynosComponent, __FUNCTION__, pTemporalLayering->nBLayerCountMax, OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS_FOR_B); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.bTemporalSVC = OMX_TRUE; + pH264Enc->nMaxTemporalLayerCount = pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual; + pH264Enc->nMaxTemporalLayerCountForB = pTemporalLayering->nBLayerCountActual; + pH264Enc->nTemporalLayerCount = pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual; + pH264Enc->nTemporalLayerCountForB = pTemporalLayering->nBLayerCountActual; + + if (pH264Enc->bDisableHBEncoding) { + pH264Enc->nMaxTemporalLayerCountForB = 0; + pH264Enc->nTemporalLayerCountForB = 0; + } + + pH264Enc->bUseTemporalLayerBitrateRatio = pTemporalLayering->bBitrateRatiosSpecified; + if (pH264Enc->bUseTemporalLayerBitrateRatio == OMX_TRUE) { + for (i = 0; i < (int)pH264Enc->nMaxTemporalLayerCount; i++) + pH264Enc->nTemporalLayerBitrateRatio[i] = (pTemporalLayering->nBitrateRatios[i] >> 16); + } + + /* HIGH_SPEED_ENCODING */ + if (pH264Enc->nTemporalLayerCountForB > 0) { + int minRequiredInputs = pow(2, pH264Enc->nTemporalLayerCount - 1); + if (minRequiredInputs > pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.nBufferCountActual) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Temporal Layering with B-frame, increase InputBufferNum(%d)", pExynosComponent, __FUNCTION__, minRequiredInputs); + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.nBufferCountActual = minRequiredInputs; + } + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Max(%d), B-Max(%d), layer(%d), B-layer(%d)", pExynosComponent, __FUNCTION__, + pH264Enc->nMaxTemporalLayerCount, pH264Enc->nMaxTemporalLayerCountForB, + pH264Enc->nTemporalLayerCount, pH264Enc->nTemporalLayerCountForB); + } else { + /* DISABLE */ + pH264Enc->hMFCH264Handle.bTemporalSVC = OMX_FALSE; + pH264Enc->nMaxTemporalLayerCount = 0; + pH264Enc->nMaxTemporalLayerCountForB = 0; + pH264Enc->nTemporalLayerCount = 0; + pH264Enc->nTemporalLayerCountForB = 0; + pH264Enc->bUseTemporalLayerBitrateRatio = OMX_FALSE; + Exynos_OSAL_Memset(pH264Enc->nTemporalLayerBitrateRatio, 0, sizeof(pH264Enc->nTemporalLayerBitrateRatio)); + } + } + break; +#endif + case OMX_IndexParamVideoAVCEnableTemporalSVC: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *pSrcEnableTemporalSVC = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *)pComponentParameterStructure; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition); + int i; + + ret = Exynos_OMX_Check_SizeVersion(pSrcEnableTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcEnableTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) && + (pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Temporal SVC is not supported", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_TRUE) && + (pH264Enc->hMFCH264Handle.bTemporalSVC == OMX_FALSE)) { + /* ENABLE : not initialized yet */ + pH264Enc->hMFCH264Handle.bTemporalSVC = OMX_TRUE; + pH264Enc->nMaxTemporalLayerCount = OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; + pH264Enc->nMaxTemporalLayerCountForB = OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS_FOR_B; + pH264Enc->nTemporalLayerCount = 1; + pH264Enc->nTemporalLayerCountForB = 0; + pH264Enc->bUseTemporalLayerBitrateRatio = OMX_TRUE; + pH264Enc->nTemporalLayerBitrateRatio[0] = pPortDef->format.video.nBitrate; + } else if (pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_FALSE) { + /* DISABLE */ + pH264Enc->hMFCH264Handle.bTemporalSVC = OMX_FALSE; /* DISABLE */ + pH264Enc->nMaxTemporalLayerCount = 0; + pH264Enc->nMaxTemporalLayerCountForB = 0; + pH264Enc->nTemporalLayerCount = 0; + pH264Enc->nTemporalLayerCountForB = 0; + pH264Enc->bUseTemporalLayerBitrateRatio = OMX_FALSE; + Exynos_OSAL_Memset(pH264Enc->nTemporalLayerBitrateRatio, 0, sizeof(pH264Enc->nTemporalLayerBitrateRatio)); + } + } + break; + case OMX_IndexParamVideoEnableRoiInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *pSrcEnableRoiInfo = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pSrcEnableRoiInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bRoiInfoSupport == VIDEO_FALSE) && + (pSrcEnableRoiInfo->bEnableRoiInfo == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Roi Info is not supported", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.bRoiInfo = pSrcEnableRoiInfo->bEnableRoiInfo; + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortDef->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[nPortIndex];; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + if (pPortDef->nBufferCountActual < pExynosPort->portDefinition.nBufferCountMin) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pPortDef->format.video.xFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] xFramerate is invalid(%d)", + pExynosComponent, __FUNCTION__, pPortDef->format.video.xFramerate >> 16); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Memcpy(((char *)&pExynosPort->portDefinition) + nOffset, + ((char *)pPortDef) + nOffset, + pPortDef->nSize - nOffset); + if (nPortIndex == INPUT_PORT_INDEX) { + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + Exynos_UpdateFrameSize(pOMXComponent); + + if (pVideoEnc->bFirstInput == OMX_FALSE) + pVideoEnc->bEncDRC = OMX_TRUE; + + pVideoEnc->bFirstInput = OMX_TRUE; + pH264Enc->hMFCH264Handle.bConfiguredMFCSrc = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] pOutputPort->portDefinition.nBufferSize: %d", pExynosComponent, __FUNCTION__, pExynosPort->portDefinition.nBufferSize); + } else if (nPortIndex == OUTPUT_PORT_INDEX) { + pH264Enc->hMFCH264Handle.bConfiguredMFCDst = OMX_FALSE; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bPVCSupport == VIDEO_FALSE) && + (pEnablePVC->nU32 != 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] PVC mode is not supported", pExynosComponent, __FUNCTION__); + } + + pVideoEnc->bPVCMode = (pEnablePVC->nU32 != 0)? OMX_TRUE:OMX_FALSE; + } + break; + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE *pVideoBitrate = (OMX_VIDEO_PARAM_BITRATETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoBitrate->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + if (pH264Enc->hMFCH264Handle.bSkypeBitrate == OMX_FALSE) { + pPortDef = &(pExynosComponent->pExynosPort[nPortIndex].portDefinition); + pVideoEnc->eControlRate[nPortIndex] = pVideoBitrate->eControlRate; + pPortDef->format.video.nBitrate = pVideoBitrate->nTargetBitrate; + } + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoChromaQP: + { + OMX_VIDEO_PARAM_CHROMA_QP_OFFSET *pChromaQP = (OMX_VIDEO_PARAM_CHROMA_QP_OFFSET *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pChromaQP, sizeof(OMX_VIDEO_PARAM_CHROMA_QP_OFFSET)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pChromaQP->nCr < -12) || (pChromaQP->nCr > 12)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] ChromaQP Offset(Cr) 0x%x is invalid [min:-12, max:12]", pExynosComponent, __FUNCTION__, pChromaQP->nCr); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if ((pChromaQP->nCb < -12) || (pChromaQP->nCb > 12)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] ChromaQP Offset(Cb) 0x%x is invalid [min:-12, max:12]", pExynosComponent, __FUNCTION__, pChromaQP->nCb); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc->chromaQPOffset.nCr = pChromaQP->nCr; + pH264Enc->chromaQPOffset.nCb = pChromaQP->nCb; + } + break; + case OMX_IndexParamVideoDisableHBEncoding: + { + OMX_CONFIG_BOOLEANTYPE *pDisableHBEncoding = (OMX_CONFIG_BOOLEANTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDisableHBEncoding, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pH264Enc->bDisableHBEncoding = pDisableHBEncoding->bEnabled; + } + break; + default: +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bSkypeSupport == VIDEO_TRUE) { + ret = Exynos_H264Enc_SetParameter_SkypeHD(hComponent, nIndex, pComponentParameterStructure); + if (ret == OMX_ErrorNone) + goto EXIT; + } +#endif + ret = Exynos_OMX_VideoEncodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoAVCIntraPeriod: + { + OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pAVCIntraPeriod = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pComponentConfigStructure; + OMX_U32 portIndex = pAVCIntraPeriod->nPortIndex; + + if ((portIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pAVCIntraPeriod->nIDRPeriod = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames + 1; + pAVCIntraPeriod->nPFrames = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames; + } + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pH264Enc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pH264Enc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pH264Enc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pH264Enc->qpRangeP.nMaxQP; + pQpRange->qpRangeB.nMinQP = pH264Enc->qpRangeB.nMinQP; + pQpRange->qpRangeB.nMaxQP = pH264Enc->qpRangeB.nMaxQP; + } + break; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pDstTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pComponentConfigStructure; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstTemporalSVC->nKeyFrameInterval = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames + 1; + pDstTemporalSVC->nMinQuantizer = pH264Enc->qpRangeI.nMinQP; + pDstTemporalSVC->nMaxQuantizer = pH264Enc->qpRangeI.nMaxQP; + pDstTemporalSVC->nTemporalLayerCount = pH264Enc->nTemporalLayerCount; + for (i = 0; i < OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; i++) + pDstTemporalSVC->nTemporalLayerBitrateRatio[i] = pH264Enc->nTemporalLayerBitrateRatio[i]; + } + break; + default: +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bSkypeSupport == VIDEO_TRUE) { + ret = Exynos_H264Enc_GetConfig_SkypeHD(hComponent, nIndex, pComponentConfigStructure); + if (ret == OMX_ErrorNone) + goto EXIT; + } +#endif + ret = Exynos_OMX_VideoEncodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_U32 nPFrames = (*((OMX_U32 *)pComponentConfigStructure)) - 1; + pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames = nPFrames; + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexConfigVideoAVCIntraPeriod: + { + OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pAVCIntraPeriod = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pComponentConfigStructure; + OMX_U32 portIndex = pAVCIntraPeriod->nPortIndex; + + if ((portIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + if (pAVCIntraPeriod->nIDRPeriod == (pAVCIntraPeriod->nPFrames + 1)) + pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames = pAVCIntraPeriod->nPFrames; + else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP) || + (pQpRange->qpRangeB.nMinQP > pQpRange->qpRangeB.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d], B[min:%d, max:%d])", + pExynosComponent, __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP, + pQpRange->qpRangeB.nMinQP, pQpRange->qpRangeB.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_FALSE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] only I-frame's QP range is applied", pExynosComponent, __FUNCTION__); + + pH264Enc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pH264Enc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pH264Enc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pH264Enc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + pH264Enc->qpRangeB.nMinQP = pQpRange->qpRangeB.nMinQP; + pH264Enc->qpRangeB.nMaxQP = pQpRange->qpRangeB.nMaxQP; + } + break; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pSrcTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pComponentConfigStructure; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.bTemporalSVC == OMX_FALSE) || + (pSrcTemporalSVC->nTemporalLayerCount > OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames = pSrcTemporalSVC->nKeyFrameInterval - 1; + + pH264Enc->qpRangeI.nMinQP = pSrcTemporalSVC->nMinQuantizer; + pH264Enc->qpRangeI.nMaxQP = pSrcTemporalSVC->nMaxQuantizer; + pH264Enc->qpRangeP.nMinQP = pSrcTemporalSVC->nMinQuantizer; + pH264Enc->qpRangeP.nMaxQP = pSrcTemporalSVC->nMaxQuantizer; + pH264Enc->qpRangeB.nMinQP = pSrcTemporalSVC->nMinQuantizer; + pH264Enc->qpRangeB.nMaxQP = pSrcTemporalSVC->nMaxQuantizer; + + pH264Enc->nTemporalLayerCount = pSrcTemporalSVC->nTemporalLayerCount; + for (i = 0; i < OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; i++) + pH264Enc->nTemporalLayerBitrateRatio[i] = pSrcTemporalSVC->nTemporalLayerBitrateRatio[i]; + + } + break; + case OMX_IndexConfigVideoRoiInfo: + { + EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *pRoiInfo = (EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *)pComponentConfigStructure; + + if (pRoiInfo->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pH264Enc->hMFCH264Handle.bRoiInfo == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] RoiInfo is not enabled", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((pRoiInfo->bUseRoiInfo == OMX_TRUE) && + ((pRoiInfo->nRoiMBInfoSize <= 0) || (pRoiInfo->pRoiMBInfo == NULL))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] parameter is invalid : nRoiMBInfoSize(%d)/pRoiMBInfo(%p)", + pExynosComponent, __FUNCTION__, pRoiInfo->nRoiMBInfoSize, pRoiInfo->pRoiMBInfo); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + case OMX_IndexConfigIFrameRatio: + { + OMX_PARAM_U32TYPE *pIFrameRatio = (OMX_PARAM_U32TYPE *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pIFrameRatio, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pIFrameRatio->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bIFrameRatioSupport == VIDEO_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] I-Frame ratio feature is not supported", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorNoneExpiration; + goto EXIT; + } + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigAndroidVideoTemporalLayering: + { + OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *pTemporalLayering = (OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pTemporalLayering, sizeof(OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pTemporalLayering->nPortIndex != OUTPUT_PORT_INDEX) || + (pH264Enc->hMFCH264Handle.bTemporalSVC == OMX_FALSE)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pTemporalLayering->ePattern == OMX_VIDEO_AndroidTemporalLayeringPatternNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] can not disable TemporalSVC while encoding", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (((pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual) > pH264Enc->nMaxTemporalLayerCount) || + ((pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual) == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] layer count is invalid(MAX(%d), layer(%d), B-layer(%d))", + pExynosComponent, __FUNCTION__, + pH264Enc->nMaxTemporalLayerCount, + pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual, + pTemporalLayering->nBLayerCountActual); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc->nTemporalLayerCount = pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual; + if (pH264Enc->bDisableHBEncoding == OMX_TRUE) { + pH264Enc->nTemporalLayerCountForB = 0; + } else { + pH264Enc->nTemporalLayerCountForB = pTemporalLayering->nBLayerCountActual; + } + + pH264Enc->bUseTemporalLayerBitrateRatio = pTemporalLayering->bBitrateRatiosSpecified; + if (pH264Enc->bUseTemporalLayerBitrateRatio == OMX_TRUE) { + for (i = 0; i < (int)pH264Enc->nMaxTemporalLayerCount; i++) + pH264Enc->nTemporalLayerBitrateRatio[i] = (pTemporalLayering->nBitrateRatios[i] >> 16); + } else { + Exynos_OSAL_Memset(pH264Enc->nTemporalLayerBitrateRatio, 0, sizeof(pH264Enc->nTemporalLayerBitrateRatio)); + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Max(%d), layer(%d), B-layer(%d)", pExynosComponent, __FUNCTION__, + pH264Enc->nMaxTemporalLayerCount, pH264Enc->nTemporalLayerCount, pH264Enc->nTemporalLayerCountForB); + } + break; +#endif + default: +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bSkypeSupport == VIDEO_TRUE) { + ret = Exynos_H264Enc_SetConfig_SkypeHD(hComponent, nIndex, pComponentConfigStructure); + if (ret == OMX_ErrorNone) + goto EXIT; + } +#endif + ret = Exynos_OMX_VideoEncodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + OMX_PTR pDynamicConfigCMD = NULL; + pDynamicConfigCMD = Exynos_OMX_MakeDynamicConfig(nIndex, pComponentConfigStructure); + Exynos_OSAL_Queue(&pExynosComponent->dynamicConfigQ, (void *)pDynamicConfigCMD); + } + + if (ret == (OMX_ERRORTYPE)OMX_ErrorNoneExpiration) + ret = OMX_ErrorNone; + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_TEMPORALSVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigVideoTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_AVC_ENABLE_TEMPORALSVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoAVCEnableTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_ROIINFO) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigVideoRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_ENABLE_ROIINFO) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoEnableRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_PVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoEnablePVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_IFRAME_RATIO) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigIFrameRatio; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_ANDROID + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_PREPEND_SPSPPS_TO_IDR) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamPrependSPSPPSToIDR; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + ret = Exynos_OMX_VideoEncodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_H264_DRM_ENC_ROLE); + else + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_H264_ENC_ROLE); + + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_H264Enc_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = &pH264Enc->hMFCH264Handle; + OMX_COLOR_FORMATTYPE eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; + + ExynosVideoInstInfo *pVideoInstInfo = &(pH264Enc->hMFCH264Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + + FunctionIn(); + + pH264Enc->hMFCH264Handle.bConfiguredMFCSrc = OMX_FALSE; + pH264Enc->hMFCH264Handle.bConfiguredMFCDst = OMX_FALSE; + pVideoEnc->bFirstInput = OMX_TRUE; + pVideoEnc->bFirstOutput = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + if (pInputPort->eMetaDataType != METADATA_TYPE_DISABLED) { + /* metadata buffer */ + pInputPort->bufferProcessType = BUFFER_SHARE; + +#ifdef USE_ANDROID + if ((pInputPort->eMetaDataType == METADATA_TYPE_DATA) && + (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque)) { + pInputPort->eMetaDataType = METADATA_TYPE_GRAPHIC; /* AndoridOpaque means GrallocSource */ + pInputPort->bufferProcessType = BUFFER_COPY; /* will determine a process type after getting a hal format at handle */ + } +#else + if (pInputPort->eMetaDataType == METADATA_TYPE_UBM_BUFFER) { + pInputPort->bufferProcessType = BUFFER_COPY; + } +#endif + } else { + /* data buffer */ + pInputPort->bufferProcessType = BUFFER_COPY; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pInputPort->portDefinition.format.video.nFrameWidth, + pInputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.format.video.nBitrate, + pInputPort->portDefinition.format.video.xFramerate); + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pInputPort->portDefinition.format.video.xFramerate; + + /* H.264 Codec Open */ + ret = H264CodecOpen(pH264Enc, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + Exynos_SetPlaneToPort(pOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + + Exynos_OSAL_SemaphoreCreate(&pInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_OSAL_SemaphoreCreate(&pOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pH264Enc->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pH264Enc->hSourceStartEvent); + pH264Enc->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pH264Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pH264Enc->hDestinationOutStartEvent); + + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pH264Enc->hMFCH264Handle.indexTimestamp = 0; + pH264Enc->hMFCH264Handle.outputIndexTimestamp = 0; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pH264Enc->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) { + pVideoEnc->csc_handle = csc_init(CSC_METHOD_HW); + csc_set_hw_property(pVideoEnc->csc_handle, CSC_HW_PROPERTY_FIXED_NODE, 2); + csc_set_hw_property(pVideoEnc->csc_handle, CSC_HW_PROPERTY_MODE_DRM, 1); + } else { + pVideoEnc->csc_handle = csc_init(csc_method); + } + if (pVideoEnc->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVideoEnc->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_H264Enc_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoEnc != NULL) { + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + + if (pVideoEnc->csc_handle != NULL) { + csc_deinit(pVideoEnc->csc_handle); + pVideoEnc->csc_handle = NULL; + } + + if (pH264Enc != NULL) { + Exynos_OSAL_QueueTerminate(&pH264Enc->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pH264Enc->hDestinationInStartEvent); + pH264Enc->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pH264Enc->hDestinationOutStartEvent); + pH264Enc->hDestinationOutStartEvent = NULL; + pH264Enc->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pH264Enc->hSourceStartEvent); + pH264Enc->hSourceStartEvent = NULL; + pH264Enc->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + + if (pH264Enc != NULL) { + H264CodecClose(pH264Enc); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_SrcIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE inputColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt, nConfigCnt; + + FunctionIn(); + +#ifdef USE_ANDROID + { + int fps = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + + if (pVideoEnc->pPerfHandle != NULL) + Exynos_OSAL_Performance(pVideoEnc->pPerfHandle, pH264Enc->hMFCH264Handle.indexTimestamp, fps); + } +#endif + + if (pH264Enc->hMFCH264Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = H264CodecSrcSetup(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to H264CodecSrcSetup(0x%x)", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + } + if (pH264Enc->hMFCH264Handle.bConfiguredMFCDst == OMX_FALSE) { + ret = H264CodecDstSetup(pOMXComponent); + + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to H264CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + } + +#ifdef USE_SKYPE_HD + if ((pH264Enc->hMFCH264Handle.bEnableSkypeHD == OMX_TRUE) && + (pSrcInputData->dataLen > 0)) { + do { + /* process dynamic control until meet input trigger. + * if there are several input triggers, do process until empty. + */ + ret = Change_H264Enc_Param(pExynosComponent); + } while (ret == OMX_ErrorNone); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] all config messages were handled", pExynosComponent, __FUNCTION__); + } else +#endif + { + nConfigCnt = Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ); + if (nConfigCnt > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] has config message(%d)", pExynosComponent, __FUNCTION__, nConfigCnt); + while (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + Change_H264Enc_Param(pExynosComponent); + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] all config messages were handled", pExynosComponent, __FUNCTION__); + } + } + + /* DRC on Executing state through OMX_IndexConfigCommonOutputSize */ + if (pVideoEnc->bEncDRC == OMX_TRUE) { + ret = H264CodecUpdateResolution(pOMXComponent); + pVideoEnc->bEncDRC = OMX_FALSE; + goto EXIT; + } + + if ((pSrcInputData->dataLen > 0) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + pExynosComponent->timeStamp[pH264Enc->hMFCH264Handle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->bTimestampSlotUsed[pH264Enc->hMFCH264Handle.indexTimestamp] = OMX_TRUE; + pExynosComponent->nFlags[pH264Enc->hMFCH264Handle.indexTimestamp] = pSrcInputData->nFlags; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pH264Enc->hMFCH264Handle.indexTimestamp); + pEncOps->Set_FrameTag(hMFCHandle, pH264Enc->hMFCH264Handle.indexTimestamp); + pH264Enc->hMFCH264Handle.indexTimestamp++; + pH264Enc->hMFCH264Handle.indexTimestamp %= MAX_TIMESTAMP; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + { + OMX_S32 nTargetWidth, nTargetHeight; + + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + nTargetWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nTargetHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nTargetWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nTargetHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + /* rotation */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + nTargetWidth, nTargetHeight, + nDataLen, nAllocLen); + } else { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + nTargetHeight, nTargetWidth, + nDataLen, nAllocLen); + } + } + + if (pInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + if (pSrcInputData->dataLen == 0) { + for (i = 0; i < nPlaneCnt; i++) + nDataLen[i] = 0; + } else { + /* when having valid input */ + if (pSrcInputData->buffer.addr[2] != NULL) { + ExynosVideoMeta *pVideoMeta = (ExynosVideoMeta *)pSrcInputData->buffer.addr[2]; + + if (pH264Enc->hMFCH264Handle.bWeightedPrediction == OMX_TRUE) { + if (pVideoMeta->eType & VIDEO_INFO_TYPE_YSUM_DATA) { + codecReturn = pEncOps->Set_YSumData(hMFCHandle, pVideoMeta->data.enc.sYsumData.high, + pVideoMeta->data.enc.sYsumData.low); + if (codecReturn != VIDEO_ERROR_NONE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Failed to Set_YSumData()", pExynosComponent, __FUNCTION__); + } + } + + if ((pVideoMeta->eType & VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT) && + ((pVideoEnc->surfaceFormat >= OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC) && + (pVideoEnc->surfaceFormat <= OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L80))) { + int nOMXFormat = OMX_COLOR_FormatUnused; + int nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + + nOMXFormat = Exynos_OSAL_HAL2OMXColorFormat(pVideoMeta->nPixelFormat); + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nVideoFormat = Exynos_OSAL_OMX2VideoFormat(nOMXFormat, pInputPort->ePlaneType); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + if (pEncOps->Set_ActualFormat(hMFCHandle, nVideoFormat) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] set change format is failed", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] video format is changed: %d", pExynosComponent, __FUNCTION__, nVideoFormat); + } + } + } + } + } + + if ((pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bDropControlSupport == VIDEO_TRUE) && + (pVideoEnc->bDropControl == OMX_TRUE)) { + pEncOps->Set_DropControl(hMFCHandle, VIDEO_TRUE); + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + + H264CodecStart(pOMXComponent, INPUT_PORT_INDEX); + if (pH264Enc->bSourceStart == OMX_FALSE) { + pH264Enc->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pH264Enc->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + if ((pH264Enc->bDestinationStart == OMX_FALSE) && + (pH264Enc->hMFCH264Handle.bConfiguredMFCDst == OMX_TRUE)) { + pH264Enc->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pH264Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pH264Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_SrcOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else { + if (pVideoEnc->bEncDRCSync == OMX_TRUE) { + Exynos_OSAL_SignalSet(pVideoEnc->hEncDRCSyncEvent); + pVideoEnc->bEncDRCSync = OMX_FALSE; + } + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->allocSize = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->pPrivate = NULL; + } else { + int plane = 0, nPlaneCnt; + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pSrcOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pSrcOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pSrcOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == + pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]) { + pVideoEnc->pMFCEncInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoEnc->pMFCEncInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_DstIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + unsigned int nDataLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + nAllocLen[0] = pOutputPort->portDefinition.nBufferSize; + if ((pOutputPort->bufferProcessType & BUFFER_COPY) || + (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nAllocLen[0] = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nAllocLen[0] = Exynos_OSAL_GetOutBufferSize(pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.nBufferSize); +#endif + +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) { + if (nAllocLen[0] > CUSTOM_LIMITED_DRM_OUTPUT_BUFFER_SIZE) { + nAllocLen[0] = CUSTOM_LIMITED_DRM_OUTPUT_BUFFER_SIZE; + } + } +#endif + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + pDstInputData->bufferHeader); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + + H264CodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_DstOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + void *hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + ExynosVideoEncBufferOps *pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_S32 indexTimestamp = 0; + + FunctionIn(); + + if (pH264Enc->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO)", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + + + pDstOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pDstOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + + pDstOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + pDstOutputData->dataLen = pVideoBuffer->planes[0].dataSize; + pDstOutputData->remainDataLen = pVideoBuffer->planes[0].dataSize; + pDstOutputData->usedDataLen = 0; + + pDstOutputData->pPrivate = pVideoBuffer; + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoEnc->pMFCEncOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + if (pVideoEnc->bFirstOutput == OMX_FALSE) { + if (pExynosComponent->codecType != HW_VIDEO_ENC_SECURE_CODEC) { + OMX_U8 *p = NULL; + OMX_U32 iSpsSize = 0; + OMX_U32 iPpsSize = 0; + + /* start header return */ + /* Calculate sps/pps size if needed */ + p = FindDelimiter((OMX_U8 *)((char *)pDstOutputData->buffer.addr[0] + 4), + pDstOutputData->dataLen - 4); + + iSpsSize = (unsigned int)(unsigned long)((p - (OMX_U8 *)pDstOutputData->buffer.addr[0])); + pH264Enc->hMFCH264Handle.headerData.pHeaderSPS = + (OMX_PTR)pDstOutputData->buffer.addr[0]; + pH264Enc->hMFCH264Handle.headerData.SPSLen = iSpsSize; + + iPpsSize = pDstOutputData->dataLen - iSpsSize; + pH264Enc->hMFCH264Handle.headerData.pHeaderPPS = + (OMX_U8 *)pDstOutputData->buffer.addr[0] + iSpsSize; + pH264Enc->hMFCH264Handle.headerData.PPSLen = iPpsSize; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] codec specific data is generated", pExynosComponent, __FUNCTION__); + pDstOutputData->timeStamp = 0; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + pVideoEnc->bFirstOutput = OMX_TRUE; + } else { + indexTimestamp = pEncOps->Get_FrameTag(pH264Enc->hMFCH264Handle.hMFCHandle); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d(0x%x)", pExynosComponent, __FUNCTION__, indexTimestamp, indexTimestamp); + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp == INDEX_AFTER_DRC) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid frame, buffer will be discard and reused", pExynosComponent, __FUNCTION__); + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + + if (indexTimestamp == INDEX_HEADER_DATA) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] codec specific data is generated", pExynosComponent, __FUNCTION__); + indexTimestamp = pH264Enc->hMFCH264Handle.outputIndexTimestamp; + pDstOutputData->timeStamp = pExynosComponent->nFlags[indexTimestamp]; + pDstOutputData->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, frameType: %d, dataLen: %d, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pVideoBuffer->frameType, pDstOutputData->dataLen, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + ret = OMX_ErrorNone; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Tag(%x) is invalid. changes to use outputIndexTimestamp(%d)", + pExynosComponent, __FUNCTION__, + indexTimestamp, pH264Enc->hMFCH264Handle.outputIndexTimestamp); + indexTimestamp = pH264Enc->hMFCH264Handle.outputIndexTimestamp; + } else { + pH264Enc->hMFCH264Handle.outputIndexTimestamp = indexTimestamp; + } + + if (pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nBFrames > 0) { + if ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) && + (pVideoBuffer->frameType == VIDEO_FRAME_P)) { + /* move an EOS flag to previous slot + * B1 B2 P(EOS) -> P B1 B2(EOS) + * B1 P(EOS) -> P B1(EOS) + */ + int index = ((indexTimestamp - 1) < 0)? (MAX_TIMESTAMP - 1):(indexTimestamp - 1); + + if (pExynosComponent->bTimestampSlotUsed[index] == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] EOS flag is moved to %d from %d", + pExynosComponent, __FUNCTION__, + index, indexTimestamp); + pExynosComponent->nFlags[indexTimestamp] &= (~OMX_BUFFERFLAG_EOS); + pExynosComponent->nFlags[index] |= OMX_BUFFERFLAG_EOS; + } + } + } + + /* In case of Video buffer batch mode, use timestamp from MFC device driver */ + if (pVideoBuffer->timestamp != 0) + pDstOutputData->timeStamp = pVideoBuffer->timestamp; + else + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + + pExynosComponent->bTimestampSlotUsed[indexTimestamp] = OMX_FALSE; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp]; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + } + + if (pVideoBuffer->frameType == VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, frameType: %d, dataLen: %d, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pVideoBuffer->frameType, pDstOutputData->dataLen, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] got end of stream", pExynosComponent, __FUNCTION__); + + if (pExynosComponent->bBehaviorEOS == OMX_FALSE) + pDstOutputData->remainDataLen = 0; + else + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_srcInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || + (!CHECK_PORT_POPULATED(pInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = Exynos_H264Enc_SrcIn(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_srcOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || + (!CHECK_PORT_POPULATED(pInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if ((pH264Enc->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pInputPort))) { + Exynos_OSAL_SignalWait(pH264Enc->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pH264Enc->hSourceStartEvent); + } + + ret = Exynos_H264Enc_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_dstInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pH264Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pH264Enc->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pH264Enc->hDestinationInStartEvent); + } + + if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pH264Enc->bypassBufferInfoQ) > 0) { + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pH264Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if (pH264Enc->hMFCH264Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_H264Enc_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_dstOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pH264Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pH264Enc->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pH264Enc->hDestinationOutStartEvent); + } + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + if (Exynos_OSAL_GetElemNum(&pH264Enc->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pH264Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_H264Enc_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + OMX_BOOL bSecureMode = OMX_FALSE; + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || + (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H264_ENC, componentName) == 0) { + bSecureMode = OMX_FALSE; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H264_DRM_ENC, componentName) == 0) { + bSecureMode = OMX_TRUE; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = (bSecureMode == OMX_TRUE)? HW_VIDEO_ENC_SECURE_CODEC:HW_VIDEO_ENC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pH264Enc = Exynos_OSAL_Malloc(sizeof(EXYNOS_H264ENC_HANDLE)); + if (pH264Enc == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pH264Enc, 0, sizeof(EXYNOS_H264ENC_HANDLE)); + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoEnc->hCodecHandle = (OMX_HANDLETYPE)pH264Enc; + pH264Enc->qpRangeI.nMinQP = 5; + pH264Enc->qpRangeI.nMaxQP = 50; + pH264Enc->qpRangeP.nMinQP = 5; + pH264Enc->qpRangeP.nMaxQP = 50; + pH264Enc->qpRangeB.nMinQP = 5; + pH264Enc->qpRangeB.nMaxQP = 50; + + pVideoEnc->quantization.nQpI = 29; + pVideoEnc->quantization.nQpP = 30; + pVideoEnc->quantization.nQpB = 32; + + pH264Enc->chromaQPOffset.nCr = 0; + pH264Enc->chromaQPOffset.nCb = 0; + + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_H264_DRM_ENC); + else + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_H264_ENC); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + +#ifdef USE_SINGLE_PLANE_IN_DRM + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + pExynosPort->ePlaneType = PLANE_SINGLE; +#endif + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/avc"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pH264Enc->AVCComponent[i], OMX_VIDEO_PARAM_AVCTYPE); + pH264Enc->AVCComponent[i].nPortIndex = i; + pH264Enc->AVCComponent[i].eProfile = OMX_VIDEO_AVCProfileBaseline; + pH264Enc->AVCComponent[i].eLevel = OMX_VIDEO_AVCLevel31; + + pH264Enc->AVCComponent[i].nPFrames = 29; + pH264Enc->AVCComponent[i].nBFrames = 0; + pH264Enc->AVCComponent[i].nRefFrames = 1; + } + + pH264Enc->hMFCH264Handle.bTemporalSVC = OMX_FALSE; + pH264Enc->nMaxTemporalLayerCount = 0; + pH264Enc->nTemporalLayerCount = 0; + pH264Enc->bUseTemporalLayerBitrateRatio = 0; + Exynos_OSAL_Memset(pH264Enc->nTemporalLayerBitrateRatio, 0, sizeof(pH264Enc->nTemporalLayerBitrateRatio)); + + pOMXComponent->GetParameter = &Exynos_H264Enc_GetParameter; + pOMXComponent->SetParameter = &Exynos_H264Enc_SetParameter; + pOMXComponent->GetConfig = &Exynos_H264Enc_GetConfig; + pOMXComponent->SetConfig = &Exynos_H264Enc_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_H264Enc_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_H264Enc_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_H264Enc_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_H264Enc_Terminate; + + pVideoEnc->exynos_codec_srcInputProcess = &Exynos_H264Enc_srcInputBufferProcess; + pVideoEnc->exynos_codec_srcOutputProcess = &Exynos_H264Enc_srcOutputBufferProcess; + pVideoEnc->exynos_codec_dstInputProcess = &Exynos_H264Enc_dstInputBufferProcess; + pVideoEnc->exynos_codec_dstOutputProcess = &Exynos_H264Enc_dstOutputBufferProcess; + + pVideoEnc->exynos_codec_start = &H264CodecStart; + pVideoEnc->exynos_codec_stop = &H264CodecStop; + pVideoEnc->exynos_codec_bufferProcessRun = &H264CodecOutputBufferProcessRun; + pVideoEnc->exynos_codec_enqueueAllBuffer = &H264CodecEnqueueAllBuffer; + + pVideoEnc->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pVideoEnc->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoEnc->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pH264Enc); + pH264Enc = pVideoEnc->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.videoInstInfo.eCodecType = VIDEO_CODING_AVC; + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + pH264Enc->hMFCH264Handle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pH264Enc->hMFCH264Handle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + pH264Enc->hMFCH264Handle.bSkypeBitrate = OMX_FALSE; + + if (Exynos_Video_GetInstInfo(&(pH264Enc->hMFCH264Handle.videoInstInfo), VIDEO_FALSE /* enc */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pH264Enc); + pH264Enc = pVideoEnc->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for enc : temporal-svc(%d)/skype(%d)/roi(%d)/qp-range(%d)/fix(%d)/pvc(%d)/I-ratio(%d)/CA(%d)/AdaptiveBR(%d)/ChromaQP(%d)", + pExynosComponent, __FUNCTION__, + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bSkypeSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bRoiInfoSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bQpRangePBSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bFixedSliceSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bPVCSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bIFrameRatioSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bColorAspectsSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bAdaptiveLayerBitrateSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bChromaQpSupport)); + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-qp-range", (OMX_INDEXTYPE)OMX_IndexConfigVideoQPRange); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-drop-control", (OMX_INDEXTYPE)OMX_IndexParamVideoDropControl); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-disable-dfr", (OMX_INDEXTYPE)OMX_IndexParamVideoDisableDFR); + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bChromaQpSupport == VIDEO_TRUE) + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-chroma-qp-offset", (OMX_INDEXTYPE)OMX_IndexParamVideoChromaQP); + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_TRUE) + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-disable-hierarchical-b-encoding", (OMX_INDEXTYPE)OMX_IndexParamVideoDisableHBEncoding); +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bSkypeSupport == VIDEO_TRUE) { + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-caps-vt-driver-version", (OMX_INDEXTYPE)OMX_IndexSkypeParamDriverVersion); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-low-latency", (OMX_INDEXTYPE)OMX_IndexSkypeParamLowLatency); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-caps-temporal-layers", (OMX_INDEXTYPE)OMX_IndexSkypeParamEncoderMaxTemporalLayerCount); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-caps-ltr", (OMX_INDEXTYPE)OMX_IndexSkypeParamEncoderMaxLTR); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-ltr-count", (OMX_INDEXTYPE)OMX_IndexSkypeParamEncoderLTR); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-caps-preprocess", (OMX_INDEXTYPE)OMX_IndexSkypeParamEncoderPreprocess); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-custom-profile-level", (OMX_INDEXTYPE)OMX_IndexParamVideoProfileLevelCurrent); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-sar", (OMX_INDEXTYPE)OMX_IndexSkypeParamEncoderSar); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-slice", (OMX_INDEXTYPE)OMX_IndexParamVideoAvc); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-ltr", (OMX_INDEXTYPE)OMX_IndexSkypeConfigEncoderLTR); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-frame-qp", (OMX_INDEXTYPE)OMX_IndexSkypeConfigQP); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-base-layer-pid", (OMX_INDEXTYPE)OMX_IndexSkypeConfigBasePid); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-app-input-control", (OMX_INDEXTYPE)OMX_IndexSkypeParamEncoderInputControl); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-input-trigger", (OMX_INDEXTYPE)OMX_IndexSkypeConfigEncoderInputTrigger); + Exynos_OSAL_AddVendorExt(hComponent, "rtc-ext-enc-bitrate-mode", (OMX_INDEXTYPE)OMX_IndexSkypeParamVideoBitrate); + } +#endif +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoEnc->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc != NULL) { + Exynos_OSAL_Free(pH264Enc); + pH264Enc = pVideoEnc->hCodecHandle = NULL; + } + +#ifdef USE_ANDROID + Exynos_OSAL_DelVendorExts(hComponent); +#endif + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/enc/h264/Exynos_OMX_H264enc.h b/openmax/component/video/enc/h264/Exynos_OMX_H264enc.h new file mode 100644 index 0000000..baca280 --- /dev/null +++ b/openmax/component/video/enc/h264/Exynos_OMX_H264enc.h @@ -0,0 +1,135 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_H264enc.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_H264_ENC_COMPONENT +#define EXYNOS_OMX_H264_ENC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" + +#include "ExynosVideoApi.h" +#include "library_register.h" + + +typedef struct _H264_VUI_SAR { + OMX_BOOL SarEnable; + OMX_U32 SarIndex; + OMX_U32 SarWidth; + OMX_U32 SarHeight; +} H264_VUI_SAR; + +typedef struct _EXTRA_DATA +{ + OMX_PTR pHeaderSPS; + OMX_U32 SPSLen; + OMX_PTR pHeaderPPS; + OMX_U32 PPSLen; +} EXTRA_DATA; + +typedef struct _EXYNOS_MFC_H264ENC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + + OMX_BOOL bPrependSpsPpsToIdr; + OMX_BOOL bTemporalSVC; + OMX_BOOL bRoiInfo; + OMX_BOOL bWeightedPrediction; + + /* skypeHD */ + OMX_BOOL bEnableSkypeHD; + OMX_S64 nTriggerTS; + OMX_U32 nLTRFrames; + OMX_BOOL bLowLatency; + EXYNOS_OMX_HIERARCHICAL_CODING_TYPE eHierarchicalType; + H264_VUI_SAR stSarParam; + OMX_S32 nBaseLayerPid; + OMX_BOOL bSkypeBitrate; + + EXTRA_DATA headerData; + + ExynosVideoEncOps *pEncOps; + ExynosVideoEncBufferOps *pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps; + ExynosVideoEncParam encParam; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 5 + OMX_VIDEO_AVCPROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_AVCLEVELTYPE maxLevel; +} EXYNOS_MFC_H264ENC_HANDLE; + +typedef struct _EXYNOS_H264ENC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_AVCTYPE AVCComponent[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_AVCSLICEFMO AVCSliceFmo; + OMX_VIDEO_QPRANGE qpRangeI; + OMX_VIDEO_QPRANGE qpRangeP; + OMX_VIDEO_QPRANGE qpRangeB; + OMX_VIDEO_PARAM_CHROMA_QP_OFFSET chromaQPOffset; + OMX_BOOL bDisableHBEncoding; + + /* Temporal SVC */ + OMX_U32 nMaxTemporalLayerCount; + OMX_U32 nMaxTemporalLayerCountForB; + OMX_U32 nTemporalLayerCount; + OMX_U32 nTemporalLayerCountForB; + OMX_BOOL bUseTemporalLayerBitrateRatio; + OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS]; + + /* SEC MFC Codec specific */ + EXYNOS_MFC_H264ENC_HANDLE hMFCH264Handle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_H264ENC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/enc/h264/NOTICE b/openmax/component/video/enc/h264/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/enc/h264/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/enc/h264/library_register.c b/openmax/component/video/enc/h264/library_register.c new file mode 100644 index 0000000..e2810cc --- /dev/null +++ b/openmax/component/video/enc/h264/library_register.c @@ -0,0 +1,60 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents) +{ + FunctionIn(); + + if (exynosComponents == NULL) + goto EXIT; + + /* component 1 - video Encoder H.264 */ + Exynos_OSAL_Strcpy(exynosComponents[0]->componentName, EXYNOS_OMX_COMPONENT_H264_ENC); + Exynos_OSAL_Strcpy(exynosComponents[0]->roles[0], EXYNOS_OMX_COMPONENT_H264_ENC_ROLE); + exynosComponents[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 2 - video Encoder H.264 for DRM */ + Exynos_OSAL_Strcpy(exynosComponents[1]->componentName, EXYNOS_OMX_COMPONENT_H264_DRM_ENC); + Exynos_OSAL_Strcpy(exynosComponents[1]->roles[0], EXYNOS_OMX_COMPONENT_H264_DRM_ENC_ROLE); + exynosComponents[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} + diff --git a/openmax/component/video/enc/h264/library_register.h b/openmax/component/video/enc/h264/library_register.h new file mode 100644 index 0000000..4e9fd23 --- /dev/null +++ b/openmax/component/video/enc/h264/library_register.h @@ -0,0 +1,57 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_H264_REG +#define EXYNOS_OMX_H264_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 2 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* H.264 */ +#define EXYNOS_OMX_COMPONENT_H264_ENC "OMX.Exynos.AVC.Encoder" +#define EXYNOS_OMX_COMPONENT_H264_DRM_ENC "OMX.Exynos.AVC.Encoder.secure" +#define EXYNOS_OMX_COMPONENT_H264_ENC_ROLE "video_encoder.avc" +#define EXYNOS_OMX_COMPONENT_H264_DRM_ENC_ROLE "video_encoder.avc-wfd" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/openmax/component/video/enc/h264wfd/Android.mk b/openmax/component/video/enc/h264wfd/Android.mk new file mode 100644 index 0000000..ddc5220 --- /dev/null +++ b/openmax/component/video/enc/h264wfd/Android.mk @@ -0,0 +1,74 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_H264enc_wfd.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.AVC.WFD.Encoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libVendorVideoApi libExynosOMX_OSAL libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/enc \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label -Wno-unused-parameter -Wno-unused-function + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/enc/h264wfd/Exynos_OMX_H264enc_wfd.c b/openmax/component/video/enc/h264wfd/Exynos_OMX_H264enc_wfd.c new file mode 100644 index 0000000..c5703c3 --- /dev/null +++ b/openmax/component/video/enc/h264wfd/Exynos_OMX_H264enc_wfd.c @@ -0,0 +1,5747 @@ +/* + * + * Copyright 2017 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_H264enc_wfd.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * ByungGwan Kang (bk0917.kang@samsung.com) + * @version 2.0.0 + * @history + * 2017.06.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Venc.h" +#include "Exynos_OMX_VencControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OMX_H264enc_wfd.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OSAL_Queue.h" + +#include "Exynos_OSAL_Platform.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_H264_WFD_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +typedef struct _OMX_BUFFERHEADER_ARRAY { + OMX_BUFFERHEADERTYPE *pBuffer; + OMX_BOOL bInOMX; +} OMX_BUFFERHEADER_ARRAY; + +static OMX_BUFFERHEADER_ARRAY inputBufArray[MAX_BUFFER_NUM]; +static OMX_BUFFERHEADER_ARRAY outputBufArray[MAX_BUFFER_NUM]; + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.profiles[nProfileCnt++] = OMX_VIDEO_AVCProfileBaseline; + pH264Enc->hMFCH264Handle.profiles[nProfileCnt++] = OMX_VIDEO_AVCProfileMain; + pH264Enc->hMFCH264Handle.profiles[nProfileCnt++] = OMX_VIDEO_AVCProfileHigh; + pH264Enc->hMFCH264Handle.profiles[nProfileCnt++] = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedBaseline; + pH264Enc->hMFCH264Handle.profiles[nProfileCnt++] = (OMX_VIDEO_AVCPROFILETYPE)OMX_VIDEO_AVCProfileConstrainedHigh; + pH264Enc->hMFCH264Handle.nProfileCnt = nProfileCnt; + + switch (pH264Enc->hMFCH264Handle.videoInstInfo.HwVersion) { + case MFC_1501: + case MFC_150: + pH264Enc->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel6; + break; + case MFC_1400: + case MFC_140: + case MFC_130: + case MFC_120: + case MFC_1220: + case MFC_110: + case MFC_100: + case MFC_101: + pH264Enc->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel52; + break; + case MFC_80: + case MFC_90: + case MFC_1010: + case MFC_1120: + pH264Enc->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel51; + break; + case MFC_61: + case MFC_65: + case MFC_72: + case MFC_723: + case MFC_77: + case MFC_1011: + case MFC_1021: + pH264Enc->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel42; + break; + case MFC_51: + case MFC_78: + case MFC_78D: + case MFC_92: + case MFC_1020: + default: + pH264Enc->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel4; + break; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + + int nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pH264Enc->hMFCH264Handle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pH264Enc->hMFCH264Handle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pH264Enc->hMFCH264Handle.maxLevel; +#else + while ((pH264Enc->hMFCH264Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pH264Enc->hMFCH264Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pH264Enc->hMFCH264Handle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pH264Enc->hMFCH264Handle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) + goto EXIT; + + while ((pH264Enc->hMFCH264Handle.maxLevel >> nLevelCnt++) > 0); + + if ((pH264Enc->hMFCH264Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pH264Enc->hMFCH264Handle.nProfileCnt; i++) { + if (pH264Enc->hMFCH264Handle.profiles[i] == pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +static OMX_U32 OMXAVCProfileToProfileIDC(OMX_VIDEO_AVCPROFILETYPE profile) +{ + OMX_U32 ret = 0; + + if (profile == OMX_VIDEO_AVCProfileBaseline) + ret = 0; + else if ((OMX_VIDEO_AVCPROFILEEXTTYPE)profile == OMX_VIDEO_AVCProfileConstrainedBaseline) + ret = 1; + else if (profile == OMX_VIDEO_AVCProfileMain) + ret = 2; + else if (profile == OMX_VIDEO_AVCProfileHigh) + ret = 4; + else if ((OMX_VIDEO_AVCPROFILEEXTTYPE)profile == OMX_VIDEO_AVCProfileConstrainedHigh) + ret = 17; + + return ret; +} + +static OMX_U32 OMXAVCLevelToLevelIDC(OMX_VIDEO_AVCLEVELTYPE level) +{ + OMX_U32 ret = 11; //default OMX_VIDEO_AVCLevel4 + + if (level == OMX_VIDEO_AVCLevel1) + ret = 0; + else if (level == OMX_VIDEO_AVCLevel1b) + ret = 1; + else if (level == OMX_VIDEO_AVCLevel11) + ret = 2; + else if (level == OMX_VIDEO_AVCLevel12) + ret = 3; + else if (level == OMX_VIDEO_AVCLevel13) + ret = 4; + else if (level == OMX_VIDEO_AVCLevel2) + ret = 5; + else if (level == OMX_VIDEO_AVCLevel21) + ret = 6; + else if (level == OMX_VIDEO_AVCLevel22) + ret = 7; + else if (level == OMX_VIDEO_AVCLevel3) + ret = 8; + else if (level == OMX_VIDEO_AVCLevel31) + ret = 9; + else if (level == OMX_VIDEO_AVCLevel32) + ret = 10; + else if (level == OMX_VIDEO_AVCLevel4) + ret = 11; + else if (level == OMX_VIDEO_AVCLevel41) + ret = 12; + else if (level == OMX_VIDEO_AVCLevel42) + ret = 13; + else if (level == OMX_VIDEO_AVCLevel5) + ret = 14; + else if (level == OMX_VIDEO_AVCLevel51) + ret = 15; + else if (level == OMX_VIDEO_AVCLevel52) + ret = 16; + else if (level == OMX_VIDEO_AVCLevel6) + ret = 17; + + return ret; +} + +static OMX_U8 *FindDelimiter(OMX_U8 *pBuffer, OMX_U32 size) +{ + OMX_U32 i; + + for (i = 0; i < size - 3; i++) { + if ((pBuffer[i] == 0x00) && + (pBuffer[i + 1] == 0x00) && + (pBuffer[i + 2] == 0x00) && + (pBuffer[i + 3] == 0x01)) + return (pBuffer + i); + } + + return NULL; +} + +static void Print_H264WFDEnc_Param(ExynosVideoEncParam *pEncParam) +{ + ExynosVideoEncCommonParam *pCommonParam = &pEncParam->commonParam; + ExynosVideoEncH264Param *pH264Param = &pEncParam->codecParam.h264; + + /* common parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceWidth : %d", pCommonParam->SourceWidth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceHeight : %d", pCommonParam->SourceHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "IDRPeriod : %d", pCommonParam->IDRPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SliceMode : %d", pCommonParam->SliceMode); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RandomIntraMBRefresh : %d", pCommonParam->RandomIntraMBRefresh); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Bitrate : %d", pCommonParam->Bitrate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp : %d", pCommonParam->FrameQp); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_P : %d", pCommonParam->FrameQp_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(I) ranege : %d / %d", pCommonParam->QpRange.QpMin_I, pCommonParam->QpRange.QpMax_I); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(P) ranege : %d / %d", pCommonParam->QpRange.QpMin_P, pCommonParam->QpRange.QpMax_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(B) ranege : %d / %d", pCommonParam->QpRange.QpMin_B, pCommonParam->QpRange.QpMax_B); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + + /* H.264 specific parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "ProfileIDC : %d", pH264Param->ProfileIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LevelIDC : %d", pH264Param->LevelIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_B : %d", pH264Param->FrameQp_B); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameRate : %d", pH264Param->FrameRate); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SliceArgument : %d", pH264Param->SliceArgument); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberBFrames : %d", pH264Param->NumberBFrames); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberReferenceFrames : %d", pH264Param->NumberReferenceFrames); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberRefForPframes : %d", pH264Param->NumberRefForPframes); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterDisable : %d", pH264Param->LoopFilterDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterAlphaC0Offset : %d", pH264Param->LoopFilterAlphaC0Offset); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterBetaOffset : %d", pH264Param->LoopFilterBetaOffset); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SymbolMode : %d", pH264Param->SymbolMode); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PictureInterlace : %d", pH264Param->PictureInterlace); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Transform8x8Mode : %d", pH264Param->Transform8x8Mode); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "DarkDisable : %d", pH264Param->DarkDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SmoothDisable : %d", pH264Param->SmoothDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "StaticDisable : %d", pH264Param->StaticDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "ActivityDisable : %d", pH264Param->ActivityDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "HierarType: : %d", pH264Param->HierarType); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "VuiRestrictionEnable: : %d", pH264Param->VuiRestrictionEnable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "HeaderWithIFrame: : %d", pH264Param->HeaderWithIFrame); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LTRFrames: : %d", pH264Param->LTRFrames); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "ROIEnable: : %d", pH264Param->ROIEnable); + + /* rate control related parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableFRMRateControl : %d", pCommonParam->EnableFRMRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableMBRateControl : %d", pCommonParam->EnableMBRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CBRPeriodRf : %d", pCommonParam->CBRPeriodRf); +} + +static void Set_H264WFDEnc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + EXYNOS_MFC_H264WFDENC_HANDLE *pMFCH264Handle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncInitParam *pInitParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH264Param *pH264Param = NULL; + + int i; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pEncParam = &pMFCH264Handle->encParam; + pInitParam = &pEncParam->initParam; + pCommonParam = &pEncParam->commonParam; + pH264Param = &pEncParam->codecParam.h264; + pEncParam->eCompressionFormat = VIDEO_CODING_AVC; + + /* common parameters */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + pCommonParam->SourceWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + pCommonParam->SourceHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } else { + pCommonParam->SourceWidth = pOutputPort->portDefinition.format.video.nFrameHeight; + pCommonParam->SourceHeight = pOutputPort->portDefinition.format.video.nFrameWidth; + } + pCommonParam->IDRPeriod = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames + 1; + pCommonParam->SliceMode = pH264Enc->AVCSliceFmo.eSliceMode; + pCommonParam->Bitrate = pOutputPort->portDefinition.format.video.nBitrate; + pCommonParam->FrameQp = pVideoEnc->quantization.nQpI; + pCommonParam->FrameQp_P = pVideoEnc->quantization.nQpP; + + pCommonParam->QpRange.QpMin_I = pH264Enc->qpRangeI.nMinQP; + pCommonParam->QpRange.QpMax_I = pH264Enc->qpRangeI.nMaxQP; + pCommonParam->QpRange.QpMin_P = pH264Enc->qpRangeP.nMinQP; + pCommonParam->QpRange.QpMax_P = pH264Enc->qpRangeP.nMaxQP; + pCommonParam->QpRange.QpMin_B = pH264Enc->qpRangeB.nMinQP; + pCommonParam->QpRange.QpMax_B = pH264Enc->qpRangeB.nMaxQP; + + pCommonParam->PadControlOn = 0; /* 0: disable, 1: enable */ + pCommonParam->LumaPadVal = 0; + pCommonParam->CbPadVal = 0; + pCommonParam->CrPadVal = 0; + + if (pVideoEnc->intraRefresh.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic) { + /* Cyclic Mode */ + pCommonParam->RandomIntraMBRefresh = pVideoEnc->intraRefresh.nCirMBs; + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + /* Perceptual Mode */ + pCommonParam->PerceptualMode = (pVideoEnc->bPVCMode)? VIDEO_TRUE:VIDEO_FALSE; + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + /* H.264 specific parameters */ + pH264Param->ProfileIDC = OMXAVCProfileToProfileIDC(pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].eProfile); /*0: OMX_VIDEO_AVCProfileMain */ + pH264Param->LevelIDC = OMXAVCLevelToLevelIDC(pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].eLevel); /*40: OMX_VIDEO_AVCLevel4 */ + pH264Param->FrameQp_B = pVideoEnc->quantization.nQpB; + pH264Param->FrameRate = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + if (pH264Enc->AVCSliceFmo.eSliceMode == OMX_VIDEO_SLICEMODE_AVCDefault) + pH264Param->SliceArgument = 0; /* Slice mb/byte size number */ + else + pH264Param->SliceArgument = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nSliceHeaderSpacing; + + pH264Param->NumberBFrames = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nBFrames; /* 0 ~ 2 */ + pH264Param->NumberRefForPframes = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nRefFrames; /* 1 ~ 2 */ + pH264Param->NumberReferenceFrames = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nRefFrames; + + pH264Param->LoopFilterDisable = 0; /* 1: Loop Filter Disable, 0: Filter Enable */ + pH264Param->LoopFilterAlphaC0Offset = 0; + pH264Param->LoopFilterBetaOffset = 0; + pH264Param->SymbolMode = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].bEntropyCodingCABAC; /* 0: CAVLC, 1: CABAC */ + pH264Param->PictureInterlace = 0; + pH264Param->Transform8x8Mode = 1; /* 0: 4x4, 1: allow 8x8 */ + pH264Param->DarkDisable = 1; + pH264Param->SmoothDisable = 1; + pH264Param->StaticDisable = 1; + pH264Param->ActivityDisable = 1; + + /* Temporal SVC */ + /* If MaxTemporalLayerCount value is 0, codec supported max value will be set */ + pH264Param->MaxTemporalLayerCount = 0; + pH264Param->TemporalSVC.nTemporalLayerCount = (unsigned int)pH264Enc->TemporalSVC.nTemporalLayerCount; + for (i = 0; i < OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; i++) + pH264Param->TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pH264Enc->TemporalSVC.nTemporalLayerBitrateRatio[i]; + + /* Hierarchal P & B */ + pH264Param->HierarType = pH264Enc->eHierarchicalType; + + if (pH264Enc->bLowLatency == OMX_TRUE) { + pH264Param->HeaderWithIFrame = 0; /* 1: header + first frame */ + pH264Param->LoopFilterDisable = 0; /* 1: disable, 0: enable */ + pH264Param->VuiRestrictionEnable = (int)OMX_TRUE; + pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] = OMX_Video_ControlRateDisable; + pCommonParam->EnableFRMQpControl = 1; /* 0: Disable, 1: Per frame QP */ + } else { + pH264Param->VuiRestrictionEnable = (int)OMX_FALSE; + } + + pH264Param->VuiRestrictionEnable = (int)OMX_TRUE; + + pH264Param->LTRFrames = pMFCH264Handle->nLTRFrames; + + pH264Param->ROIEnable = (pMFCH264Handle->bRoiInfo == OMX_TRUE)? 1:0; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eControlRate: 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]); + /* rate control related parameters */ + switch ((int)pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]) { + case OMX_Video_ControlRateDisable: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode DBR"); + pCommonParam->EnableFRMRateControl = 0; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 0; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + case OMX_Video_ControlRateConstantVTCall: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR VT Call"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 5; + pCommonParam->bFixedSlice = VIDEO_TRUE; + break; + case OMX_Video_ControlRateConstantSkipFrames: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR VT Call with Skip frame"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 5; + pCommonParam->bFixedSlice = VIDEO_TRUE; + pInitParam->FrameSkip = VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT; + break; + case OMX_Video_ControlRateConstant: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 10; + break; + case OMX_Video_ControlRateVariable: + default: /*Android default */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode VBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + } + +// Print_H264Enc_Param(pEncParam); +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) + goto EXIT; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pH264Enc->hMFCH264Handle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE H264WFDCodecOpen( + EXYNOS_H264WFDENC_HANDLE *pH264Enc, + ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pH264Enc == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pEncOps = (ExynosVideoEncOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncOps)); + pInbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + pOutbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + + if ((pEncOps == NULL) || + (pInbufOps == NULL) || + (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.pEncOps = pEncOps; + pH264Enc->hMFCH264Handle.pInbufOps = pInbufOps; + pH264Enc->hMFCH264Handle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pEncOps->nSize = sizeof(ExynosVideoEncOps); + pInbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + + if (Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for encoder ops */ + if ((pEncOps->Init == NULL) || + (pEncOps->Finalize == NULL) || + (pEncOps->Set_FrameTag == NULL) || + (pEncOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pH264Enc->hMFCH264Handle.hMFCHandle = pH264Enc->hMFCH264Handle.pEncOps->Init(pVideoInstInfo); + if (pH264Enc->hMFCH264Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pH264Enc->hMFCH264Handle.pEncOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pH264Enc->hMFCH264Handle.pInbufOps = NULL; + } + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pH264Enc->hMFCH264Handle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264WFDCodecClose(EXYNOS_H264WFDENC_HANDLE *pH264Enc) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pH264Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + + if (hMFCHandle != NULL) { + pEncOps->Finalize(hMFCHandle); + hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle = NULL; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Encoder(pEncOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps = NULL; + } + + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pEncOps = pH264Enc->hMFCH264Handle.pEncOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264WFDCodecStart( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + + if (nPortIndex == INPUT_PORT_INDEX) + pInbufOps->Run(hMFCHandle); + else if (nPortIndex == OUTPUT_PORT_INDEX) + pOutbufOps->Run(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264WFDCodecStop( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) + pInbufOps->Stop(hMFCHandle); + else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) + pOutbufOps->Stop(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264WFDEnc_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nParamIndex %x", pExynosComponent, __FUNCTION__, (int)nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = (OMX_VIDEO_PARAM_AVCTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCTYPE *pSrcAVCComponent = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstAVCComponent, sizeof(OMX_VIDEO_PARAM_AVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstAVCComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcAVCComponent = &pH264Enc->AVCComponent[pDstAVCComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstAVCComponent) + nOffset, + ((char *)pSrcAVCComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_AVCTYPE) - nOffset); + } + break; + case OMX_IndexParamVideoSliceFMO: + { + OMX_VIDEO_PARAM_AVCSLICEFMO *pDstSliceFmo = (OMX_VIDEO_PARAM_AVCSLICEFMO *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCSLICEFMO *pSrcSliceFmo = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstSliceFmo, sizeof(OMX_VIDEO_PARAM_AVCSLICEFMO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pSrcSliceFmo = &pH264Enc->AVCSliceFmo; + + Exynos_OSAL_Memcpy(((char *)pDstSliceFmo) + nOffset, + ((char *)pSrcSliceFmo) + nOffset, + sizeof(OMX_VIDEO_PARAM_AVCSLICEFMO) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H264_WFD_ENC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCTYPE *pSrcAVCComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcAVCComponent = &pH264Enc->AVCComponent[pDstProfileLevel->nPortIndex]; + pDstProfileLevel->eProfile = pSrcAVCComponent->eProfile; + pDstProfileLevel->eLevel = pSrcAVCComponent->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pH264Enc->errorCorrectionType[OUTPUT_PORT_INDEX]; + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pH264Enc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pH264Enc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pH264Enc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pH264Enc->qpRangeP.nMaxQP; + pQpRange->qpRangeB.nMinQP = pH264Enc->qpRangeB.nMinQP; + pQpRange->qpRangeB.nMaxQP = pH264Enc->qpRangeB.nMaxQP; + } + break; + case OMX_IndexParamVideoAVCEnableTemporalSVC: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *pDstEnableTemporalSVC = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstEnableTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstEnableTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstEnableTemporalSVC->bEnableTemporalSVC = pH264Enc->hMFCH264Handle.bTemporalSVC; + } + break; + case OMX_IndexParamVideoEnableRoiInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *pDstEnableRoiInfo = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstEnableRoiInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstEnableRoiInfo->bEnableRoiInfo = pH264Enc->hMFCH264Handle.bRoiInfo; + } + break; + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pEnablePVC->nU32 = pVideoEnc->bPVCMode; + } + break; + + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *pPortParam = (OMX_PORT_PARAM_TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pPortParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pPortParam->nPorts = pExynosComponent->portParam.nPorts; + pPortParam->nStartPortNumber = pExynosComponent->portParam.nStartPortNumber; + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *pPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortFormat->nPortIndex; + OMX_U32 nIndex = pPortFormat->nIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (nIndex > (INPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pPortDef = &pExynosPort->portDefinition; + + pPortFormat->eCompressionFormat = OMX_VIDEO_CodingUnused; + pPortFormat->xFramerate = pPortDef->format.video.xFramerate; + + if (pExynosPort->supportFormat[nIndex] == OMX_COLOR_FormatUnused) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + pPortFormat->eColorFormat = pExynosPort->supportFormat[nIndex]; + } else if (nPortIndex == OUTPUT_PORT_INDEX) { + if (nIndex > (OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pPortDef = &pExynosPort->portDefinition; + + pPortFormat->eCompressionFormat = pPortDef->format.video.eCompressionFormat; + pPortFormat->xFramerate = pPortDef->format.video.xFramerate; + pPortFormat->eColorFormat = pPortDef->format.video.eColorFormat; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE *pVideoBitrate = (OMX_VIDEO_PARAM_BITRATETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoBitrate->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pPortDef = &pExynosPort->portDefinition; + + pVideoBitrate->eControlRate = pVideoEnc->eControlRate[nPortIndex]; + pVideoBitrate->nTargetBitrate = pPortDef->format.video.nBitrate; + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoQuantization: + { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *pVideoQuantization = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoQuantization->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pPortDef = &pExynosPort->portDefinition; + + pVideoQuantization->nQpI = pVideoEnc->quantization.nQpI; + pVideoQuantization->nQpP = pVideoEnc->quantization.nQpP; + pVideoQuantization->nQpB = pVideoEnc->quantization.nQpB; + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 portIndex = portDefinition->nPortIndex; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(portDefinition, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + Exynos_OSAL_Memcpy(((char *)portDefinition) + nOffset, + ((char *)&pExynosPort->portDefinition) + nOffset, + portDefinition->nSize - nOffset); + + ret = Exynos_OSAL_GetParameter(hComponent, nParamIndex, pComponentParameterStructure); + if (ret != OMX_ErrorNone) + goto EXIT; + } + break; + case OMX_IndexVendorNeedContigMemory: + { + EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *pPortMemType = (EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortMemType->nPortIndex; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortMemType, sizeof(EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + pPortMemType->bNeedContigMem = pExynosPort->bNeedContigMem; + } + break; + case OMX_IndexParamVideoIntraRefresh: + { + OMX_VIDEO_PARAM_INTRAREFRESHTYPE *pIntraRefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pIntraRefresh->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pIntraRefresh, sizeof(OMX_VIDEO_PARAM_INTRAREFRESHTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pIntraRefresh->eRefreshMode = pVideoEnc->intraRefresh.eRefreshMode; + pIntraRefresh->nAirMBs = pVideoEnc->intraRefresh.nAirMBs; + pIntraRefresh->nAirRef = pVideoEnc->intraRefresh.nAirRef; + pIntraRefresh->nCirMBs = pVideoEnc->intraRefresh.nCirMBs; + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamRotationInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *pRotationInfo = (EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *)pComponentParameterStructure; + OMX_U32 nPortIndex = pRotationInfo->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pRotationInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pRotationInfo->eRotationType = pVideoEnc->eRotationType; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamConsumerUsageBits: + { + ret = Exynos_OSAL_GetParameter(hComponent, nParamIndex, pComponentParameterStructure); + } + break; +#endif + + // below is from Exynos_OMX_GetParameter + case OMX_IndexParamAudioInit: + case OMX_IndexParamImageInit: + case OMX_IndexParamOtherInit: + { + OMX_PORT_PARAM_TYPE *portParam = (OMX_PORT_PARAM_TYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(portParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + portParam->nPorts = 0; + portParam->nStartPortNumber = 0; + } + break; + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *compPriority = (OMX_PRIORITYMGMTTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(compPriority, sizeof(OMX_PRIORITYMGMTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + compPriority->nGroupID = pExynosComponent->compPriority.nGroupID; + compPriority->nGroupPriority = pExynosComponent->compPriority.nGroupPriority; + } + break; + + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplier = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pComponentParameterStructure; + OMX_U32 portIndex = bufferSupplier->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort; + + if ((pExynosComponent->currentState == OMX_StateLoaded) || + (pExynosComponent->currentState == OMX_StateWaitForResources)) { + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(bufferSupplier, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + + + if (pExynosPort->portDefinition.eDir == OMX_DirInput) { + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyInput; + } else if (CHECK_PORT_TUNNELED(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyOutput; + } else { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyUnspecified; + } + } else { + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyOutput; + } else if (CHECK_PORT_TUNNELED(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyInput; + } else { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyUnspecified; + } + } + } + else + { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + break; + default: + { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264WFDEnc_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = NULL; + OMX_VIDEO_PARAM_AVCTYPE *pSrcAVCComponent = (OMX_VIDEO_PARAM_AVCTYPE *)pComponentParameterStructure; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcAVCComponent, sizeof(OMX_VIDEO_PARAM_AVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcAVCComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstAVCComponent = &pH264Enc->AVCComponent[pSrcAVCComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstAVCComponent) + nOffset, + ((char *)pSrcAVCComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_AVCTYPE) - nOffset); + + if (pDstAVCComponent->nBFrames > 2) { /* 0 ~ 2 */ + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] nBFrames(%d) is over a maximum value(2). it is limited to max", + pExynosComponent, __FUNCTION__, pDstAVCComponent->nBFrames); + pDstAVCComponent->nBFrames = 2; + } + + if (pDstAVCComponent->nRefFrames > 2) { /* 1 ~ 2 */ + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] nRefFrames(%d) is over a maximum value(2). it is limited to max", + pExynosComponent, __FUNCTION__, pDstAVCComponent->nRefFrames); + pDstAVCComponent->nRefFrames = 2; + } else if (pDstAVCComponent->nRefFrames == 0) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] nRefFrames(%d) is smaller than minimum value(1). it is limited to min", + pExynosComponent, __FUNCTION__, pDstAVCComponent->nRefFrames); + pDstAVCComponent->nRefFrames = 1; + } + } + break; + case OMX_IndexParamVideoSliceFMO: + { + OMX_VIDEO_PARAM_AVCSLICEFMO *pSrcSliceFmo = (OMX_VIDEO_PARAM_AVCSLICEFMO *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCSLICEFMO *pDstSliceFmo = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcSliceFmo, sizeof(OMX_VIDEO_PARAM_AVCSLICEFMO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDstSliceFmo = &pH264Enc->AVCSliceFmo; + + Exynos_OSAL_Memcpy(((char *)pDstSliceFmo) + nOffset, + ((char *)pSrcSliceFmo) + nOffset, + sizeof(OMX_VIDEO_PARAM_AVCSLICEFMO) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H264_WFD_ENC_ROLE)) { + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstAVCComponent = &pH264Enc->AVCComponent[pSrcProfileLevel->nPortIndex]; + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstAVCComponent->eProfile = pSrcProfileLevel->eProfile; + pDstAVCComponent->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pH264Enc->errorCorrectionType[OUTPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP) || + (pQpRange->qpRangeB.nMinQP > pQpRange->qpRangeB.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d], B[min:%d, max:%d])", __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP, + pQpRange->qpRangeB.nMinQP, pQpRange->qpRangeB.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pH264Enc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pH264Enc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pH264Enc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + pH264Enc->qpRangeB.nMinQP = pQpRange->qpRangeB.nMinQP; + pH264Enc->qpRangeB.nMaxQP = pQpRange->qpRangeB.nMaxQP; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamPrependSPSPPSToIDR: + { + ret = Exynos_OSAL_SetPrependSPSPPSToIDR(pComponentParameterStructure, &(pH264Enc->hMFCH264Handle.bPrependSpsPpsToIdr)); + } + break; +#endif + case OMX_IndexParamVideoAVCEnableTemporalSVC: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *pSrcEnableTemporalSVC = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *)pComponentParameterStructure; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition); + int i; + + ret = Exynos_OMX_Check_SizeVersion(pSrcEnableTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcEnableTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) && + (pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] MFC D/D doesn't support Temporal SVC", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.bTemporalSVC = pSrcEnableTemporalSVC->bEnableTemporalSVC; + if ((pH264Enc->hMFCH264Handle.bTemporalSVC == OMX_TRUE) && + (pH264Enc->TemporalSVC.nTemporalLayerCount == 0)) { /* not initialized yet */ + pH264Enc->TemporalSVC.nTemporalLayerCount = 1; + pH264Enc->TemporalSVC.nTemporalLayerBitrateRatio[0] = pPortDef->format.video.nBitrate; + } else if (pH264Enc->hMFCH264Handle.bTemporalSVC == OMX_FALSE) { /* set default value */ + pH264Enc->TemporalSVC.nTemporalLayerCount = 0; + for (i = 0; i < OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; i++) + pH264Enc->TemporalSVC.nTemporalLayerBitrateRatio[i] = pPortDef->format.video.nBitrate; + } + } + break; + case OMX_IndexParamVideoEnableRoiInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *pSrcEnableRoiInfo = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pSrcEnableRoiInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bRoiInfoSupport == VIDEO_FALSE) && + (pSrcEnableRoiInfo->bEnableRoiInfo == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] MFC D/D doesn't support Roi Info", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.bRoiInfo = pSrcEnableRoiInfo->bEnableRoiInfo; + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortDef->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[nPortIndex];; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + if (pPortDef->nBufferCountActual < pExynosPort->portDefinition.nBufferCountMin) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pPortDef->format.video.xFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] xFramerate is invalid(%d)", + pExynosComponent, __FUNCTION__, pPortDef->format.video.xFramerate >> 16); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Memcpy(((char *)&pExynosPort->portDefinition) + nOffset, + ((char *)pPortDef) + nOffset, + pPortDef->nSize - nOffset); + if (nPortIndex == INPUT_PORT_INDEX) { + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + Exynos_UpdateFrameSize(pOMXComponent); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] pOutputPort->portDefinition.nBufferSize: %d", pExynosComponent, __FUNCTION__, pExynosPort->portDefinition.nBufferSize); + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoEnc->bPVCMode = (pEnablePVC->nU32)? OMX_TRUE:OMX_FALSE; + } + break; + + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *pPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortFormat->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pPortDef = &(pExynosComponent->pExynosPort[nPortIndex].portDefinition); + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pPortFormat->xFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] xFramerate is invalid(%d)", + pExynosComponent, __FUNCTION__, pPortFormat->xFramerate >> 16); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pPortDef->format.video.eColorFormat = pPortFormat->eColorFormat; + pPortDef->format.video.eCompressionFormat = pPortFormat->eCompressionFormat; + pPortDef->format.video.xFramerate = pPortFormat->xFramerate; + } + break; + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE *pVideoBitrate = (OMX_VIDEO_PARAM_BITRATETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoBitrate->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pPortDef = &(pExynosComponent->pExynosPort[nPortIndex].portDefinition); + pVideoEnc->eControlRate[nPortIndex] = pVideoBitrate->eControlRate; + pPortDef->format.video.nBitrate = pVideoBitrate->nTargetBitrate; + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoQuantization: + { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *pVideoQuantization = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoQuantization->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pPortDef = &pExynosPort->portDefinition; + + pVideoEnc->quantization.nQpI = pVideoQuantization->nQpI; + pVideoEnc->quantization.nQpP = pVideoQuantization->nQpP; + pVideoEnc->quantization.nQpB = pVideoQuantization->nQpB; + } + ret = OMX_ErrorNone; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamStoreMetaDataBuffer: + case OMX_IndexParamAllocateNativeHandle: + { + ret = Exynos_OSAL_SetParameter(hComponent, nIndex, pComponentParameterStructure); + } + break; +#endif + case OMX_IndexVendorNeedContigMemory: + { + EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *pPortMemType = (EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortMemType->nPortIndex; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortMemType, sizeof(EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + pExynosPort->bNeedContigMem = pPortMemType->bNeedContigMem; + } + break; + case OMX_IndexParamVideoIntraRefresh: + { + OMX_VIDEO_PARAM_INTRAREFRESHTYPE *pIntraRefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pIntraRefresh->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pIntraRefresh, sizeof(OMX_VIDEO_PARAM_INTRAREFRESHTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pIntraRefresh->eRefreshMode == OMX_VIDEO_IntraRefreshCyclic) { + pVideoEnc->intraRefresh.eRefreshMode = pIntraRefresh->eRefreshMode; + pVideoEnc->intraRefresh.nCirMBs = pIntraRefresh->nCirMBs; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX_VIDEO_IntraRefreshCyclic Enable, nCirMBs: %d", + pVideoEnc->intraRefresh.nCirMBs); + } else { + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamEnableBlurFilter: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_BLURFILTER *pBlurMode = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_BLURFILTER *)pComponentParameterStructure; + OMX_U32 nPortIndex = pBlurMode->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pBlurMode, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_BLURFILTER)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pVideoEnc->bUseBlurFilter = pBlurMode->bUseBlurFilter; + } + break; + case OMX_IndexParamRotationInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *pRotationInfo = (EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *)pComponentParameterStructure; + OMX_U32 nPortIndex = pRotationInfo->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pRotationInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pRotationInfo->eRotationType != ROTATE_0) && + (pRotationInfo->eRotationType != ROTATE_90) && + (pRotationInfo->eRotationType != ROTATE_180) && + (pRotationInfo->eRotationType != ROTATE_270)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] can't accecpt a rotation value(%d)", pExynosComponent, __FUNCTION__, + pRotationInfo->eRotationType); + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + pVideoEnc->eRotationType = pRotationInfo->eRotationType; + } + break; + + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParam = (OMX_PORT_PARAM_TYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(portParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + /* ret = OMX_ErrorUndefined; */ + /* Exynos_OSAL_Memcpy(&pExynosComponent->portParam, portParam, sizeof(OMX_PORT_PARAM_TYPE)); */ + } + break; + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *compPriority = (OMX_PRIORITYMGMTTYPE *)pComponentParameterStructure; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(compPriority, sizeof(OMX_PRIORITYMGMTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosComponent->compPriority.nGroupID = compPriority->nGroupID; + pExynosComponent->compPriority.nGroupPriority = compPriority->nGroupPriority; + } + break; + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplier = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pComponentParameterStructure; + OMX_U32 portIndex = bufferSupplier->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(bufferSupplier, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyUnspecified) { + ret = OMX_ErrorNone; + goto EXIT; + } + if (CHECK_PORT_TUNNELED(pExynosPort) == 0) { + ret = OMX_ErrorNone; /*OMX_ErrorNone ?????*/ + goto EXIT; + } + + if (pExynosPort->portDefinition.eDir == OMX_DirInput) { + if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyInput) { + /* + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorNone; + } + */ + pExynosPort->tunnelFlags |= EXYNOS_TUNNEL_IS_SUPPLIER; + bufferSupplier->nPortIndex = pExynosPort->tunneledPort; + ret = OMX_SetParameter(pExynosPort->tunneledComponent, OMX_IndexParamCompBufferSupplier, bufferSupplier); + goto EXIT; + } else if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyOutput) { + ret = OMX_ErrorNone; + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + pExynosPort->tunnelFlags &= ~EXYNOS_TUNNEL_IS_SUPPLIER; + bufferSupplier->nPortIndex = pExynosPort->tunneledPort; + ret = OMX_SetParameter(pExynosPort->tunneledComponent, OMX_IndexParamCompBufferSupplier, bufferSupplier); + } + goto EXIT; + } + } else if (pExynosPort->portDefinition.eDir == OMX_DirOutput) { + if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyInput) { + ret = OMX_ErrorNone; + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + pExynosPort->tunnelFlags &= ~EXYNOS_TUNNEL_IS_SUPPLIER; + ret = OMX_ErrorNone; + } + goto EXIT; + } else if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyOutput) { + /* + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorNone; + } + */ + pExynosPort->tunnelFlags |= EXYNOS_TUNNEL_IS_SUPPLIER; + ret = OMX_ErrorNone; + goto EXIT; + } + } + } + break; + default: + { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264WFDEnc_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoAVCIntraPeriod: + { + OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pAVCIntraPeriod = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pComponentConfigStructure; + OMX_U32 portIndex = pAVCIntraPeriod->nPortIndex; + + if ((portIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pAVCIntraPeriod->nIDRPeriod = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames + 1; + pAVCIntraPeriod->nPFrames = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames; + } + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pH264Enc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pH264Enc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pH264Enc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pH264Enc->qpRangeP.nMaxQP; + pQpRange->qpRangeB.nMinQP = pH264Enc->qpRangeB.nMinQP; + pQpRange->qpRangeB.nMaxQP = pH264Enc->qpRangeB.nMaxQP; + } + break; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pDstTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pComponentConfigStructure; + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pSrcTemporalSVC = &pH264Enc->TemporalSVC; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcTemporalSVC->nKeyFrameInterval = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames + 1; + pSrcTemporalSVC->nMinQuantizer = pH264Enc->qpRangeI.nMinQP; + pSrcTemporalSVC->nMaxQuantizer = pH264Enc->qpRangeI.nMaxQP; + + Exynos_OSAL_Memcpy(((char *)pDstTemporalSVC) + nOffset, + ((char *)pSrcTemporalSVC) + nOffset, + sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC) - nOffset); + } + break; + + // below is from Exynos_OMX_VideoEncodeGetConfig + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigBitrate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pConfigBitrate->nEncodeBitrate = pExynosPort->portDefinition.format.video.nBitrate; + } + } + break; + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pConfigFramerate->xEncodeFramerate = pExynosPort->portDefinition.format.video.xFramerate; + } + break; + case OMX_IndexVendorGetBufferFD: + { + EXYNOS_OMX_VIDEO_CONFIG_BUFFERINFO *pBufferInfo = (EXYNOS_OMX_VIDEO_CONFIG_BUFFERINFO *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pBufferInfo, sizeof(EXYNOS_OMX_VIDEO_CONFIG_BUFFERINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pBufferInfo->fd = Exynos_OSAL_SharedMemory_VirtToION(pVideoEnc->hSharedMemory, pBufferInfo->pVirAddr); + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigVideoColorAspects: + { + ret = Exynos_OSAL_GetConfig(hComponent, nIndex, pComponentConfigStructure); + } + break; +#endif + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264WFDEnc_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + EXYNOS_MFC_H264WFDENC_HANDLE *pMFCH264WFDHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + if (&(pH264Enc->hMFCH264Handle) == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMFCH264WFDHandle = (EXYNOS_MFC_H264WFDENC_HANDLE *)&pH264Enc->hMFCH264Handle; + + if (pMFCH264WFDHandle->pEncOps == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pEncOps = (ExynosVideoEncOps *)pMFCH264WFDHandle->pEncOps; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_U32 nPFrames = (*((OMX_U32 *)pComponentConfigStructure)) - 1; + pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames = nPFrames; + pEncOps->Set_IDRPeriod(pH264Enc->hMFCH264Handle.hMFCHandle, nPFrames + 1); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] IDR period: %d", pExynosComponent, __FUNCTION__, nPFrames + 1); + ret = OMX_ErrorNone ; + } + break; + case OMX_IndexConfigVideoAVCIntraPeriod: + { + OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pAVCIntraPeriod = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pComponentConfigStructure; + OMX_U32 portIndex = pAVCIntraPeriod->nPortIndex; + + if ((portIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + if (pAVCIntraPeriod->nIDRPeriod == (pAVCIntraPeriod->nPFrames + 1)) { + pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames = pAVCIntraPeriod->nPFrames; + pEncOps->Set_IDRPeriod(pMFCH264WFDHandle->hMFCHandle, pAVCIntraPeriod->nIDRPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] IDR period: %d", pExynosComponent, __FUNCTION__, pAVCIntraPeriod->nIDRPeriod); + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + ExynosVideoQPRange qpRange; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP) || + (pQpRange->qpRangeB.nMinQP > pQpRange->qpRangeB.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d], B[min:%d, max:%d])", __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP, + pQpRange->qpRangeB.nMinQP, pQpRange->qpRangeB.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pH264Enc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pH264Enc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pH264Enc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + pH264Enc->qpRangeB.nMinQP = pQpRange->qpRangeB.nMinQP; + pH264Enc->qpRangeB.nMaxQP = pQpRange->qpRangeB.nMaxQP; + + qpRange.QpMin_I = pQpRange->qpRangeI.nMinQP; + qpRange.QpMax_I = pQpRange->qpRangeI.nMaxQP; + qpRange.QpMin_P = pQpRange->qpRangeP.nMinQP; + qpRange.QpMax_P = pQpRange->qpRangeP.nMaxQP; + qpRange.QpMin_B = pQpRange->qpRangeB.nMinQP; + qpRange.QpMax_B = pQpRange->qpRangeB.nMaxQP; + + pEncOps->Set_QpRange(pMFCH264WFDHandle->hMFCHandle, qpRange); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qp range: I(%d, %d), P(%d, %d), B(%d, %d)", + pExynosComponent, __FUNCTION__, + qpRange.QpMin_I, qpRange.QpMax_I, + qpRange.QpMin_P, qpRange.QpMax_P, + qpRange.QpMin_B, qpRange.QpMax_B); + } + break; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pDstTemporalSVC = &pH264Enc->TemporalSVC; + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pSrcTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pComponentConfigStructure; + ExynosVideoQPRange qpRange; + TemporalLayerShareBuffer TemporalSVC; + + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.bTemporalSVC == OMX_FALSE) || + (pSrcTemporalSVC->nTemporalLayerCount > OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames = pSrcTemporalSVC->nKeyFrameInterval - 1; + + pH264Enc->qpRangeI.nMinQP = pSrcTemporalSVC->nMinQuantizer; + pH264Enc->qpRangeI.nMaxQP = pSrcTemporalSVC->nMaxQuantizer; + pH264Enc->qpRangeP.nMinQP = pSrcTemporalSVC->nMinQuantizer; + pH264Enc->qpRangeP.nMaxQP = pSrcTemporalSVC->nMaxQuantizer; + pH264Enc->qpRangeB.nMinQP = pSrcTemporalSVC->nMinQuantizer; + pH264Enc->qpRangeB.nMaxQP = pSrcTemporalSVC->nMaxQuantizer; + + Exynos_OSAL_Memcpy(((char *)pDstTemporalSVC) + nOffset, + ((char *)pSrcTemporalSVC) + nOffset, + sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC) - nOffset); + + qpRange.QpMin_I = pDstTemporalSVC->nMinQuantizer; + qpRange.QpMax_I = pDstTemporalSVC->nMaxQuantizer; + qpRange.QpMin_P = pDstTemporalSVC->nMinQuantizer; + qpRange.QpMax_P = pDstTemporalSVC->nMaxQuantizer; + qpRange.QpMin_B = pDstTemporalSVC->nMinQuantizer; + qpRange.QpMax_B = pDstTemporalSVC->nMaxQuantizer; + + pEncOps->Set_QpRange(pMFCH264WFDHandle->hMFCHandle, qpRange); + pEncOps->Set_IDRPeriod(pMFCH264WFDHandle->hMFCHandle, pDstTemporalSVC->nKeyFrameInterval); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // qp range: I(%d, %d), P(%d, %d), B(%d, %d)", + pExynosComponent, __FUNCTION__, + qpRange.QpMin_I, qpRange.QpMax_I, + qpRange.QpMin_P, qpRange.QpMax_P, + qpRange.QpMin_B, qpRange.QpMax_B); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // IDR period: %d", pExynosComponent, __FUNCTION__, pDstTemporalSVC->nKeyFrameInterval); + + /* Temporal SVC */ + Exynos_OSAL_Memset(&TemporalSVC, 0, sizeof(TemporalLayerShareBuffer)); + + TemporalSVC.nTemporalLayerCount = (unsigned int)pDstTemporalSVC->nTemporalLayerCount; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // layer count: %d", pExynosComponent, __FUNCTION__, TemporalSVC.nTemporalLayerCount); + + for (i = 0; i < OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; i++) { + TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pDstTemporalSVC->nTemporalLayerBitrateRatio[i]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // bitrate ratio[%d]: %d", + pExynosComponent, __FUNCTION__, + i, TemporalSVC.nTemporalLayerBitrateRatio[i]); + } + if (pEncOps->Set_LayerChange(pMFCH264WFDHandle->hMFCHandle, TemporalSVC) != VIDEO_ERROR_NONE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Not supported control: Set_LayerChange", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigVideoRoiInfo: + { + EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *pRoiInfo = (EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *)pComponentConfigStructure; + RoiInfoShareBuffer RoiInfo; + + if (pRoiInfo->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.bRoiInfo == OMX_FALSE) || + ((pRoiInfo->bUseRoiInfo == OMX_TRUE) && + ((pRoiInfo->nRoiMBInfoSize <= 0) || + (pRoiInfo->pRoiMBInfo == NULL)))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: bUseRoiInfo %d nRoiMBInfoSize %d pRoiMBInfo %p", __FUNCTION__, __LINE__, + pRoiInfo->bUseRoiInfo, pRoiInfo->nRoiMBInfoSize, pRoiInfo->pRoiMBInfo); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Memset(&RoiInfo, 0, sizeof(RoiInfo)); + RoiInfo.pRoiMBInfo = (OMX_U64)(unsigned long)(((OMX_U8 *)pComponentConfigStructure) + sizeof(EXYNOS_OMX_VIDEO_CONFIG_ROIINFO)); + RoiInfo.nRoiMBInfoSize = pRoiInfo->nRoiMBInfoSize; + RoiInfo.nUpperQpOffset = pRoiInfo->nUpperQpOffset; + RoiInfo.nLowerQpOffset = pRoiInfo->nLowerQpOffset; + RoiInfo.bUseRoiInfo = (pRoiInfo->bUseRoiInfo == OMX_TRUE)? VIDEO_TRUE:VIDEO_FALSE; + if (pEncOps->Set_RoiInfo != NULL) { + pEncOps->Set_RoiInfo(pMFCH264WFDHandle->hMFCHandle, &RoiInfo); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] roi info: %s", pExynosComponent, __FUNCTION__, + (RoiInfo.bUseRoiInfo == VIDEO_TRUE)? "enabled":"disabled"); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s]: Not supported control: Set_RoiInfo", + pExynosComponent, __FUNCTION__); + } + } + break; + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigBitrate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + if (pVideoEnc->eControlRate[nPortIndex] == OMX_Video_ControlRateDisable) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Rate control(eControlRate) is disable. can not change a bitrate", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pExynosPort->portDefinition.format.video.nBitrate = pConfigBitrate->nEncodeBitrate; + pEncOps->Set_BitRate(pH264Enc->hMFCH264Handle.hMFCHandle, pConfigBitrate->nEncodeBitrate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bitrate: %d", pExynosComponent, __FUNCTION__, pConfigBitrate->nEncodeBitrate); + } + } + break; + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pConfigFramerate->xEncodeFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] xFramerate is invalid(%d)", + pExynosComponent, __FUNCTION__, pConfigFramerate->xEncodeFramerate >> 16); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pExynosPort->portDefinition.format.video.xFramerate = pConfigFramerate->xEncodeFramerate; + + pEncOps->Set_FrameRate(pH264Enc->hMFCH264Handle.hMFCHandle, (pConfigFramerate->xEncodeFramerate) >> 16); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] framerate: %d", pExynosComponent, __FUNCTION__, (pConfigFramerate->xEncodeFramerate) >> 16); + } + break; + case OMX_IndexConfigVideoIntraVOPRefresh: + { + OMX_CONFIG_INTRAREFRESHVOPTYPE *pIntraRefreshVOP = (OMX_CONFIG_INTRAREFRESHVOPTYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pIntraRefreshVOP->nPortIndex; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pVideoEnc->IntraRefreshVOP = pIntraRefreshVOP->IntraRefreshVOP; + } + + pEncOps->Set_FrameType(pMFCH264WFDHandle->hMFCHandle, VIDEO_FRAME_I); + pVideoEnc->IntraRefreshVOP = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] VOP Refresh", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigOperatingRate: /* since M version */ + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pComponentConfigStructure; + OMX_U32 xFramerate = 0; + + ret = Exynos_OMX_Check_SizeVersion(pConfigRate, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + pVideoEnc->nQosRatio = pConfigRate->nU32 >> 16; + + if (pVideoEnc->nQosRatio == (((OMX_U32)INT_MAX) >> 16)) { + pVideoEnc->nQosRatio = 1000; + } else { + pVideoEnc->nQosRatio = ((xFramerate >> 16) == 0)? 100:(OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + } + + pEncOps->Set_QosRatio(pMFCH264WFDHandle->hMFCHandle, pVideoEnc->nQosRatio); + + pVideoEnc->bQosChanged = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qos ratio: 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->nQosRatio); + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexConfigBlurInfo: + { + EXYNOS_OMX_VIDEO_CONFIG_BLURINFO *pBlurMode = (EXYNOS_OMX_VIDEO_CONFIG_BLURINFO *)pComponentConfigStructure; + OMX_U32 nPortIndex = pBlurMode->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + int nEncResol; + + ret = Exynos_OMX_Check_SizeVersion(pBlurMode, sizeof(EXYNOS_OMX_VIDEO_CONFIG_BLURINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + nEncResol = pExynosPort->portDefinition.format.video.nFrameWidth * pExynosPort->portDefinition.format.video.nFrameHeight; + + if (pVideoEnc->bUseBlurFilter == OMX_TRUE) { + if ((pBlurMode->eBlurMode & BLUR_MODE_DOWNUP) && + (nEncResol < (int)pBlurMode->eTargetResol)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Resolution(%d x %d) is smaller than target resolution", + pExynosComponent, __FUNCTION__, + pExynosPort->portDefinition.format.video.nFrameWidth, + pExynosPort->portDefinition.format.video.nFrameHeight); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc->eBlurMode = pBlurMode->eBlurMode; + pVideoEnc->eBlurResol = pBlurMode->eTargetResol; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Blur Filter is not enabled, it will be discard", + pExynosComponent, __FUNCTION__); + } + + ret = (OMX_ERRORTYPE)OMX_ErrorNoneExpiration; + } + break; + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + if (ret == (OMX_ERRORTYPE)OMX_ErrorNoneExpiration) + ret = OMX_ErrorNone; + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264WFDEnc_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_TEMPORALSVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigVideoTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_AVC_ENABLE_TEMPORALSVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoAVCEnableTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_ROIINFO) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigVideoRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_ENABLE_ROIINFO) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoEnableRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_PVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoEnablePVC; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_ANDROID + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_PREPEND_SPSPPS_TO_IDR) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamPrependSPSPPSToIDR; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_INTRAPERIOD) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigVideoIntraPeriod; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_NEED_CONTIG_MEMORY) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorNeedContigMemory; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_GET_BUFFER_FD) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorGetBufferFD; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_QPRANGE_TYPE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamVideoQPRange; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_QPRANGE_TYPE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoQPRange; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_BLUR_FILTER) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamEnableBlurFilter; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_BLUR_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigBlurInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ROATION_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamRotationInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_ANDROID + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_STORE_METADATA_BUFFER) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamStoreMetaDataBuffer; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_COLOR_ASPECTS_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoColorAspects; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ALLOCATE_NATIVE_HANDLE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamAllocateNativeHandle; + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = OMX_ErrorBadParameter; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264WFDEnc_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((hComponent == NULL) || + (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_H264_WFD_ENC_ROLE); + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_H264WFDEnc_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_H264WFDENC_HANDLE *pMFCH264Handle = &pH264Enc->hMFCH264Handle; + OMX_COLOR_FORMATTYPE eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; + + FunctionIn(); + + if (pInputPort->eMetaDataType != METADATA_TYPE_DISABLED) { + /* metadata buffer */ + pInputPort->bufferProcessType = BUFFER_SHARE; + +#ifdef USE_ANDROID + if ((pInputPort->eMetaDataType == METADATA_TYPE_DATA) && + (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque)) { + pInputPort->eMetaDataType = METADATA_TYPE_GRAPHIC; /* AndoridOpaque means GrallocSource */ + pInputPort->bufferProcessType = BUFFER_COPY; /* will determine a process type after getting a hal format at handle */ + } +#endif + } else { + /* data buffer */ + pInputPort->bufferProcessType = BUFFER_COPY; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pInputPort->portDefinition.format.video.nFrameWidth, + pInputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.format.video.nBitrate, + pInputPort->portDefinition.format.video.xFramerate); + + Exynos_SetPlaneToPort(pInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + Exynos_SetPlaneToPort(pOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pH264Enc->hMFCH264Handle.indexTimestamp = 0; + pH264Enc->hMFCH264Handle.outputIndexTimestamp = 0; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_H264WFDEnc_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle); + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + FunctionIn(); + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + OMX_BOOL bSecureMode = OMX_FALSE; + + ExynosVideoInstInfo *pVideoInstInfo = NULL; + + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || + (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H264_WFD_ENC, componentName) == 0) { + bSecureMode = OMX_FALSE; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H264_WFD_DRM_ENC, componentName) == 0) { + bSecureMode = OMX_TRUE; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit for WFD (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = (bSecureMode == OMX_TRUE)? HW_VIDEO_ENC_SECURE_CODEC:HW_VIDEO_ENC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pH264Enc = Exynos_OSAL_Malloc(sizeof(EXYNOS_H264WFDENC_HANDLE)); + if (pH264Enc == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pH264Enc, 0, sizeof(EXYNOS_H264WFDENC_HANDLE)); + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoEnc->hCodecHandle = (OMX_HANDLETYPE)pH264Enc; + pH264Enc->qpRangeI.nMinQP = 5; + pH264Enc->qpRangeI.nMaxQP = 50; + pH264Enc->qpRangeP.nMinQP = 5; + pH264Enc->qpRangeP.nMaxQP = 50; + pH264Enc->qpRangeB.nMinQP = 5; + pH264Enc->qpRangeB.nMaxQP = 50; + + pVideoEnc->quantization.nQpI = 29; + pVideoEnc->quantization.nQpP = 30; + pVideoEnc->quantization.nQpB = 32; + + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_H264_WFD_DRM_ENC); + else + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_H264_WFD_ENC); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + +#ifdef USE_SINGLE_PLANE_IN_DRM + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + pExynosPort->ePlaneType = PLANE_SINGLE; +#endif + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/avc"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pH264Enc->AVCComponent[i], OMX_VIDEO_PARAM_AVCTYPE); + pH264Enc->AVCComponent[i].nPortIndex = i; + pH264Enc->AVCComponent[i].eProfile = OMX_VIDEO_AVCProfileBaseline; + pH264Enc->AVCComponent[i].eLevel = OMX_VIDEO_AVCLevel31; + + pH264Enc->AVCComponent[i].nPFrames = 29; + pH264Enc->AVCComponent[i].nBFrames = 0; + pH264Enc->AVCComponent[i].nRefFrames = 1; + } + + Exynos_OSAL_Memset(&pH264Enc->TemporalSVC, 0, sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC)); + INIT_SET_SIZE_VERSION(&pH264Enc->TemporalSVC, EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC); + pH264Enc->TemporalSVC.nKeyFrameInterval = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames + 1; + pH264Enc->TemporalSVC.nTemporalLayerCount = 0; + pH264Enc->nMaxTemporalLayerCount = 0; + pH264Enc->hMFCH264Handle.bTemporalSVC = OMX_FALSE; + for (i = 0; i < OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; i++) { + pH264Enc->TemporalSVC.nTemporalLayerBitrateRatio[i] = + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.nBitrate; + } + pH264Enc->TemporalSVC.nMinQuantizer = pH264Enc->qpRangeI.nMinQP; + pH264Enc->TemporalSVC.nMaxQuantizer = pH264Enc->qpRangeI.nMaxQP; + + pH264Enc->hMFCH264Handle.videoInstInfo.bOTFMode = VIDEO_TRUE; + + pOMXComponent->GetParameter = &Exynos_H264WFDEnc_GetParameter; + pOMXComponent->SetParameter = &Exynos_H264WFDEnc_SetParameter; + pOMXComponent->GetConfig = &Exynos_H264WFDEnc_GetConfig; + pOMXComponent->SetConfig = &Exynos_H264WFDEnc_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_H264WFDEnc_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_H264WFDEnc_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_H264WFDEnc_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_H264WFDEnc_Terminate; + + pVideoEnc->exynos_codec_start = &H264WFDCodecStart; + pVideoEnc->exynos_codec_stop = &H264WFDCodecStop; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pVideoEnc->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoEnc->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pH264Enc); + pH264Enc = pVideoEnc->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.videoInstInfo.eCodecType = VIDEO_CODING_AVC; + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + pH264Enc->hMFCH264Handle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pH264Enc->hMFCH264Handle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + if (Exynos_Video_GetInstInfo(&(pH264Enc->hMFCH264Handle.videoInstInfo), VIDEO_FALSE /* enc */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pH264Enc); + pH264Enc = pVideoEnc->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for enc : temporal-svc(%d)/roi(%d)/qp-range(%d)", + pExynosComponent, __FUNCTION__, + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bRoiInfoSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.supportInfo.enc.bQpRangePBSupport)); + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-qp-range", (OMX_INDEXTYPE)OMX_IndexConfigVideoQPRange); +#endif + + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pVideoInstInfo = &(pH264Enc->hMFCH264Handle.videoInstInfo); + + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pInputPort->portDefinition.format.video.xFramerate; + + /* H.264 Codec Open */ + ret = H264WFDCodecOpen(pH264Enc, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_SharedMemory_Close(pVideoEnc->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pH264Enc != NULL) { + H264WFDCodecClose(pH264Enc); + Exynos_OSAL_Free(pH264Enc); + pH264Enc = pVideoEnc->hCodecHandle = NULL; + } + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Port_Constructor(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_BASEPORT *pExynosInputPort = NULL; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = NULL; + int i = 0, j = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x) Line:%d", __FUNCTION__, ret, __LINE__); + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x) Line:%d", __FUNCTION__, ret, __LINE__); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + INIT_SET_SIZE_VERSION(&pExynosComponent->portParam, OMX_PORT_PARAM_TYPE); + pExynosComponent->portParam.nPorts = ALL_PORT_NUM; + pExynosComponent->portParam.nStartPortNumber = INPUT_PORT_INDEX; + + pExynosPort = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BASEPORT) * ALL_PORT_NUM); + if (pExynosPort == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort, 0, sizeof(EXYNOS_OMX_BASEPORT) * ALL_PORT_NUM); + pExynosComponent->pExynosPort = pExynosPort; + + /* Input Port */ + pExynosInputPort = &pExynosPort[INPUT_PORT_INDEX]; + + pExynosInputPort->extendBufferHeader = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + if (pExynosInputPort->extendBufferHeader == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosInputPort->extendBufferHeader, 0, sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + + pExynosInputPort->bufferStateAllocate = Exynos_OSAL_Malloc(sizeof(OMX_U32) * MAX_BUFFER_NUM); + if (pExynosInputPort->bufferStateAllocate == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosInputPort->bufferStateAllocate, 0, sizeof(OMX_U32) * MAX_BUFFER_NUM); + + pExynosInputPort->bufferSemID = NULL; + pExynosInputPort->assignedBufferNum = 0; + pExynosInputPort->portState = EXYNOS_OMX_PortStateLoaded; + pExynosInputPort->tunneledComponent = NULL; + pExynosInputPort->tunneledPort = 0; + pExynosInputPort->tunnelBufferNum = 0; + pExynosInputPort->bufferSupplier = OMX_BufferSupplyUnspecified; + pExynosInputPort->tunnelFlags = 0; + pExynosInputPort->supportFormat = NULL; + pExynosInputPort->bNeedContigMem = OMX_FALSE; + pExynosInputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + + INIT_SET_SIZE_VERSION(&pExynosInputPort->portDefinition, OMX_PARAM_PORTDEFINITIONTYPE); + pExynosInputPort->portDefinition.nPortIndex = INPUT_PORT_INDEX; + pExynosInputPort->portDefinition.eDir = OMX_DirInput; + pExynosInputPort->portDefinition.nBufferCountActual = 0; + pExynosInputPort->portDefinition.nBufferCountMin = 0; + pExynosInputPort->portDefinition.nBufferSize = 0; + pExynosInputPort->portDefinition.bEnabled = OMX_FALSE; + pExynosInputPort->portDefinition.bPopulated = OMX_FALSE; + pExynosInputPort->portDefinition.eDomain = OMX_PortDomainMax; + pExynosInputPort->portDefinition.bBuffersContiguous = OMX_FALSE; + pExynosInputPort->portDefinition.nBufferAlignment = 0; + + /* Output Port */ + pExynosOutputPort = &pExynosPort[OUTPUT_PORT_INDEX]; + + pExynosOutputPort->extendBufferHeader = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + if (pExynosOutputPort->extendBufferHeader == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosOutputPort->extendBufferHeader, 0, sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + + pExynosOutputPort->bufferStateAllocate = Exynos_OSAL_Malloc(sizeof(OMX_U32) * MAX_BUFFER_NUM); + if (pExynosOutputPort->bufferStateAllocate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosOutputPort->bufferStateAllocate, 0, sizeof(OMX_U32) * MAX_BUFFER_NUM); + + pExynosOutputPort->bufferSemID = NULL; + pExynosOutputPort->assignedBufferNum = 0; + pExynosOutputPort->portState = EXYNOS_OMX_PortStateLoaded; + pExynosOutputPort->tunneledComponent = NULL; + pExynosOutputPort->tunneledPort = 0; + pExynosOutputPort->tunnelBufferNum = 0; + pExynosOutputPort->bufferSupplier = OMX_BufferSupplyUnspecified; + pExynosOutputPort->tunnelFlags = 0; + pExynosOutputPort->supportFormat = NULL; + pExynosOutputPort->bNeedContigMem = OMX_FALSE; + pExynosOutputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + + INIT_SET_SIZE_VERSION(&pExynosOutputPort->portDefinition, OMX_PARAM_PORTDEFINITIONTYPE); + pExynosOutputPort->portDefinition.nPortIndex = OUTPUT_PORT_INDEX; + pExynosOutputPort->portDefinition.eDir = OMX_DirOutput; + pExynosOutputPort->portDefinition.nBufferCountActual = 0; + pExynosOutputPort->portDefinition.nBufferCountMin = 0; + pExynosOutputPort->portDefinition.nBufferSize = 0; + pExynosOutputPort->portDefinition.bEnabled = OMX_FALSE; + pExynosOutputPort->portDefinition.bPopulated = OMX_FALSE; + pExynosOutputPort->portDefinition.eDomain = OMX_PortDomainMax; + pExynosOutputPort->portDefinition.bBuffersContiguous = OMX_FALSE; + pExynosOutputPort->portDefinition.nBufferAlignment = 0; + + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.startTimeStamp = 0; + pExynosComponent->checkTimeStamp.nStartFlags = 0x0; + + pOMXComponent->EmptyThisBuffer = &Exynos_OMX_EmptyThisBuffer; + pOMXComponent->FillThisBuffer = &Exynos_OMX_FillThisBuffer; + + ret = OMX_ErrorNone; + +EXIT: + if ((ret != OMX_ErrorNone) && + (pExynosComponent != NULL) && + (pExynosComponent->pExynosPort != NULL)) { + for (i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + Exynos_OSAL_Free(pExynosPort->bufferStateAllocate); + pExynosPort->bufferStateAllocate = NULL; + Exynos_OSAL_Free(pExynosPort->extendBufferHeader); + pExynosPort->extendBufferHeader = NULL; + } + + Exynos_OSAL_Free(pExynosComponent->pExynosPort); + pExynosComponent->pExynosPort = NULL; + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Port_Destructor(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + int i = 0, j = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + for (i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + Exynos_OSAL_Free(pExynosPort->bufferStateAllocate); + pExynosPort->bufferStateAllocate = NULL; + Exynos_OSAL_Free(pExynosPort->extendBufferHeader); + pExynosPort->extendBufferHeader = NULL; + } + + Exynos_OSAL_Free(pExynosComponent->pExynosPort); + pExynosComponent->pExynosPort = NULL; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_InputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE* bufferHeader) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 i = 0; + + pExynosComponent->pCallbacks->EmptyBufferDone(pOMXComponent, + pExynosComponent->callbackData, + bufferHeader); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader: %p", pExynosComponent, __FUNCTION__, bufferHeader); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (bufferHeader == inputBufArray[i].pBuffer) { + inputBufArray[i].bInOMX = OMX_FALSE; + break; + } + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_OutputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE* bufferHeader) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 i = 0; + + pExynosComponent->pCallbacks->FillBufferDone(pOMXComponent, + pExynosComponent->callbackData, + bufferHeader); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader: %p", pExynosComponent, __FUNCTION__, bufferHeader); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (bufferHeader == outputBufArray[i].pBuffer) { + outputBufArray[i].bInOMX = OMX_FALSE; + break; + } + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferFlushProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex, + OMX_BOOL bEvent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + cnt = (nPortIndex == ALL_PORT_INDEX) ? ALL_PORT_NUM : 1; + for (i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Flush %s Port", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + + ret = pExynosComponent->exynos_BufferFlush(pOMXComponent, nIndex, bEvent); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port is flushed", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + if (ret == OMX_ErrorNone) { + pExynosComponent->pExynosPort[nIndex].portState = EXYNOS_OMX_PortStateIdle; + + if (bEvent == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(EventCmdComplete/Flush/%s port)", + pExynosComponent, __FUNCTION__, (nIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandFlush, nIndex, NULL); + } + } + } + +EXIT: + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + if ((pOMXComponent != NULL) && + (pExynosComponent != NULL)) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_EnablePort( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + OMX_U32 i = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_PortEnableProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + cnt = (nPortIndex == ALL_PORT_INDEX) ? ALL_PORT_NUM : 1; + for (i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + } + +EXIT: + if ((ret != OMX_ErrorNone) && + (pOMXComponent != NULL) && + (pExynosComponent != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_DisablePort( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + pExynosPort->portDefinition.bEnabled = OMX_FALSE; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_PortDisableProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + cnt = (nPortIndex == ALL_PORT_INDEX ) ? ALL_PORT_NUM : 1; + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + /* port flush*/ + for(i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Before disabling %s port, do flush", + pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosComponent->pExynosPort[nIndex].portState = EXYNOS_OMX_PortStateFlushingForDisable; + ret = pExynosComponent->exynos_BufferFlush(pOMXComponent, nIndex, OMX_FALSE); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s Port is flushed", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + if (ret != OMX_ErrorNone) + goto EXIT; + } + } + + for(i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Disable %s Port", + pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosComponent->pExynosPort[nIndex].portState = EXYNOS_OMX_PortStateDisabling; + ret = Exynos_OMX_DisablePort(pOMXComponent, nIndex); + } + +EXIT: + if ((ret != OMX_ErrorNone) && + (pOMXComponent != NULL) && + (pExynosComponent != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + + FunctionOut(); + + return ret; +} + +/* Change CHECK_SIZE_VERSION Macro */ +OMX_ERRORTYPE Exynos_OMX_Check_SizeVersion(OMX_PTR header, OMX_U32 size) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_VERSIONTYPE *version = NULL; + + if (header == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + version = (OMX_VERSIONTYPE*)((char*)header + sizeof(OMX_U32)); + if (*((OMX_U32*)header) != size) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_FUNC_TRACE, "[%s] nVersionMajor:%d, nVersionMinor:%d", __FUNCTION__, version->s.nVersionMajor, version->s.nVersionMinor); + + if ((version->s.nVersionMajor != VERSIONMAJOR_NUMBER) || + (version->s.nVersionMinor > VERSIONMINOR_NUMBER)) { + ret = OMX_ErrorVersionMismatch; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + return ret; +} + +int Exynos_GetPlaneFromPort(EXYNOS_OMX_BASEPORT *pPort) +{ + int ret = 0; + + if (pPort == NULL) + goto EXIT; + + ret = pPort->processData.buffer.nPlanes; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_SetPlaneToPort(EXYNOS_OMX_BASEPORT *pPort, int nPlaneNum) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pPort == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pPort->processData.buffer.nPlanes = nPlaneNum; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_EmptyThisBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + unsigned int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->pExynosPort == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pBuffer->nInputPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StateExecuting) && + (pExynosComponent->currentState != OMX_StatePause)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (inputBufArray[i].bInOMX == OMX_FALSE) { + inputBufArray[i].pBuffer = pBuffer; + inputBufArray[i].bInOMX = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] pBuffer[%d]: %p", + pExynosComponent, __FUNCTION__, i, pBuffer); + break; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FillThisBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + unsigned int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->pExynosPort == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pBuffer->nOutputPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StateExecuting) && + (pExynosComponent->currentState != OMX_StatePause)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (outputBufArray[i].bInOMX == OMX_FALSE) { + outputBufArray[i].pBuffer = pBuffer; + outputBufArray[i].bInOMX = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] pBuffer[%d]: %p", + pExynosComponent, __FUNCTION__, i, pBuffer); + break; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetComponentVersion( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STRING pComponentName, + OMX_OUT OMX_VERSIONTYPE *pComponentVersion, + OMX_OUT OMX_VERSIONTYPE *pSpecVersion, + OMX_OUT OMX_UUIDTYPE *pComponentUUID) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + unsigned long compUUID[3]; + + FunctionIn(); + + /* check parameters */ + if (hComponent == NULL || + pComponentName == NULL || pComponentVersion == NULL || + pSpecVersion == NULL || pComponentUUID == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Strcpy(pComponentName, pExynosComponent->componentName); + Exynos_OSAL_Memcpy(pComponentVersion, &(pExynosComponent->componentVersion), sizeof(OMX_VERSIONTYPE)); + Exynos_OSAL_Memcpy(pSpecVersion, &(pExynosComponent->specVersion), sizeof(OMX_VERSIONTYPE)); + + /* Fill UUID with handle address, PID and UID. + * This should guarantee uiniqness */ + compUUID[0] = (unsigned long)pOMXComponent; + compUUID[1] = (unsigned long)getpid(); + compUUID[2] = (unsigned long)getuid(); + Exynos_OSAL_Memcpy(*pComponentUUID, compUUID, 3 * sizeof(*compUUID)); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetState( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STATETYPE *pState) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pState == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + *pState = pExynosComponent->currentState; + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SetPortFlush(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nPortIndex = nParam; + unsigned int i; + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + if ((nPortIndex != ALL_PORT_INDEX) && + ((OMX_S32)nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateFlushing; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateFlushing; + } + } else { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_SetPortDisable(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nPortIndex = nParam; + unsigned int i; + + FunctionIn(); + + if ((nPortIndex != ALL_PORT_INDEX) && + ((OMX_S32)nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex != ALL_PORT_INDEX) && + ((OMX_S32)nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateDisabling; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateDisabling; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SetPortEnable(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nPortIndex = nParam; + + OMX_U16 i = 0; + + FunctionIn(); + + if ((nPortIndex != ALL_PORT_INDEX) && + ((OMX_S32)nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; + +} + +static OMX_ERRORTYPE Exynos_SetStateSet( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + OMX_U32 i = 0; + + FunctionIn(); + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + switch ((OMX_STATETYPE)nParam) { + case OMX_StateIdle: + { + /* Loaded to Idle */ + if (pExynosComponent->currentState == OMX_StateLoaded) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateLoadedToIdle; + + for(i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateEnabling; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateLoaded to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + /* Executing to Idle */ + if (pExynosComponent->currentState == OMX_StateExecuting) { + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + pExynosComponent->transientState = EXYNOS_OMX_TransStateExecutingToIdle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateExecuting to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + /* Pause to Idle */ + if (pExynosComponent->currentState == OMX_StatePause) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StatePause to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_StateExecuting: + { + /* Idle to Executing */ + if (pExynosComponent->currentState == OMX_StateIdle) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateIdleToExecuting; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateExecuting", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + /* Pause to Executing */ + if (pExynosComponent->currentState == OMX_StatePause) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StatePause to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = OMX_ErrorBadParameter; + } + break; + case OMX_StateLoaded: + { + /* Idle to Loaded */ + if (pExynosComponent->currentState == OMX_StateIdle) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateIdleToLoaded; + + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateDisabling; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateLoaded", pExynosComponent, __FUNCTION__); + } + } + break; + case OMX_StateInvalid: + { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateInvalid; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, stateString(pExynosComponent->currentState)); + } + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s to %s", pExynosComponent, __FUNCTION__, + stateString(pExynosComponent->currentState), stateString(nParam)); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_StateSet(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_U32 destState = nParam; + OMX_U32 i = 0; + + if ((destState == OMX_StateIdle) && (pExynosComponent->currentState == OMX_StateLoaded)) { + for(i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateEnabling; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateLoaded to OMX_StateIdle", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateLoaded) && (pExynosComponent->currentState == OMX_StateIdle)) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateDisabling; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateLoaded", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateIdle) && (pExynosComponent->currentState == OMX_StateExecuting)) { + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateExecuting to OMX_StateIdle", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateIdle) && (pExynosComponent->currentState == OMX_StatePause)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StatePause to OMX_StateIdle", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateExecuting) && (pExynosComponent->currentState == OMX_StateIdle)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateExecuting", pExynosComponent, __FUNCTION__); + } else if (destState == OMX_StateInvalid) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateInvalid; + } + } + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentStateSet(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + OMX_STATETYPE destState = nParam; + OMX_STATETYPE currentState = pExynosComponent->currentState; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264WFDENC_HANDLE *pH264Enc = (EXYNOS_H264WFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoGeometry bufferConf; + + unsigned int i = 0, j = 0; + int k = 0; + int nOutBufSize = 0, nOutputBufferCnt = 0; + + FunctionIn(); + + /* check parameters */ + if (currentState == destState) { + ret = OMX_ErrorSameState; + goto EXIT; + } + if (currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] current:(%s) dest:(%s)", pExynosComponent, __FUNCTION__, stateString(currentState), stateString(destState)); + switch (destState) { + case OMX_StateInvalid: + switch (currentState) { + case OMX_StateWaitForResources: + case OMX_StateIdle: + case OMX_StateExecuting: + case OMX_StatePause: + case OMX_StateLoaded: + pExynosComponent->currentState = OMX_StateInvalid; + + if (currentState != OMX_StateLoaded) + pExynosComponent->exynos_codec_componentTerminate(pOMXComponent); + + ret = OMX_ErrorInvalidState; + break; + default: + ret = OMX_ErrorInvalidState; + break; + } + break; + case OMX_StateLoaded: + switch (currentState) { + case OMX_StateIdle: + for(i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateDisabling; + + ret = pExynosComponent->exynos_codec_componentTerminate(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + else + goto NO_EVENT_EXIT; + + break; + case OMX_StateWaitForResources: + pExynosComponent->currentState = OMX_StateLoaded; + break; + case OMX_StateExecuting: + case OMX_StatePause: + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StateIdle: + switch (currentState) { + case OMX_StateLoaded: + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &(pExynosComponent->pExynosPort[i]); + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + } + + Exynos_OSAL_Get_Log_Property(); // For debuging, Function called when GetHandle function is success + ret = pExynosComponent->exynos_codec_componentInit(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + else + goto NO_EVENT_EXIT; + + break; + case OMX_StateExecuting: + Exynos_SetPortFlush(pExynosComponent, ALL_PORT_INDEX); + Exynos_OMX_BufferFlushProcess(pOMXComponent, ALL_PORT_INDEX, OMX_FALSE); + pExynosComponent->currentState = OMX_StateIdle; + break; + case OMX_StatePause: + Exynos_SetPortFlush(pExynosComponent, ALL_PORT_INDEX); + Exynos_OMX_BufferFlushProcess(pOMXComponent, ALL_PORT_INDEX, OMX_FALSE); + pExynosComponent->currentState = OMX_StateIdle; + break; + case OMX_StateWaitForResources: + pExynosComponent->currentState = OMX_StateIdle; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StateExecuting: + switch (currentState) { + case OMX_StateLoaded: + ret = OMX_ErrorIncorrectStateTransition; + break; + case OMX_StateIdle: + pExynosComponent->currentState = OMX_StateExecuting; + + /* Set EncParam for input (src) */ + Set_H264WFDEnc_Param(pExynosComponent); + pEncParam = &(pH264Enc->hMFCH264Handle.encParam); + if (pEncOps->Set_EncParam) { + if(pEncOps->Set_EncParam(pH264Enc->hMFCH264Handle.hMFCHandle, pEncParam) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set encParam", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + Print_H264WFDEnc_Param(pEncParam); + + /* set geometry for output (dst) */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + nOutBufSize = pExynosPort->portDefinition.nBufferSize; + if ((pExynosPort->bufferProcessType & BUFFER_COPY) || + (pExynosPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nOutBufSize = ALIGN(pExynosPort->portDefinition.format.video.nFrameWidth * + pExynosPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nOutBufSize = Exynos_OSAL_GetOutBufferSize(pExynosPort->portDefinition.format.video.nFrameWidth, + pExynosPort->portDefinition.format.video.nFrameHeight, + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.nBufferSize); +#endif + + } + if (pOutbufOps->Set_Geometry) { + /* output buffer info: only 2 config values needed */ + bufferConf.eCompressionFormat = VIDEO_CODING_AVC; + bufferConf.nSizeImage = nOutBufSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosPort); + + if (pOutbufOps->Set_Geometry(pH264Enc->hMFCH264Handle.hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + break; + case OMX_StatePause: + pExynosComponent->currentState = OMX_StateExecuting; + break; + case OMX_StateWaitForResources: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StatePause: + switch (currentState) { + case OMX_StateLoaded: + ret = OMX_ErrorIncorrectStateTransition; + break; + case OMX_StateIdle: + pExynosComponent->currentState = OMX_StatePause; + break; + case OMX_StateExecuting: + pExynosComponent->currentState = OMX_StatePause; + break; + case OMX_StateWaitForResources: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StateWaitForResources: + switch (currentState) { + case OMX_StateLoaded: + pExynosComponent->currentState = OMX_StateWaitForResources; + break; + case OMX_StateIdle: + case OMX_StateExecuting: + case OMX_StatePause: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + if (pExynosComponent->pCallbacks != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, OMX_CommandStateSet, + destState, NULL); + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + if (pExynosComponent->pCallbacks != NULL) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +NO_EVENT_EXIT: /* postpone to send event */ + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SendCommand( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_COMMANDTYPE Cmd, + OMX_IN OMX_U32 nParam, + OMX_IN OMX_PTR pCmdData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (Cmd) { + case OMX_CommandStateSet : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandStateSet", pExynosComponent, __FUNCTION__); + ret = Exynos_StateSet(pExynosComponent, nParam); + if (ret == OMX_ErrorNone) + Exynos_SetStateSet(pExynosComponent, nParam); + ret = Exynos_OMX_ComponentStateSet(pOMXComponent, nParam); + break; + case OMX_CommandFlush : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandFlush", pExynosComponent, __FUNCTION__); + ret = Exynos_SetPortFlush(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + ret = Exynos_OMX_BufferFlushProcess(pOMXComponent, nParam, OMX_TRUE); + break; + case OMX_CommandPortDisable : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandPortDisable", pExynosComponent, __FUNCTION__); + ret = Exynos_SetPortDisable(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + ret = Exynos_OMX_PortDisableProcess(pOMXComponent, nParam); + break; + case OMX_CommandPortEnable : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandPortEnable", pExynosComponent, __FUNCTION__); + ret = Exynos_SetPortEnable(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + ret = Exynos_OMX_PortEnableProcess(pOMXComponent, nParam); + break; + default: + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SetCallbacks( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_CALLBACKTYPE* pCallbacks, + OMX_IN OMX_PTR pAppData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pCallbacks == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + if (pExynosComponent->currentState != OMX_StateLoaded) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosComponent->pCallbacks = pCallbacks; + pExynosComponent->callbackData = pAppData; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Constructor( + OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] lib version is %s", __FUNCTION__, IS_64BIT_OS? "64bit":"32bit"); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x)", __FUNCTION__, ret); + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BASECOMPONENT)); + if (pExynosComponent == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Malloc (0x%x)", __FUNCTION__, ret); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent, 0, sizeof(EXYNOS_OMX_BASECOMPONENT)); + pOMXComponent->pComponentPrivate = (OMX_PTR)pExynosComponent; + + pOMXComponent->GetComponentVersion = &Exynos_OMX_GetComponentVersion; + pOMXComponent->SendCommand = &Exynos_OMX_SendCommand; + pOMXComponent->GetState = &Exynos_OMX_GetState; + pOMXComponent->SetCallbacks = &Exynos_OMX_SetCallbacks; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Destructor( + OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + Exynos_OSAL_Free(pExynosComponent); + pExynosComponent = NULL; + + ret = OMX_ErrorNone; +EXIT: + FunctionOut(); + + return ret; +} + +void Exynos_UpdateFrameSize(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + exynosInputPort->portDefinition.nBufferSize = ALIGN(exynosInputPort->portDefinition.format.video.nFrameWidth, 16) * + ALIGN(exynosInputPort->portDefinition.format.video.nFrameHeight, 16) * 3 / 2; + + if ((exynosOutputPort->portDefinition.format.video.nFrameWidth != + exynosInputPort->portDefinition.format.video.nFrameWidth) || + (exynosOutputPort->portDefinition.format.video.nFrameHeight != + exynosInputPort->portDefinition.format.video.nFrameHeight)) { + OMX_U32 width = 0, height = 0; + + exynosOutputPort->portDefinition.format.video.nFrameWidth = + exynosInputPort->portDefinition.format.video.nFrameWidth; + exynosOutputPort->portDefinition.format.video.nFrameHeight = + exynosInputPort->portDefinition.format.video.nFrameHeight; + width = exynosOutputPort->portDefinition.format.video.nStride = + exynosInputPort->portDefinition.format.video.nStride; + height = exynosOutputPort->portDefinition.format.video.nSliceHeight = + exynosInputPort->portDefinition.format.video.nSliceHeight; + + if (width && height) + exynosOutputPort->portDefinition.nBufferSize = ALIGN((ALIGN(width, 16) * ALIGN(height, 16) * 3) / 2, 512); + } + + return; +} + +void Exynos_Input_SetSupportFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_COLOR_FORMATTYPE ret = OMX_COLOR_FormatUnused; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if ((pVideoEnc == NULL) || (pInputPort == NULL)) + return ; + + if (pInputPort->supportFormat != NULL) { + OMX_BOOL ret = OMX_FALSE; + int nLastIndex = INPUT_PORT_SUPPORTFORMAT_DEFAULT_NUM; + int i; + + /* default supported formats */ + pInputPort->supportFormat[0] = OMX_COLOR_FormatYUV420Planar; + pInputPort->supportFormat[1] = OMX_COLOR_FormatYUV420SemiPlanar; + pInputPort->supportFormat[2] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV21Linear; + pInputPort->supportFormat[3] = OMX_COLOR_Format32bitARGB8888; + pInputPort->supportFormat[4] = (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888; +#ifdef USE_ANDROID + pInputPort->supportFormat[nLastIndex++] = OMX_COLOR_FormatAndroidOpaque; +#endif + + /* add extra formats, if It is supported by H/W. (CSC doesn't exist) */ + /* OMX_SEC_COLOR_FormatNV12Tiled */ + ret = pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled); + if (ret == OMX_TRUE) + pInputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled; + + /* OMX_SEC_COLOR_FormatYVU420Planar */ + ret = pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420Planar); + if (ret == OMX_TRUE) + pInputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420Planar; + + /* OMX_COLOR_Format32bitBGRA8888 */ + ret = pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, OMX_COLOR_Format32bitBGRA8888); + if (ret == OMX_TRUE) + pInputPort->supportFormat[nLastIndex++] = OMX_COLOR_Format32bitBGRA8888; + + for (i = 0; i < nLastIndex; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] Supported Format[%d] : 0x%x", + pExynosComponent, __FUNCTION__, i, pInputPort->supportFormat[i]); + } + + pInputPort->supportFormat[nLastIndex] = OMX_COLOR_FormatUnused; + } + + return ; +} + +OMX_COLOR_FORMATTYPE Exynos_Input_GetActualColorFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_COLOR_FORMATTYPE ret = OMX_COLOR_FormatUnused; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; + +#ifdef USE_ANDROID + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) + eColorFormat = pVideoEnc->surfaceFormat; +#endif + + if (pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, eColorFormat) == OMX_TRUE) { + ret = eColorFormat; + goto EXIT; + } + + switch ((int)eColorFormat) { + case OMX_COLOR_FormatYUV420SemiPlanar: + case OMX_COLOR_FormatYUV420Planar: /* converted to NV12 using CSC */ + case OMX_COLOR_Format32bitARGB8888: /* converted to NV12 using CSC */ + case OMX_COLOR_Format32BitRGBA8888: /* converted to NV12 using CSC */ + ret = OMX_COLOR_FormatYUV420SemiPlanar; + break; + case OMX_SEC_COLOR_FormatNV21Linear: + case OMX_SEC_COLOR_FormatNV12Tiled: + ret = eColorFormat; + break; + default: + ret = OMX_COLOR_FormatUnused; + break; + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_ResetAllPortConfig(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + /* Input port */ + pInputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pInputPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pInputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pInputPort->portDefinition.format.video.nSliceHeight = 0; + pInputPort->portDefinition.format.video.pNativeRender = 0; + pInputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pInputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + + pInputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + pInputPort->portDefinition.bEnabled = OMX_TRUE; + + pInputPort->bufferProcessType = BUFFER_COPY; + pInputPort->portWayType = WAY2_PORT; + Exynos_SetPlaneToPort(pInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + + /* Output port */ + pOutputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pOutputPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pOutputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pOutputPort->portDefinition.format.video.nSliceHeight = 0; + pOutputPort->portDefinition.format.video.pNativeRender = 0; + pOutputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pOutputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + + pOutputPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM; + pOutputPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM; + pOutputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pOutputPort->portDefinition.bEnabled = OMX_TRUE; + + pOutputPort->bufferProcessType = BUFFER_SHARE; + pOutputPort->portWayType = WAY2_PORT; + pOutputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(OMX_COLOR_FormatYUV420Planar, pOutputPort->ePlaneType)); + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = Exynos_OMX_BaseComponent_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to construct BaseComponent for WFD", __FUNCTION__); + goto EXIT; + } + + ret = Exynos_OMX_Port_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Port_Constructor", __FUNCTION__); + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pVideoEnc = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_VIDEOENC_COMPONENT)); + if (pVideoEnc == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_Port_Destructor(pOMXComponent); + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Memset(pVideoEnc, 0, sizeof(EXYNOS_OMX_VIDEOENC_COMPONENT)); + pExynosComponent->hComponentHandle = (OMX_HANDLETYPE)pVideoEnc; + + pVideoEnc->nQosRatio = 0; + pVideoEnc->quantization.nQpI = 4; // I frame quantization parameter + pVideoEnc->quantization.nQpP = 5; // P frame quantization parameter + pVideoEnc->quantization.nQpB = 5; // B frame quantization parameter + + pVideoEnc->bUseBlurFilter = OMX_FALSE; + pVideoEnc->eBlurMode = BLUR_MODE_NONE; + pVideoEnc->eBlurResol = BLUR_RESOL_240; + + pVideoEnc->eRotationType = ROTATE_0; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->supportFormat = Exynos_OSAL_Malloc(sizeof(OMX_COLOR_FORMATTYPE) * INPUT_PORT_SUPPORTFORMAT_NUM_MAX); + if (pExynosPort->supportFormat == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort->supportFormat, 0, (sizeof(OMX_COLOR_FORMATTYPE) * INPUT_PORT_SUPPORTFORMAT_NUM_MAX)); + + pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MAX_VIDEO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = 0; + pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo; + + pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + if (pExynosPort->portDefinition.format.video.cMIMEType == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + + pExynosPort->portDefinition.format.video.nFrameWidth = 0; + pExynosPort->portDefinition.format.video.nFrameHeight= 0; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.format.video.nBitrate = 1000000; + pExynosPort->portDefinition.format.video.xFramerate = (15 << 16); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pVideoEnc->eControlRate[INPUT_PORT_INDEX] = OMX_Video_ControlRateVariable; + + pExynosPort->eMetaDataType = METADATA_TYPE_DISABLED; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->supportFormat = Exynos_OSAL_Malloc(sizeof(OMX_COLOR_FORMATTYPE) * OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX); + if (pExynosPort->supportFormat == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort->supportFormat, 0, (sizeof(OMX_COLOR_FORMATTYPE) * OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX)); + + pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo; + + pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + if (pExynosPort->portDefinition.format.video.cMIMEType == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + + pExynosPort->portDefinition.format.video.nFrameWidth = 0; + pExynosPort->portDefinition.format.video.nFrameHeight= 0; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.format.video.nBitrate = 1000000; + pExynosPort->portDefinition.format.video.xFramerate = (15 << 16); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] = OMX_Video_ControlRateVariable; + + pExynosPort->eMetaDataType = METADATA_TYPE_DISABLED; + + pOMXComponent->UseBuffer = &Exynos_OMX_UseBuffer; + pOMXComponent->AllocateBuffer = &Exynos_OMX_AllocateBuffer; + pOMXComponent->FreeBuffer = &Exynos_OMX_FreeBuffer; + + pExynosComponent->exynos_BufferFlush = &Exynos_OMX_BufferFlush; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + + int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Free(pVideoEnc); + pExynosComponent->hComponentHandle = pVideoEnc = NULL; + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + if (pExynosPort->processData.extInfo != NULL) { + Exynos_OSAL_Free(pExynosPort->processData.extInfo); + pExynosPort->processData.extInfo = NULL; + } + + for(i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + Exynos_OSAL_Free(pExynosPort->portDefinition.format.video.cMIMEType); + pExynosPort->portDefinition.format.video.cMIMEType = NULL; + + Exynos_OSAL_Free(pExynosPort->supportFormat); + pExynosPort->supportFormat = NULL; + } + + ret = Exynos_OMX_Port_Destructor(pOMXComponent); + + ret = Exynos_OMX_BaseComponent_Destructor(hComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pTempBufferHdr = NULL; + OMX_U8 *pTempBuffer = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (pExynosPort->portState != EXYNOS_OMX_PortStateEnabling) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pTempBuffer = (OMX_U8 *)Exynos_OSAL_Malloc(64); + if (pTempBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pTempBuffer, 0, 64); + + pTempBufferHdr = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (pTempBufferHdr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pTempBufferHdr, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = pTempBufferHdr; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ALLOCATED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(pTempBufferHdr, OMX_BUFFERHEADERTYPE); + + pTempBufferHdr->pBuffer = pTempBuffer; + pTempBufferHdr->nAllocLen = nSizeBytes; + pTempBufferHdr->pAppPrivate = pAppPrivate; + + if (nPortIndex == INPUT_PORT_INDEX) + pTempBufferHdr->nInputPortIndex = INPUT_PORT_INDEX; + else + pTempBufferHdr->nOutputPortIndex = OUTPUT_PORT_INDEX; + + pExynosPort->assignedBufferNum++; + + *ppBufferHdr = pTempBufferHdr; + + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + + if ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle)) { + if (CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, OMX_CommandStateSet, + OMX_StateIdle, NULL); + + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateIdle; + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateIdle; + } + } else if(!(CHECK_PORT_ENABLED(pExynosPort)) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + pExynosPort->portState = EXYNOS_OMX_PortStateIdle; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Enable %s Port", pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + ret = Exynos_OMX_EnablePort(pOMXComponent, nPortIndex); + + if ((ret == OMX_ErrorNone) && (pExynosComponent->pCallbacks != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(Enable/%s port)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX) ? "input" : "output"); + + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortEnable, + (nPortIndex == INPUT_PORT_INDEX) ? INPUT_PORT_INDEX : OUTPUT_PORT_INDEX, + NULL); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(EventCmdComplete/Enable/%s port)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + + } + } + } + + ret = OMX_ErrorNone; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p), size(%d)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + (*ppBufferHdr), nSizeBytes); + goto EXIT; + } + } + + ret = OMX_ErrorInsufficientResources; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pTempBufferHdr != NULL) + Exynos_OSAL_Free(pTempBufferHdr); + + if (pTempBuffer != NULL) + Exynos_OSAL_Free(pTempBuffer); + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pTempBufferHdr = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (pExynosPort->portState != EXYNOS_OMX_PortStateEnabling) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pTempBufferHdr = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (pTempBufferHdr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pTempBufferHdr, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = pTempBufferHdr; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ASSIGNED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(pTempBufferHdr, OMX_BUFFERHEADERTYPE); + + pTempBufferHdr->pBuffer = pBuffer; + pTempBufferHdr->nAllocLen = nSizeBytes; + pTempBufferHdr->pAppPrivate = pAppPrivate; + + if (nPortIndex == INPUT_PORT_INDEX) + pTempBufferHdr->nInputPortIndex = INPUT_PORT_INDEX; + else + pTempBufferHdr->nOutputPortIndex = OUTPUT_PORT_INDEX; + + pExynosPort->assignedBufferNum++; + + *ppBufferHdr = pTempBufferHdr; + + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + + if ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle)) { + if (CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, OMX_CommandStateSet, + OMX_StateIdle, NULL); + + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateIdle; + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateIdle; + } + } else if(!(CHECK_PORT_ENABLED(pExynosPort)) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + pExynosPort->portState = EXYNOS_OMX_PortStateIdle; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Enable %s Port", pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + ret = Exynos_OMX_EnablePort(pOMXComponent, nPortIndex); + + if ((ret == OMX_ErrorNone) && (pExynosComponent->pCallbacks != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(Enable/%s port)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX) ? "input" : "output"); + + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortEnable, + (nPortIndex == INPUT_PORT_INDEX) ? INPUT_PORT_INDEX : OUTPUT_PORT_INDEX, + NULL); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(EventCmdComplete/Enable/%s port)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + + } + } + } + + ret = OMX_ErrorNone; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p), size(%d)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + (*ppBufferHdr), nSizeBytes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pTempBufferHdr); + ret = OMX_ErrorInsufficientResources; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pOMXBufferHdr = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosPort->portState != EXYNOS_OMX_PortStateDisabling) && + (pExynosPort->portState != EXYNOS_OMX_PortStateFlushingForDisable) && + (pExynosPort->portState != EXYNOS_OMX_PortStateInvalid)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + + (*(pExynosComponent->pCallbacks->EventHandler)) (pOMXComponent, + pExynosComponent->callbackData, + (OMX_U32)OMX_EventError, + (OMX_U32)OMX_ErrorPortUnpopulated, + nPortIndex, NULL); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + for (i = 0; i < /*pExynosPort->portDefinition.nBufferCountActual*/MAX_BUFFER_NUM; i++) { + if ((pExynosPort->bufferStateAllocate[i] != BUFFER_STATE_FREE) && + (pExynosPort->extendBufferHeader[i].OMXBufferHeader != NULL)) { + pOMXBufferHdr = pExynosPort->extendBufferHeader[i].OMXBufferHeader; + + if (pOMXBufferHdr->pBuffer == pBufferHdr->pBuffer) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pOMXBufferHdr); + if (pExynosPort->bufferStateAllocate[i] & BUFFER_STATE_ALLOCATED) { + pOMXBufferHdr->pBuffer = NULL; + pBufferHdr->pBuffer = NULL; + } + + pExynosPort->assignedBufferNum--; + + if (pExynosPort->bufferStateAllocate[i] & HEADER_STATE_ALLOCATED) { + Exynos_OSAL_Free(pOMXBufferHdr); + pExynosPort->extendBufferHeader[i].OMXBufferHeader = NULL; + pBufferHdr = NULL; + } + + pExynosPort->bufferStateAllocate[i] = BUFFER_STATE_FREE; + ret = OMX_ErrorNone; + goto EXIT; + } + } + } + +EXIT: + if (ret == OMX_ErrorNone) { + if (pExynosPort->assignedBufferNum < (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) + pExynosPort->portDefinition.bPopulated = OMX_FALSE; + + if (pExynosPort->assignedBufferNum == 0) { + if ((pExynosComponent->currentState == OMX_StateIdle) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateIdleToLoaded)) { + if (!CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + !CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, OMX_CommandStateSet, + OMX_StateLoaded, NULL); + + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateLoaded; + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateLoaded; + } + } + + if (pExynosPort->portState == EXYNOS_OMX_PortStateDisabling) { + if (!CHECK_PORT_ENABLED(pExynosPort)) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortDisable, nPortIndex, NULL); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s]send event(EventCmdComplete/Disable/%s port)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + + pExynosPort->portState = EXYNOS_OMX_PortStateLoaded; + } + } + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FlushPort( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *pBufferHdr = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + unsigned int i = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if ((nPortIndex < 0) || + (nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (nPortIndex == INPUT_PORT_INDEX) { + if (inputBufArray[i].bInOMX == OMX_TRUE) { + if (inputBufArray[i].pBuffer != NULL) { + pBufferHdr = inputBufArray[i].pBuffer; + pBufferHdr->nFilledLen = 0; + Exynos_OMX_InputBufferReturn(pOMXComponent, pBufferHdr); + } + } + } else { + if (outputBufArray[i].bInOMX == OMX_TRUE) { + if (outputBufArray[i].pBuffer != NULL) { + pBufferHdr = outputBufArray[i].pBuffer; + pBufferHdr->nFilledLen = 0; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pBufferHdr); + } + } + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferFlush( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex, + OMX_BOOL bEvent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if ((nPortIndex < 0) || + (nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] OMX_CommandFlush start, port:%d, event:%d", + pExynosComponent, __FUNCTION__, nPortIndex, bEvent); + + ret = Exynos_OMX_FlushPort(pOMXComponent, nPortIndex); + if (ret != OMX_ErrorNone) + goto EXIT; + + Exynos_ResetCodecData(&pExynosPort->processData); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] OMX_CommandFlush end, port:%d, event:%d", + pExynosComponent, __FUNCTION__, nPortIndex, bEvent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_ResetCodecData(EXYNOS_OMX_DATA *pData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + /* caution: nPlanes in buffer structure might be used all times */ + Exynos_OSAL_Memset(&(pData->buffer.fd), 0, sizeof(pData->buffer.fd)); + Exynos_OSAL_Memset(&(pData->buffer.addr), 0, sizeof(pData->buffer.addr)); + + pData->dataLen = 0; + pData->usedDataLen = 0; + pData->remainDataLen = 0; + pData->nFlags = 0; + pData->timeStamp = 0; + pData->pPrivate = NULL; + pData->bufferHeader = NULL; + +EXIT: + return ret; +} diff --git a/openmax/component/video/enc/h264wfd/Exynos_OMX_H264enc_wfd.h b/openmax/component/video/enc/h264wfd/Exynos_OMX_H264enc_wfd.h new file mode 100644 index 0000000..28261a2 --- /dev/null +++ b/openmax/component/video/enc/h264wfd/Exynos_OMX_H264enc_wfd.h @@ -0,0 +1,133 @@ +/* + * + * Copyright 2017 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_H264enc_wfd.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * ByungGwan Kang (bk0917.kang@samsung.com) + * @version 2.0.0 + * @history + * 2017.06.20 : Create + */ + +#ifndef EXYNOS_OMX_H264_WFD_ENC_COMPONENT +#define EXYNOS_OMX_H264_WFD_ENC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" + +#include "ExynosVideoApi.h" +#include "library_register.h" + +typedef struct _EXYNOS_MFC_H264WFDENC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bPrependSpsPpsToIdr; + OMX_BOOL bTemporalSVC; + OMX_BOOL bRoiInfo; + OMX_U32 nLTRFrames; + + ExynosVideoEncOps *pEncOps; + ExynosVideoEncBufferOps *pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps; + ExynosVideoEncParam encParam; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 5 + OMX_VIDEO_AVCPROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_AVCLEVELTYPE maxLevel; +} EXYNOS_MFC_H264WFDENC_HANDLE; + +typedef struct _EXYNOS_H264WFDENC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_AVCTYPE AVCComponent[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_AVCSLICEFMO AVCSliceFmo; + OMX_VIDEO_QPRANGE qpRangeI; + OMX_VIDEO_QPRANGE qpRangeP; + OMX_VIDEO_QPRANGE qpRangeB; + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC TemporalSVC; /* Temporal SVC */ + + /* SEC MFC Codec specific */ + EXYNOS_MFC_H264WFDENC_HANDLE hMFCH264Handle; + + EXYNOS_QUEUE bypassBufferInfoQ; + + OMX_BOOL bLowLatency; + EXYNOS_OMX_HIERARCHICAL_CODING_TYPE eHierarchicalType; + + OMX_S32 nBaseLayerPid; + OMX_U32 nMaxTemporalLayerCount; +} EXYNOS_H264WFDENC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +OMX_ERRORTYPE Exynos_OMX_Port_Constructor(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_Port_Destructor(OMX_HANDLETYPE hComponent); +int Exynos_GetPlaneFromPort(EXYNOS_OMX_BASEPORT *pPort); +OMX_ERRORTYPE Exynos_SetPlaneToPort(EXYNOS_OMX_BASEPORT *pPort, int nPlaneNum); +OMX_ERRORTYPE Exynos_OMX_EmptyThisBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer); +OMX_ERRORTYPE Exynos_OMX_FillThisBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer); + + +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Constructor(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Destructor(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_Check_SizeVersion(OMX_PTR header, OMX_U32 size); + +void Exynos_UpdateFrameSize(OMX_COMPONENTTYPE *pOMXComponent); +void Exynos_Input_SetSupportFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +OMX_COLOR_FORMATTYPE Exynos_Input_GetActualColorFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +OMX_ERRORTYPE Exynos_ResetAllPortConfig(OMX_COMPONENTTYPE *pOMXComponent); +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent); + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer); +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes); +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/enc/h264wfd/NOTICE b/openmax/component/video/enc/h264wfd/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/enc/h264wfd/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/enc/h264wfd/library_register.c b/openmax/component/video/enc/h264wfd/library_register.c new file mode 100644 index 0000000..99988a3 --- /dev/null +++ b/openmax/component/video/enc/h264wfd/library_register.c @@ -0,0 +1,62 @@ +/* + * + * Copyright 2017 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * ByungGwan Kang (bk0917.kang@samsung.com) + * @version 2.0.0 + * @history + * 2017.06.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents) +{ + FunctionIn(); + + if (exynosComponents == NULL) + goto EXIT; + + /* component 1 - video Encoder H.264 */ + Exynos_OSAL_Strcpy(exynosComponents[0]->componentName, EXYNOS_OMX_COMPONENT_H264_WFD_ENC); + Exynos_OSAL_Strcpy(exynosComponents[0]->roles[0], EXYNOS_OMX_COMPONENT_H264_WFD_ENC_ROLE); + exynosComponents[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 2 - video Encoder H.264 for DRM */ + Exynos_OSAL_Strcpy(exynosComponents[1]->componentName, EXYNOS_OMX_COMPONENT_H264_WFD_DRM_ENC); + Exynos_OSAL_Strcpy(exynosComponents[1]->roles[0], EXYNOS_OMX_COMPONENT_H264_WFD_ENC_ROLE); + exynosComponents[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} + diff --git a/openmax/component/video/enc/h264wfd/library_register.h b/openmax/component/video/enc/h264wfd/library_register.h new file mode 100644 index 0000000..17e0a98 --- /dev/null +++ b/openmax/component/video/enc/h264wfd/library_register.h @@ -0,0 +1,58 @@ +/* + * + * Copyright 2017 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * ByungGwan Kang (bk0917.kang@samsung.com) + * @version 2.0.0 + * @history + * 2017.06.20 : Create + */ + +#ifndef EXYNOS_OMX_H264_WFD_REG +#define EXYNOS_OMX_H264_WFD_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 2 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* H.264 */ +#define EXYNOS_OMX_COMPONENT_H264_WFD_ENC "OMX.Exynos.AVC.WFD.Encoder" +#define EXYNOS_OMX_COMPONENT_H264_WFD_DRM_ENC "OMX.Exynos.AVC.WFD.Encoder.secure" +#define EXYNOS_OMX_COMPONENT_H264_WFD_ENC_ROLE "video_encoder.avc-wfd" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/openmax/component/video/enc/hevc/Android.mk b/openmax/component/video/enc/hevc/Android.mk new file mode 100644 index 0000000..33af2c3 --- /dev/null +++ b/openmax/component/video/enc/hevc/Android.mk @@ -0,0 +1,88 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_HEVCenc.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.HEVC.Encoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := +LOCAL_CFLAGS += -DUSE_HEVC_SUPPORT + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifeq ($(BOARD_USE_FULL_ST2094_40), true) +LOCAL_CFALGS += -DUSE_FULL_ST2094_40 +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Venc libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/enc \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_SMALL_SECURE_MEMORY), true) +LOCAL_CFLAGS += -DUSE_SMALL_SECURE_MEMORY +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/enc/hevc/Exynos_OMX_HEVCenc.c b/openmax/component/video/enc/hevc/Exynos_OMX_HEVCenc.c new file mode 100644 index 0000000..625f60e --- /dev/null +++ b/openmax/component/video/enc/hevc/Exynos_OMX_HEVCenc.c @@ -0,0 +1,4545 @@ +/* + * + * Copyright 2014 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_HEVCenc.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2014.05.22 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Venc.h" +#include "Exynos_OMX_VencControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_HEVCenc.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OSAL_Queue.h" + +#include "Exynos_OSAL_Platform.h" + +#include "VendorVideoAPI.h" + +/* To use CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */ +/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_HEVC_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain; + pHevcEnc->hMFCHevcHandle.nProfileCnt = nProfileCnt; + + switch (pHevcEnc->hMFCHevcHandle.videoInstInfo.HwVersion) { + case MFC_1501: + case MFC_150: + case MFC_1400: + case MFC_1410: + case MFC_140: + pHevcEnc->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10; + pHevcEnc->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10HDR10; + pHevcEnc->hMFCHevcHandle.nProfileCnt = nProfileCnt; + + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel6; + break; + case MFC_130: + case MFC_120: + case MFC_1220: + pHevcEnc->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10; + pHevcEnc->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10HDR10; + pHevcEnc->hMFCHevcHandle.nProfileCnt = nProfileCnt; + + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel6; + break; + case MFC_110: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel6; + break; + case MFC_100: + case MFC_101: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel51; + break; + case MFC_90: + case MFC_1010: + case MFC_1120: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel5; + break; + case MFC_1011: + case MFC_1020: + case MFC_1021: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel41; + break; + case MFC_92: + default: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel4; + break; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + int nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pHevcEnc->hMFCHevcHandle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pHevcEnc->hMFCHevcHandle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pHevcEnc->hMFCHevcHandle.maxLevel; +#else + while ((pHevcEnc->hMFCHevcHandle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pHevcEnc->hMFCHevcHandle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pHevcEnc->hMFCHevcHandle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pHevcEnc->hMFCHevcHandle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) + goto EXIT; + + while ((pHevcEnc->hMFCHevcHandle.maxLevel >> nLevelCnt++) > 0); + + if ((pHevcEnc->hMFCHevcHandle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pHevcEnc->hMFCHevcHandle.nProfileCnt; i++) { + if (pHevcEnc->hMFCHevcHandle.profiles[i] == pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +static OMX_U32 OMXHevcProfileToProfileIDC(OMX_VIDEO_HEVCPROFILETYPE eProfile) +{ + OMX_U32 ret = 0; + + switch (eProfile) { + case OMX_VIDEO_HEVCProfileMain: + ret = 0; + break; + case OMX_VIDEO_HEVCProfileMain10: + case OMX_VIDEO_HEVCProfileMain10HDR10: + case OMX_VIDEO_HEVCProfileMain10HDR10Plus: + ret = 3; + break; + default: + ret = 0; + break; + } + + return ret; +} + +static OMX_U32 OMXHevcLevelToTierIDC(OMX_VIDEO_HEVCLEVELTYPE eLevel) +{ + OMX_U32 ret = 0; //default Main tier + + switch (eLevel) { + case OMX_VIDEO_HEVCMainTierLevel1: + case OMX_VIDEO_HEVCMainTierLevel2: + case OMX_VIDEO_HEVCMainTierLevel21: + case OMX_VIDEO_HEVCMainTierLevel3: + case OMX_VIDEO_HEVCMainTierLevel31: + case OMX_VIDEO_HEVCMainTierLevel4: + case OMX_VIDEO_HEVCMainTierLevel41: + case OMX_VIDEO_HEVCMainTierLevel5: + case OMX_VIDEO_HEVCMainTierLevel51: + case OMX_VIDEO_HEVCMainTierLevel52: + case OMX_VIDEO_HEVCMainTierLevel6: + case OMX_VIDEO_HEVCMainTierLevel61: + case OMX_VIDEO_HEVCMainTierLevel62: + ret = 0; + break; + case OMX_VIDEO_HEVCHighTierLevel1: + case OMX_VIDEO_HEVCHighTierLevel2: + case OMX_VIDEO_HEVCHighTierLevel21: + case OMX_VIDEO_HEVCHighTierLevel3: + case OMX_VIDEO_HEVCHighTierLevel31: + case OMX_VIDEO_HEVCHighTierLevel4: + case OMX_VIDEO_HEVCHighTierLevel41: + case OMX_VIDEO_HEVCHighTierLevel5: + case OMX_VIDEO_HEVCHighTierLevel51: + case OMX_VIDEO_HEVCHighTierLevel52: + case OMX_VIDEO_HEVCHighTierLevel6: + case OMX_VIDEO_HEVCHighTierLevel61: + case OMX_VIDEO_HEVCHighTierLevel62: + ret = 1; + break; + default: + ret = 0; + break; + } + + return ret; +} + +static OMX_U32 OMXHevcLevelToLevelIDC(OMX_VIDEO_HEVCLEVELTYPE eLevel) +{ + OMX_U32 ret = 40; //default OMX_VIDEO_HEVCLevel4 + + switch (eLevel) { + case OMX_VIDEO_HEVCMainTierLevel1: + case OMX_VIDEO_HEVCHighTierLevel1: + ret = 10; + break; + case OMX_VIDEO_HEVCMainTierLevel2: + case OMX_VIDEO_HEVCHighTierLevel2: + ret = 20; + break; + case OMX_VIDEO_HEVCMainTierLevel21: + case OMX_VIDEO_HEVCHighTierLevel21: + ret = 21; + break; + case OMX_VIDEO_HEVCMainTierLevel3: + case OMX_VIDEO_HEVCHighTierLevel3: + ret = 30; + break; + case OMX_VIDEO_HEVCMainTierLevel31: + case OMX_VIDEO_HEVCHighTierLevel31: + ret = 31; + break; + case OMX_VIDEO_HEVCMainTierLevel4: + case OMX_VIDEO_HEVCHighTierLevel4: + ret = 40; + break; + case OMX_VIDEO_HEVCMainTierLevel41: + case OMX_VIDEO_HEVCHighTierLevel41: + ret = 41; + break; + case OMX_VIDEO_HEVCMainTierLevel5: + case OMX_VIDEO_HEVCHighTierLevel5: + ret = 50; + break; + case OMX_VIDEO_HEVCMainTierLevel51: + case OMX_VIDEO_HEVCHighTierLevel51: + ret = 51; + break; + case OMX_VIDEO_HEVCMainTierLevel52: + case OMX_VIDEO_HEVCHighTierLevel52: + ret = 52; + break; + case OMX_VIDEO_HEVCMainTierLevel6: + case OMX_VIDEO_HEVCHighTierLevel6: + ret = 60; + break; + case OMX_VIDEO_HEVCMainTierLevel61: + case OMX_VIDEO_HEVCHighTierLevel61: + ret = 61; + break; + case OMX_VIDEO_HEVCMainTierLevel62: + case OMX_VIDEO_HEVCHighTierLevel62: + ret = 62; + break; + default: + ret = 40; + break; + } + + return ret; +} + +static void Print_HEVCEnc_Param(ExynosVideoEncParam *pEncParam) +{ + ExynosVideoEncCommonParam *pCommonParam = &pEncParam->commonParam; + ExynosVideoEncHevcParam *pHEVCParam = &pEncParam->codecParam.hevc; + + /* common parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceWidth : %d", pCommonParam->SourceWidth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceHeight : %d", pCommonParam->SourceHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "IDRPeriod : %d", pCommonParam->IDRPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SliceMode : %d", pCommonParam->SliceMode); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RandomIntraMBRefresh : %d", pCommonParam->RandomIntraMBRefresh); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Bitrate : %d", pCommonParam->Bitrate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp : %d", pCommonParam->FrameQp); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_P : %d", pCommonParam->FrameQp_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(I) ranege : %d / %d", pCommonParam->QpRange.QpMin_I, pCommonParam->QpRange.QpMax_I); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(P) ranege : %d / %d", pCommonParam->QpRange.QpMin_P, pCommonParam->QpRange.QpMax_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(B) ranege : %d / %d", pCommonParam->QpRange.QpMin_B, pCommonParam->QpRange.QpMax_B); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DropControl : %d", pCommonParam->bDropControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DisableDFR : %d", pCommonParam->bDisableDFR); + + /* HEVC specific parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "ProfileIDC : %d", pHEVCParam->ProfileIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "TierIDC : %d", pHEVCParam->TierIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LevelIDC : %d", pHEVCParam->LevelIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_B : %d", pHEVCParam->FrameQp_B); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameRate : %d", pHEVCParam->FrameRate); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "MaxPartitionDepth : %d", pHEVCParam->MaxPartitionDepth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberBFrames : %d", pHEVCParam->NumberBFrames); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberRefForPframes : %d", pHEVCParam->NumberRefForPframes); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterDisable : %d", pHEVCParam->LoopFilterDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterSliceFlag : %d", pHEVCParam->LoopFilterSliceFlag); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterTcOffset : %d", pHEVCParam->LoopFilterTcOffset); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterBetaOffset : %d", pHEVCParam->LoopFilterBetaOffset); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LongtermRefEnable : %d", pHEVCParam->LongtermRefEnable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LongtermUserRef : %d", pHEVCParam->LongtermUserRef); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LongtermStoreRef : %d", pHEVCParam->LongtermStoreRef); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "DarkDisable : %d", pHEVCParam->DarkDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SmoothDisable : %d", pHEVCParam->SmoothDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "StaticDisable : %d", pHEVCParam->StaticDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "ActivityDisable : %d", pHEVCParam->ActivityDisable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "ROIEnable: : %d", pHEVCParam->ROIEnable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "GPBEnable: : %d", pHEVCParam->GPBEnable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "HierarType: : %d", pHEVCParam->HierarType); + + /* rate control related parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableFRMRateControl : %d", pCommonParam->EnableFRMRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableMBRateControl : %d", pCommonParam->EnableMBRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CBRPeriodRf : %d", pCommonParam->CBRPeriodRf); +} + +static void Set_HEVCEnc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + EXYNOS_MFC_HEVCENC_HANDLE *pMFCHevcHandle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncInitParam *pInitParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncHevcParam *pHEVCParam = NULL; + + OMX_S32 nWidth, nHeight; + int i; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCHevcHandle = &pHevcEnc->hMFCHevcHandle; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pEncParam = &pMFCHevcHandle->encParam; + pInitParam = &pEncParam->initParam; + pCommonParam = &pEncParam->commonParam; + pHEVCParam = &pEncParam->codecParam.hevc; + + pEncParam->eCompressionFormat = VIDEO_CODING_HEVC; + + /* uses specified target size instead of size on output port */ + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + nWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + + /* common parameters */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + pCommonParam->SourceWidth = nWidth; + pCommonParam->SourceHeight = nHeight; + } else { + pCommonParam->SourceWidth = nHeight; + pCommonParam->SourceHeight = nWidth; + } + pCommonParam->IDRPeriod = pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].nKeyFrameInterval; + pCommonParam->SliceMode = 0; + pCommonParam->Bitrate = pOutputPort->portDefinition.format.video.nBitrate; + pCommonParam->FrameQp = pVideoEnc->quantization.nQpI; + pCommonParam->FrameQp_P = pVideoEnc->quantization.nQpP; + + pCommonParam->QpRange.QpMin_I = pHevcEnc->qpRangeI.nMinQP; + pCommonParam->QpRange.QpMax_I = pHevcEnc->qpRangeI.nMaxQP; + pCommonParam->QpRange.QpMin_P = pHevcEnc->qpRangeP.nMinQP; + pCommonParam->QpRange.QpMax_P = pHevcEnc->qpRangeP.nMaxQP; + pCommonParam->QpRange.QpMin_B = pHevcEnc->qpRangeB.nMinQP; + pCommonParam->QpRange.QpMax_B = pHevcEnc->qpRangeB.nMaxQP; + + pCommonParam->PadControlOn = 0; /* 0: disable, 1: enable */ + pCommonParam->LumaPadVal = 0; + pCommonParam->CbPadVal = 0; + pCommonParam->CrPadVal = 0; + + if (pVideoEnc->intraRefresh.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic) { + /* Cyclic Mode */ + pCommonParam->RandomIntraMBRefresh = pVideoEnc->intraRefresh.nCirMBs; + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + + /* Perceptual Mode */ + pCommonParam->PerceptualMode = (pVideoEnc->bPVCMode)? VIDEO_TRUE:VIDEO_FALSE; + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + pCommonParam->bDropControl = (pVideoEnc->bDropControl)? VIDEO_TRUE:VIDEO_FALSE; + pCommonParam->bDisableDFR = (pVideoEnc->bDisableDFR)? VIDEO_TRUE:VIDEO_FALSE; + + /* HEVC specific parameters */ + pHEVCParam->ProfileIDC = OMXHevcProfileToProfileIDC(pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].eProfile); + pHEVCParam->TierIDC = OMXHevcLevelToTierIDC(pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].eLevel); + pHEVCParam->LevelIDC = OMXHevcLevelToLevelIDC(pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].eLevel); + + pHEVCParam->FrameQp_B = pVideoEnc->quantization.nQpB; + pHEVCParam->FrameRate = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + + if (pHevcEnc->nTemporalLayerCountForB > 0) + pHEVCParam->NumberRefForPframes = 1; /* Hierarchical-B enabled */ + else + pHEVCParam->NumberRefForPframes = pMFCHevcHandle->nRefForPframes; + + /* there is no interface at OMX IL component */ + pHEVCParam->NumberBFrames = 0; /* 0 ~ 2 */ + + pHEVCParam->MaxPartitionDepth = 1; + pHEVCParam->LoopFilterDisable = 0; /* 1: Loop Filter Disable, 0: Filter Enable */ + pHEVCParam->LoopFilterSliceFlag = 1; + pHEVCParam->LoopFilterTcOffset = 0; + pHEVCParam->LoopFilterBetaOffset = 0; + + pHEVCParam->LongtermRefEnable = 0; + pHEVCParam->LongtermUserRef = 0; + pHEVCParam->LongtermStoreRef = 0; + + pHEVCParam->DarkDisable = 1; /* disable adaptive rate control on dark region */ + pHEVCParam->SmoothDisable = 1; /* disable adaptive rate control on smooth region */ + pHEVCParam->StaticDisable = 1; /* disable adaptive rate control on static region */ + pHEVCParam->ActivityDisable = 1; /* disable adaptive rate control on high activity region */ + + /* Chroma QP Offset */ + pHEVCParam->chromaQPOffset.Cr = pHevcEnc->chromaQPOffset.nCr; + pHEVCParam->chromaQPOffset.Cb = pHevcEnc->chromaQPOffset.nCb; + + /* Temporal SVC */ + /* If MaxTemporalLayerCount value is 0, codec supported max value will be set */ + pHEVCParam->MaxTemporalLayerCount = 0; + pHEVCParam->TemporalSVC.nTemporalLayerCount = (unsigned int)pHevcEnc->nTemporalLayerCount; + + if (pHevcEnc->bUseTemporalLayerBitrateRatio == OMX_TRUE) { + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) + pHEVCParam->TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pHevcEnc->nTemporalLayerBitrateRatio[i]; + } else { + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) + pHEVCParam->TemporalSVC.nTemporalLayerBitrateRatio[i] = pOutputPort->portDefinition.format.video.nBitrate; + } + + /* Hierarchal P & B */ + if (pHevcEnc->nTemporalLayerCountForB > 0) + pHEVCParam->HierarType = EXYNOS_OMX_Hierarchical_B; + else + pHEVCParam->HierarType = EXYNOS_OMX_Hierarchical_P; + + pHEVCParam->ROIEnable = (pMFCHevcHandle->bRoiInfo == OMX_TRUE)? 1:0; + pHEVCParam->GPBEnable = (ExynosVideoBoolType)pMFCHevcHandle->bGPBEnable; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eControlRate: 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]); + /* rate control related parameters */ + switch ((int)pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]) { + case OMX_Video_ControlRateDisable: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode DBR"); + pCommonParam->EnableFRMRateControl = 0; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 0; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + case OMX_Video_ControlRateConstantVTCall: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR VT Call"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 5; + pCommonParam->bFixedSlice = VIDEO_TRUE; + break; + case OMX_Video_ControlRateConstantSkipFrames: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR VT Call with Skip frame"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 5; + pCommonParam->bFixedSlice = VIDEO_TRUE; + pInitParam->FrameSkip = VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT; + break; + case OMX_Video_ControlRateConstant: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 9; + break; + case OMX_Video_ControlRateVariable: + default: /*Android default */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode VBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + } + +// Print_HEVCEnc_Param(pEncParam); +} + +static void Change_HEVCEnc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + EXYNOS_MFC_HEVCENC_HANDLE *pMFCHevcHandle = NULL; + OMX_PTR pDynamicConfigCMD = NULL; + OMX_PTR pConfigData = NULL; + OMX_S32 nCmdIndex = 0; + ExynosVideoEncOps *pEncOps = NULL; + int nValue = 0; + + int i; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCHevcHandle = &pHevcEnc->hMFCHevcHandle; + pEncOps = pMFCHevcHandle->pEncOps; + + pDynamicConfigCMD = (OMX_PTR)Exynos_OSAL_Dequeue(&pExynosComponent->dynamicConfigQ); + if (pDynamicConfigCMD == NULL) + goto EXIT; + + nCmdIndex = *(OMX_S32 *)pDynamicConfigCMD; + pConfigData = (OMX_PTR)((OMX_U8 *)pDynamicConfigCMD + sizeof(OMX_S32)); + + switch ((int)nCmdIndex) { + case OMX_IndexConfigVideoIntraVOPRefresh: + { + nValue = VIDEO_FRAME_I; + pEncOps->Set_FrameType(pMFCHevcHandle->hMFCHandle, nValue); + pVideoEnc->IntraRefreshVOP = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] VOP Refresh", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_S32 nPFrames = (*((OMX_U32 *)pConfigData)) - 1; + nValue = nPFrames + 1; + pEncOps->Set_IDRPeriod(pMFCHevcHandle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] IDR period: %d", pExynosComponent, __FUNCTION__, nValue); + } + break; + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pConfigData; + + if (pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] != OMX_Video_ControlRateDisable) { + nValue = pConfigBitrate->nEncodeBitrate; + pEncOps->Set_BitRate(pMFCHevcHandle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bitrate: %d", pExynosComponent, __FUNCTION__, nValue); + } + } + break; + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pConfigData; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + + if (nPortIndex == INPUT_PORT_INDEX) { + nValue = (pConfigFramerate->xEncodeFramerate) >> 16; + pEncOps->Set_FrameRate(pMFCHevcHandle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] framerate: %d", pExynosComponent, __FUNCTION__, nValue); + } + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pConfigData; + ExynosVideoQPRange qpRange; + + qpRange.QpMin_I = pQpRange->qpRangeI.nMinQP; + qpRange.QpMax_I = pQpRange->qpRangeI.nMaxQP; + qpRange.QpMin_P = pQpRange->qpRangeP.nMinQP; + qpRange.QpMax_P = pQpRange->qpRangeP.nMaxQP; + qpRange.QpMin_B = pQpRange->qpRangeB.nMinQP; + qpRange.QpMax_B = pQpRange->qpRangeB.nMaxQP; + + pEncOps->Set_QpRange(pMFCHevcHandle->hMFCHandle, qpRange); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qp range: I(%d, %d), P(%d, %d), B(%d, %d)", + pExynosComponent, __FUNCTION__, + qpRange.QpMin_I, qpRange.QpMax_I, + qpRange.QpMin_P, qpRange.QpMax_P, + qpRange.QpMin_B, qpRange.QpMax_B); + } + break; + case OMX_IndexConfigOperatingRate: + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pConfigData; + OMX_U32 xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + + nValue = pConfigRate->nU32 >> 16; + + if (pMFCHevcHandle->videoInstInfo.supportInfo.enc.bOperatingRateSupport == VIDEO_TRUE) { + if (nValue == ((OMX_U32)INT_MAX >> 16)) { + nValue = (OMX_U32)INT_MAX; + } else { + nValue = nValue * 1000; + } + + pEncOps->Set_OperatingRate(pMFCHevcHandle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] operating rate: 0x%x", pExynosComponent, __FUNCTION__, nValue); + } else { + if (nValue == (((OMX_U32)INT_MAX) >> 16)) { + nValue = 1000; + } else { + nValue = ((xFramerate >> 16) == 0)? 100:(OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + } + + pEncOps->Set_QosRatio(pMFCHevcHandle->hMFCHandle, nValue); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qos ratio: 0x%x", pExynosComponent, __FUNCTION__, nValue); + } + + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pConfigData; + ExynosVideoQPRange qpRange; + TemporalLayerShareBuffer TemporalSVC; + + qpRange.QpMin_I = pTemporalSVC->nMinQuantizer; + qpRange.QpMax_I = pTemporalSVC->nMaxQuantizer; + qpRange.QpMin_P = pTemporalSVC->nMinQuantizer; + qpRange.QpMax_P = pTemporalSVC->nMaxQuantizer; + qpRange.QpMin_B = pTemporalSVC->nMinQuantizer; + qpRange.QpMax_B = pTemporalSVC->nMaxQuantizer; + + pEncOps->Set_QpRange(pMFCHevcHandle->hMFCHandle, qpRange); + pEncOps->Set_IDRPeriod(pMFCHevcHandle->hMFCHandle, pTemporalSVC->nKeyFrameInterval); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // qp range: I(%d, %d), P(%d, %d), B(%d, %d)", + pExynosComponent, __FUNCTION__, + qpRange.QpMin_I, qpRange.QpMax_I, + qpRange.QpMin_P, qpRange.QpMax_P, + qpRange.QpMin_B, qpRange.QpMax_B); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // IDR period: %d", pExynosComponent, __FUNCTION__, nValue); + + /* Temporal SVC */ + Exynos_OSAL_Memset(&TemporalSVC, 0, sizeof(TemporalLayerShareBuffer)); + + TemporalSVC.nTemporalLayerCount = (unsigned int)pTemporalSVC->nTemporalLayerCount; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // layer count: %d", pExynosComponent, __FUNCTION__, TemporalSVC.nTemporalLayerCount); + + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) { + TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pTemporalSVC->nTemporalLayerBitrateRatio[i]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // bitrate ratio[%d]: %d", + pExynosComponent, __FUNCTION__, + i, TemporalSVC.nTemporalLayerBitrateRatio[i]); + } + if (pEncOps->Set_LayerChange(pMFCHevcHandle->hMFCHandle, TemporalSVC) != VIDEO_ERROR_NONE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Not supported control: Set_LayerChange", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigVideoRoiInfo: + { + EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *pRoiInfo = (EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *)pConfigData; + + /* ROI INFO */ + RoiInfoShareBuffer RoiInfo; + + Exynos_OSAL_Memset(&RoiInfo, 0, sizeof(RoiInfo)); + RoiInfo.pRoiMBInfo = (OMX_U64)(unsigned long)(((OMX_U8 *)pConfigData) + sizeof(EXYNOS_OMX_VIDEO_CONFIG_ROIINFO)); + RoiInfo.nRoiMBInfoSize = pRoiInfo->nRoiMBInfoSize; + RoiInfo.nUpperQpOffset = pRoiInfo->nUpperQpOffset; + RoiInfo.nLowerQpOffset = pRoiInfo->nLowerQpOffset; + RoiInfo.bUseRoiInfo = (pRoiInfo->bUseRoiInfo == OMX_TRUE)? VIDEO_TRUE:VIDEO_FALSE; + + if (pEncOps->Set_RoiInfo(pMFCHevcHandle->hMFCHandle, &RoiInfo) != VIDEO_ERROR_NONE) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Set_RoiInfo()", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigIFrameRatio: + { + OMX_PARAM_U32TYPE *pIFrameRatio = (OMX_PARAM_U32TYPE *)pConfigData; + + pEncOps->Set_IFrameRatio(pMFCHevcHandle->hMFCHandle, pIFrameRatio->nU32); + } + break; + case OMX_IndexConfigCommonOutputSize: + { + OMX_FRAMESIZETYPE *pFrameSize = (OMX_FRAMESIZETYPE *)pConfigData; + OMX_CONFIG_RECTTYPE *pTargetFrame = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].cropRectangle[IMG_CROP_OUTPUT_PORT]); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] resolution(%d x %d) is changed to (%d x %d)", pExynosComponent, __FUNCTION__, + pTargetFrame->nWidth, pTargetFrame->nHeight, + pFrameSize->nWidth, pFrameSize->nHeight); + + /* update target size */ + pTargetFrame->nTop = 0; + pTargetFrame->nLeft = 0; + pTargetFrame->nWidth = pFrameSize->nWidth; + pTargetFrame->nHeight = pFrameSize->nHeight; + + pVideoEnc->bEncDRC = OMX_TRUE; + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigAndroidVideoTemporalLayering: + { + OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *pTemporalLayering = (OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *)pConfigData; + + TemporalLayerShareBuffer TemporalSVC; + + /* Temporal SVC */ + Exynos_OSAL_Memset(&TemporalSVC, 0, sizeof(TemporalLayerShareBuffer)); + + TemporalSVC.nTemporalLayerCount = (unsigned int)(pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual); + + if (pTemporalLayering->bBitrateRatiosSpecified == OMX_TRUE) { + for (i = 0; i < (int)pHevcEnc->nMaxTemporalLayerCount; i++) { + + TemporalSVC.nTemporalLayerBitrateRatio[i] = (pTemporalLayering->nBitrateRatios[i] >> 16); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // bitrate ratio[%d]: %d", + pExynosComponent, __FUNCTION__, + i, TemporalSVC.nTemporalLayerBitrateRatio[i]); + } + } else { + EXYNOS_OMX_BASEPORT *pOutputPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + + for (i = 0; i < (int)pHevcEnc->nMaxTemporalLayerCount; i++) { + TemporalSVC.nTemporalLayerBitrateRatio[i] = pOutputPort->portDefinition.format.video.nBitrate; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // bitrate ratio[%d]: %d", + pExynosComponent, __FUNCTION__, + i, TemporalSVC.nTemporalLayerBitrateRatio[i]); + } + } + + if (pEncOps->Set_LayerChange(pMFCHevcHandle->hMFCHandle, TemporalSVC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Not supported control: Set_LayerChange", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Max(%d), layer(%d), B-layer(%d)", pExynosComponent, __FUNCTION__, + pHevcEnc->nMaxTemporalLayerCount, TemporalSVC.nTemporalLayerCount, pTemporalLayering->nBLayerCountActual); + } + break; +#endif + default: + break; + } + + Exynos_OSAL_Free(pDynamicConfigCMD); + + Set_HEVCEnc_Param(pExynosComponent); + +EXIT: + return; +} + +OMX_ERRORTYPE GetCodecOutputPrivateData( + OMX_PTR pCodecBuffer, + OMX_PTR *pVirtAddr, + OMX_U32 *pDataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pVideoBuffer = NULL; + + if (pCodecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoBuffer = (ExynosVideoBuffer *)pCodecBuffer; + + if (pVirtAddr != NULL) + *pVirtAddr = pVideoBuffer->planes[0].addr; + + if (pDataSize != NULL) + *pDataSize = pVideoBuffer->planes[0].allocSize; + +EXIT: + return ret; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) + goto EXIT; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE HEVCCodecOpen( + EXYNOS_HEVCENC_HANDLE *pHevcEnc, + ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pHevcEnc == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pEncOps = (ExynosVideoEncOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncOps)); + pInbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + pOutbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + + if ((pEncOps == NULL) || + (pInbufOps == NULL) || + (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.pEncOps = pEncOps; + pHevcEnc->hMFCHevcHandle.pInbufOps = pInbufOps; + pHevcEnc->hMFCHevcHandle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pEncOps->nSize = sizeof(ExynosVideoEncOps); + pInbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + + if (Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for encoder ops */ + if ((pEncOps->Init == NULL) || + (pEncOps->Finalize == NULL) || + (pEncOps->Set_FrameTag == NULL) || + (pEncOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pHevcEnc->hMFCHevcHandle.hMFCHandle = pHevcEnc->hMFCHevcHandle.pEncOps->Init(pVideoInstInfo); + if (pHevcEnc->hMFCHevcHandle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pHevcEnc->hMFCHevcHandle.pEncOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pHevcEnc->hMFCHevcHandle.pInbufOps = NULL; + } + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pHevcEnc->hMFCHevcHandle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HEVCCodecClose(EXYNOS_HEVCENC_HANDLE *pHevcEnc) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pHevcEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + + if (hMFCHandle != NULL) { + pEncOps->Finalize(hMFCHandle); + hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle = NULL; + pHevcEnc->hMFCHevcHandle.bConfiguredMFCSrc = OMX_FALSE; + pHevcEnc->hMFCHevcHandle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Encoder(pEncOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps = NULL; + } + + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HEVCCodecStart( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + + if (nPortIndex == INPUT_PORT_INDEX) + pInbufOps->Run(hMFCHandle); + else if (nPortIndex == OUTPUT_PORT_INDEX) + pOutbufOps->Run(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HEVCCodecStop( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) + pInbufOps->Stop(hMFCHandle); + else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) + pOutbufOps->Stop(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HEVCCodecOutputBufferProcessRun( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pHevcEnc->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pHevcEnc->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pHevcEnc->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pHevcEnc->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pHevcEnc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HEVCCodecEnqueueAllBuffer( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + + ExynosVideoEncBufferOps *pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + + int i; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && + (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pHevcEnc->bSourceStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoEnc->pMFCEncInputBuffer[i]->fd[0], pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, INPUT_PORT_INDEX, pVideoEnc->pMFCEncInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pHevcEnc->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoEnc->pMFCEncOutputBuffer[i]->fd[0], pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoEnc->pMFCEncOutputBuffer[i]); + } + + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + +void HEVCCodecSetHdrInfo( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_HEVCENC_HANDLE *pMFCHevcHandle = &pHevcEnc->hMFCHevcHandle; + void *hMFCHandle = pMFCHevcHandle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + + OMX_COLOR_FORMATTYPE eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + /* color aspects */ + if (pMFCHevcHandle->videoInstInfo.supportInfo.enc.bColorAspectsSupport == VIDEO_TRUE) { + ExynosVideoColorAspects BSCA; + Exynos_OSAL_Memset(&BSCA, 0, sizeof(BSCA)); + +#ifdef USE_ANDROID + if (pVideoEnc->surfaceFormat == eColorFormat) { + Exynos_OSAL_GetColorAspectsForBitstream(&(pInputPort->ColorAspects), &(pOutputPort->ColorAspects)); + + /* in case of RGBA, re-update suitable values(transfer) */ + if (pVideoEnc->surfaceFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888) { + /* Eventhough frameworks already sent ColorAspects, + * sometimes dataspace has not set to OMX component because of timing. + * So get dataspace from frameworks ColorAspects. + */ + if (pInputPort->ColorAspects.nDataSpace == 0) { + Exynos_OSAL_UpdateDataSpaceFromAspects(&(pInputPort->ColorAspects)); + } + Exynos_OSAL_GetRGBColorTypeForBitStream(&pOutputPort->ColorAspects, pInputPort->ColorAspects.nDataSpace, eColorFormat); + } + } else { + /* in case of RGBA->YUV, color aspects for bitstream is already updated */ + if (pVideoEnc->surfaceFormat != (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888) { + Exynos_OSAL_GetColorAspectsForBitstream(&(pInputPort->ColorAspects), &(pOutputPort->ColorAspects)); + } + } +#endif + + BSCA.eRangeType = (ExynosRangeType)pOutputPort->ColorAspects.nRangeType; + BSCA.ePrimariesType = (ExynosPrimariesType)pOutputPort->ColorAspects.nPrimaryType; + BSCA.eTransferType = (ExynosTransferType)pOutputPort->ColorAspects.nTransferType; + BSCA.eCoeffType = (ExynosMatrixCoeffType)pOutputPort->ColorAspects.nCoeffType; + + pEncOps->Set_ColorAspects(hMFCHandle, &BSCA); + } + + /* hdr info : it is supported on 10bit encoding only */ + if ((eColorFormat == OMX_SEC_COLOR_FormatS10bitYUV420SemiPlanar) || + (eColorFormat == OMX_COLOR_FormatYUV420Planar16)) { + /* hdr static info */ + if (pMFCHevcHandle->videoInstInfo.supportInfo.enc.bHDRStaticInfoSupport == VIDEO_TRUE) { + EXYNOS_OMX_VIDEO_HDRSTATICINFO *FWHDR = &(pInputPort->HDRStaticInfo); + ExynosVideoHdrStatic BSHDR; + Exynos_OSAL_Memset(&BSHDR, 0, sizeof(BSHDR)); + + BSHDR.max_pic_average_light = (int)FWHDR->nMaxPicAverageLight; + BSHDR.max_content_light = (int)FWHDR->nMaxContentLight; + BSHDR.max_display_luminance = (int)FWHDR->nMaxDisplayLuminance; + BSHDR.min_display_luminance = (int)FWHDR->nMinDisplayLuminance; + + BSHDR.red.x = (unsigned short)FWHDR->red.x; + BSHDR.red.y = (unsigned short)FWHDR->red.y; + BSHDR.green.x = (unsigned short)FWHDR->green.x; + BSHDR.green.y = (unsigned short)FWHDR->green.y; + BSHDR.blue.x = (unsigned short)FWHDR->blue.x; + BSHDR.blue.y = (unsigned short)FWHDR->blue.y; + BSHDR.white.x = (unsigned short)FWHDR->white.x; + BSHDR.white.y = (unsigned short)FWHDR->white.y; + +#ifdef USE_ANDROID + if ((pInputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) && + ((pInputPort->bufferProcessType & BUFFER_SHARE) && + (pSrcInputData->buffer.addr[2] != NULL))) { + ExynosVideoMeta *pMeta = (ExynosVideoMeta *)pSrcInputData->buffer.addr[2]; + + /* use HDRStaticInfo given from camera */ + if (pMeta->eType & VIDEO_INFO_TYPE_HDR_STATIC) { + ExynosHdrStaticInfo *pHdrStaticInfo = &(pMeta->sHdrStaticInfo); + + BSHDR.max_pic_average_light = (int)pHdrStaticInfo->sType1.mMaxFrameAverageLightLevel; + BSHDR.max_content_light = (int)pHdrStaticInfo->sType1.mMaxContentLightLevel; + BSHDR.max_display_luminance = (int)pHdrStaticInfo->sType1.mMaxDisplayLuminance; + BSHDR.min_display_luminance = (int)pHdrStaticInfo->sType1.mMinDisplayLuminance; + + BSHDR.red.x = (unsigned short)pHdrStaticInfo->sType1.mR.x; + BSHDR.red.y = (unsigned short)pHdrStaticInfo->sType1.mR.y; + BSHDR.green.x = (unsigned short)pHdrStaticInfo->sType1.mG.x; + BSHDR.green.y = (unsigned short)pHdrStaticInfo->sType1.mG.y; + BSHDR.blue.x = (unsigned short)pHdrStaticInfo->sType1.mB.x; + BSHDR.blue.y = (unsigned short)pHdrStaticInfo->sType1.mB.y; + BSHDR.white.x = (unsigned short)pHdrStaticInfo->sType1.mW.x; + BSHDR.white.y = (unsigned short)pHdrStaticInfo->sType1.mW.y; + } + } +#endif + pEncOps->Set_HDRStaticInfo(hMFCHandle, &BSHDR); + } + + /* hdr dynamic info */ + if (pMFCHevcHandle->videoInstInfo.supportInfo.enc.bHDRDynamicInfoSupport == VIDEO_TRUE) { + /* just enable a mode. hdr dynamic info will be updated in SrcIn */ + pMFCHevcHandle->bHDRDynamicInfo = OMX_TRUE; + } + } + + return ; +} + +void HEVCCodecUpdateHdrDynamicInfo( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_HEVCENC_HANDLE *pMFCHevcHandle = &pHevcEnc->hMFCHevcHandle; + void *hMFCHandle = pMFCHevcHandle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + + int i; + + if (pMFCHevcHandle->videoInstInfo.supportInfo.enc.bHDRDynamicInfoSupport == VIDEO_TRUE) { + ExynosVideoHdrDynamic BSHDR; + Exynos_OSAL_Memset(&BSHDR, 0, sizeof(BSHDR)); + +#ifdef USE_ANDROID + if ((pInputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) && + ((pInputPort->bufferProcessType & BUFFER_SHARE) && + (pSrcInputData->buffer.addr[2] != NULL))) { + ExynosVideoMeta *pMeta = (ExynosVideoMeta *)pSrcInputData->buffer.addr[2]; + + if (pMeta->eType & VIDEO_INFO_TYPE_HDR_DYNAMIC) { + ExynosHdrDynamicInfo *pMetaHDRDynamic = &(pMeta->sHdrDynamicInfo); + + BSHDR.valid = pMetaHDRDynamic->valid; + + if (pMetaHDRDynamic->valid != 0) { + BSHDR.itu_t_t35_country_code = pMetaHDRDynamic->data.country_code; + BSHDR.itu_t_t35_terminal_provider_code = pMetaHDRDynamic->data.provider_code; + BSHDR.itu_t_t35_terminal_provider_oriented_code = pMetaHDRDynamic->data.provider_oriented_code; + BSHDR.application_identifier = pMetaHDRDynamic->data.application_identifier; + BSHDR.application_version = pMetaHDRDynamic->data.application_version; + +#ifdef USE_FULL_ST2094_40 + BSHDR.targeted_system_display_maximum_luminance = pMetaHDRDynamic->data.targeted_system_display_maximum_luminance; + + /* save information on window-0 only */ + BSHDR.num_windows = 1; + { + ExynosVideoHdrWindowInfo *pWindowInfo = &(BSHDR.window_info[0]); + + /* maxscl */ + for (i = 0; i < (int)(sizeof(pMetaHDRDynamic->data.maxscl)/sizeof(pMetaHDRDynamic->data.maxscl[0])); i++) + pWindowInfo->maxscl[i] = pMetaHDRDynamic->data.maxscl[0][i]; + + /* average_maxrgb */ + pWindowInfo->average_maxrgb = pMetaHDRDynamic->data.average_maxrgb[0]; + + /* distribution maxrgb */ + pWindowInfo->num_distribution_maxrgb_percentiles = pMetaHDRDynamic->data.num_maxrgb_percentiles[0]; + for (i = 0; i < pMetaHDRDynamic->data.num_maxrgb_percentiles[0]; i++) { + pWindowInfo->distribution_maxrgb_percentages[i] = pMetaHDRDynamic->data.maxrgb_percentages[0][i]; + pWindowInfo->distribution_maxrgb_percentiles[i] = pMetaHDRDynamic->data.maxrgb_percentiles[0][i]; + } + + /* tone mapping curve */ + pWindowInfo->tone_mapping_flag = pMetaHDRDynamic->data.tone_mapping.tone_mapping_flag[0]; + if (pMetaHDRDynamic->data.tone_mapping.tone_mapping_flag[0] != 0) { + pWindowInfo->knee_point_x = pMetaHDRDynamic->data.tone_mapping.knee_point_x[0]; + pWindowInfo->knee_point_y = pMetaHDRDynamic->data.tone_mapping.knee_point_y[0]; + + pWindowInfo->num_bezier_curve_anchors = pMetaHDRDynamic->data.tone_mapping.num_bezier_curve_anchors[0]; + for (i = 0; i < pMetaHDRDynamic->data.tone_mapping.num_bezier_curve_anchors[0]; i++) + pWindowInfo->bezier_curve_anchors[i] = pMetaHDRDynamic->data.tone_mapping.bezier_curve_anchors[0][i]; + } + + /* color saturation info */ + pWindowInfo->color_saturation_mapping_flag = pMetaHDRDynamic->data.color_saturation_mapping_flag[0]; + if (pMetaHDRDynamic->data.color_saturation_mapping_flag[0] != 0) { + pWindowInfo->color_saturation_weight = pMetaHDRDynamic->data.color_saturation_weight[0]; + } + } +#else // USE_FULL_ST2094_40 + BSHDR.targeted_system_display_maximum_luminance = pMetaHDRDynamic->data.display_maximum_luminance; + + /* save information on window-0 only */ + BSHDR.num_windows = 1; + { + ExynosVideoHdrWindowInfo *pWindowInfo = &(BSHDR.window_info[0]); + + /* maxscl */ + for (i = 0; i < (int)(sizeof(pMetaHDRDynamic->data.maxscl)/sizeof(pMetaHDRDynamic->data.maxscl[0])); i++) + pWindowInfo->maxscl[i] = pMetaHDRDynamic->data.maxscl[i]; + + /* distribution maxrgb */ + pWindowInfo->num_distribution_maxrgb_percentiles = pMetaHDRDynamic->data.num_maxrgb_percentiles; + for (i = 0; i < pMetaHDRDynamic->data.num_maxrgb_percentiles; i++) { + pWindowInfo->distribution_maxrgb_percentages[i] = pMetaHDRDynamic->data.maxrgb_percentages[i]; + pWindowInfo->distribution_maxrgb_percentiles[i] = pMetaHDRDynamic->data.maxrgb_percentiles[i]; + } + + /* tone mapping curve */ + pWindowInfo->tone_mapping_flag = pMetaHDRDynamic->data.tone_mapping.tone_mapping_flag; + if (pMetaHDRDynamic->data.tone_mapping.tone_mapping_flag != 0) { + pWindowInfo->knee_point_x = pMetaHDRDynamic->data.tone_mapping.knee_point_x; + pWindowInfo->knee_point_y = pMetaHDRDynamic->data.tone_mapping.knee_point_y; + + pWindowInfo->num_bezier_curve_anchors = pMetaHDRDynamic->data.tone_mapping.num_bezier_curve_anchors; + for (i = 0; i < pMetaHDRDynamic->data.tone_mapping.num_bezier_curve_anchors; i++) + pWindowInfo->bezier_curve_anchors[i] = pMetaHDRDynamic->data.tone_mapping.bezier_curve_anchors[i]; + } + } +#endif + } + } + } +#endif + + pEncOps->Set_HDRDynamicInfo(hMFCHandle, &BSHDR); + } + + return ; +} + +OMX_ERRORTYPE HevcCodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_HEVCENC_HANDLE *pMFCHevcHandle = &pHevcEnc->hMFCHevcHandle; + void *hMFCHandle = pMFCHevcHandle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + ExynosVideoEncOps *pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + ExynosVideoGeometry bufferConf; + + FunctionIn(); + + pVideoEnc->bEncDRCSync = OMX_TRUE; + + /* stream off */ + ret = HEVCCodecStop(pOMXComponent, INPUT_PORT_INDEX); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to HEVCCodecStop() about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_SignalWait(pVideoEnc->hEncDRCSyncEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pVideoEnc->hEncDRCSyncEvent); + + /* get input buffer geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + if (pInbufOps->Get_Geometry) { + if (pInbufOps->Get_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + /* clear information */ + pInbufOps->Clear_RegisteredBuffer(hMFCHandle); + pInbufOps->Cleanup_Buffer(hMFCHandle); + + /* set input buffer geometry */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + bufferConf.nFrameHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + bufferConf.nStride = ALIGN(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth, 16); + } else { + bufferConf.nFrameWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + bufferConf.nFrameHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + bufferConf.nStride = ALIGN(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight, 16); + } + + if (pInbufOps->Set_Geometry) { + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, MAX_INPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + /* header with IDR */ + if (pEncOps->Set_HeaderMode(hMFCHandle, VIDEO_FALSE) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set header mode", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + /* stream on */ + HEVCCodecStart(pOMXComponent, INPUT_PORT_INDEX); + + /* reset buffer queue */ + HEVCCodecEnqueueAllBuffer(pOMXComponent, INPUT_PORT_INDEX); + + /* clear timestamp */ + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + + /* reinitialize a value for reconfiguring CSC */ + pVideoEnc->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HEVCCodecSrcSetup( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_HEVCENC_HANDLE *pMFCHevcHandle = &pHevcEnc->hMFCHevcHandle; + void *hMFCHandle = pMFCHevcHandle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoEncOps *pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + ExynosVideoEncParam *pEncParam = NULL; + + ExynosVideoGeometry bufferConf; + OMX_U32 inputBufferNumber = 0; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pHevcEnc->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pHevcEnc->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_OSAL_SignalSet(pHevcEnc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + Set_HEVCEnc_Param(pExynosComponent); + + pEncParam = &pMFCHevcHandle->encParam; + if (pEncOps->Set_EncParam) { + if(pEncOps->Set_EncParam(pHevcEnc->hMFCHevcHandle.hMFCHandle, pEncParam) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set encParam", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + Print_HEVCEnc_Param(pEncParam); + + if (pMFCHevcHandle->bPrependSpsPpsToIdr == OMX_TRUE) { + if (pEncOps->Enable_PrependSpsPpsToIdr) + pEncOps->Enable_PrependSpsPpsToIdr(pHevcEnc->hMFCHevcHandle.hMFCHandle); + else + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Not supported control: Enable_PrependSpsPpsToIdr", pExynosComponent, __FUNCTION__); + } + + if ((pInputPort->eMetaDataType == METADATA_TYPE_GRAPHIC) && + ((pInputPort->bufferProcessType & BUFFER_SHARE) && + (pSrcInputData->buffer.addr[2] != NULL))) { + ExynosVideoMeta *pMeta = (ExynosVideoMeta *)pSrcInputData->buffer.addr[2]; + + if (pMeta->eType & VIDEO_INFO_TYPE_YSUM_DATA) { + if (VIDEO_ERROR_NONE == pEncOps->Enable_WeightedPrediction(hMFCHandle)) + pMFCHevcHandle->bWeightedPrediction = OMX_TRUE; + } + } + + if (pMFCHevcHandle->videoInstInfo.supportInfo.enc.bAdaptiveLayerBitrateSupport == VIDEO_TRUE) { + if (pHevcEnc->bUseTemporalLayerBitrateRatio == OMX_TRUE) { + pEncOps->Enable_AdaptiveLayerBitrate(pMFCHevcHandle->hMFCHandle, 0); /* Disable : Use layer bitrate from framework */ + } else { + pEncOps->Enable_AdaptiveLayerBitrate(pMFCHevcHandle->hMFCHandle, 1); /* Enable : Use adaptive layer bitrate from H/W */ + } + } + +#ifdef USE_ANDROID + HEVCCodecSetHdrInfo(pOMXComponent, pSrcInputData); +#endif + + if (pMFCHevcHandle->videoInstInfo.supportInfo.enc.bPrioritySupport == VIDEO_TRUE) + pEncOps->Set_Priority(hMFCHandle, pVideoEnc->nPriority); + + if (pEncParam->commonParam.bDisableDFR == VIDEO_TRUE) + pEncOps->Disable_DynamicFrameRate(pMFCHevcHandle->hMFCHandle, VIDEO_TRUE); + + /* input buffer info: only 3 config values needed */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eColorFormat = pEncParam->commonParam.FrameMap; + + { + OMX_S32 nTargetWidth, nTargetHeight; + + /* uses specified target size instead of size on output port */ + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + /* use specified resolution */ + nTargetWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nTargetHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nTargetWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nTargetHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = nTargetWidth; + bufferConf.nFrameHeight = nTargetHeight; + bufferConf.nStride = ALIGN(nTargetWidth, 16); + } else { + bufferConf.nFrameWidth = nTargetHeight; + bufferConf.nFrameHeight = nTargetWidth; + bufferConf.nStride = ALIGN(nTargetHeight, 16); + } + } + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + pInbufOps->Set_Shareable(hMFCHandle); + inputBufferNumber = MAX_INPUTBUFFER_NUM_DYNAMIC; + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry) { + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, inputBufferNumber) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pInputPort->bufferProcessType & BUFFER_SHARE) && + (pInputPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + /* data buffer */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.bConfiguredMFCSrc = OMX_TRUE; + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HEVCCodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_HEVCENC_HANDLE *pMFCHevcHandle = &pHevcEnc->hMFCHevcHandle; + void *hMFCHandle = pMFCHevcHandle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + unsigned int nDataLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + int i, nOutBufSize = 0, nOutputBufferCnt = 0; + + FunctionIn(); + + nOutBufSize = pOutputPort->portDefinition.nBufferSize; + if ((pOutputPort->bufferProcessType & BUFFER_COPY) || + (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nOutBufSize = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * + pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nOutBufSize = Exynos_OSAL_GetOutBufferSize(pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.nBufferSize); +#endif + +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) { + if (nOutBufSize > CUSTOM_LIMITED_DRM_OUTPUT_BUFFER_SIZE) { + nOutBufSize = CUSTOM_LIMITED_DRM_OUTPUT_BUFFER_SIZE; + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] set limited output buffer size to MFC dst: %d", + pExynosComponent, __FUNCTION__, nOutBufSize); + } + } +#endif + } + + /* set geometry for output (dst) */ + if (pOutbufOps->Set_Geometry) { + /* output buffer info: only 2 config values needed */ + bufferConf.eCompressionFormat = VIDEO_CODING_HEVC; + bufferConf.nSizeImage = nOutBufSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + + if (pOutbufOps->Set_Geometry(pHevcEnc->hMFCHevcHandle.hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pOutputPort->bufferProcessType & BUFFER_COPY) + nOutputBufferCnt = MFC_OUTPUT_BUFFER_NUM_MAX; + else + nOutputBufferCnt = pOutputPort->portDefinition.nBufferCountActual; + + if (pOutbufOps->Setup(pHevcEnc->hMFCHevcHandle.hMFCHandle, nOutputBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + nAllocLen[0] = nOutBufSize; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, MFC_OUTPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Allocate_CodecBuffers for output", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + /* Enqueue output buffer */ + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoEnc->pMFCEncOutputBuffer[i]->fd, + pVideoEnc->pMFCEncOutputBuffer[i]->bufferSize, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + NULL); + } + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /* Register output buffer */ + /*************/ + /* TBD */ + /*************/ + } + + pHevcEnc->hMFCHevcHandle.bConfiguredMFCDst = OMX_TRUE; + + if (HEVCCodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nParamIndex %x", pExynosComponent, __FUNCTION__, (int)nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoHevc: + { + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = (OMX_VIDEO_PARAM_HEVCTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_HEVCTYPE *pSrcHevcComponent = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstHevcComponent, sizeof(OMX_VIDEO_PARAM_HEVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstHevcComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcHevcComponent = &pHevcEnc->HevcComponent[pDstHevcComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstHevcComponent) + nOffset, + ((char *)pSrcHevcComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_HEVCTYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_HEVC_DRM_ENC_ROLE); + else + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_HEVC_ENC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + OMX_VIDEO_PARAM_HEVCTYPE *pSrcHevcComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcHevcComponent = &pHevcEnc->HevcComponent[pDstProfileLevel->nPortIndex]; + + pDstProfileLevel->eProfile = pSrcHevcComponent->eProfile; + pDstProfileLevel->eLevel = pSrcHevcComponent->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pHevcEnc->errorCorrectionType[OUTPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pHevcEnc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pHevcEnc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pHevcEnc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pHevcEnc->qpRangeP.nMaxQP; + pQpRange->qpRangeB.nMinQP = pHevcEnc->qpRangeB.nMinQP; + pQpRange->qpRangeB.nMaxQP = pHevcEnc->qpRangeB.nMaxQP; + } + break; + case OMX_IndexParamVideoHevcEnableTemporalSVC: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *pDstEnableTemporalSVC = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstEnableTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstEnableTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstEnableTemporalSVC->bEnableTemporalSVC = pHevcEnc->hMFCHevcHandle.bTemporalSVC; + } + break; + case OMX_IndexParamVideoEnableRoiInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *pDstEnableRoiInfo = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstEnableRoiInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstEnableRoiInfo->bEnableRoiInfo = pHevcEnc->hMFCHevcHandle.bRoiInfo; + } + break; + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pEnablePVC->nU32 = pVideoEnc->bPVCMode; + } + break; + case OMX_IndexParamNumberRefPframes: + { + OMX_PARAM_U32TYPE *pNumberRefPframes = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pNumberRefPframes, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pNumberRefPframes->nU32 = pHevcEnc->hMFCHevcHandle.nRefForPframes; + } + break; + case OMX_IndexParamVideoEnableGPB: + { + OMX_CONFIG_BOOLEANTYPE *pEnableGPB = (OMX_CONFIG_BOOLEANTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnableGPB, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pEnableGPB->bEnabled = pHevcEnc->hMFCHevcHandle.bGPBEnable; + } + break; + case OMX_IndexParamVideoChromaQP: + { + OMX_VIDEO_PARAM_CHROMA_QP_OFFSET *pChromaQP = (OMX_VIDEO_PARAM_CHROMA_QP_OFFSET *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pChromaQP, sizeof(OMX_VIDEO_PARAM_CHROMA_QP_OFFSET)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pChromaQP->nCr = pHevcEnc->chromaQPOffset.nCr; + pChromaQP->nCb = pHevcEnc->chromaQPOffset.nCb; + } + break; + case OMX_IndexParamVideoDisableHBEncoding: + { + OMX_CONFIG_BOOLEANTYPE *pDisableHBEncoding = (OMX_CONFIG_BOOLEANTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDisableHBEncoding, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pDisableHBEncoding->bEnabled = pHevcEnc->bDisableHBEncoding; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamAndroidVideoTemporalLayering: + { + OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pTemporalLayering = (OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pTemporalLayering, sizeof(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pTemporalLayering->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) { + pTemporalLayering->eSupportedPatterns = OMX_VIDEO_AndroidTemporalLayeringPatternNone; + pTemporalLayering->nLayerCountMax = 1; /* not supported */ + pTemporalLayering->nBLayerCountMax = 0; + pTemporalLayering->ePattern = OMX_VIDEO_AndroidTemporalLayeringPatternNone; + } else { + pTemporalLayering->eSupportedPatterns = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; + + if (pHevcEnc->hMFCHevcHandle.bTemporalSVC == OMX_TRUE) { + pTemporalLayering->nLayerCountMax = pHevcEnc->nMaxTemporalLayerCount; + pTemporalLayering->nBLayerCountMax = pHevcEnc->nMaxTemporalLayerCountForB; + pTemporalLayering->ePattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; + } else { + pTemporalLayering->nLayerCountMax = OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; + pTemporalLayering->nBLayerCountMax = OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS_FOR_B; + pTemporalLayering->ePattern = OMX_VIDEO_AndroidTemporalLayeringPatternNone; + + if (pHevcEnc->bDisableHBEncoding == OMX_TRUE) { + pTemporalLayering->nBLayerCountMax = 0; + } + } + } + + pTemporalLayering->nPLayerCountActual = pHevcEnc->nTemporalLayerCount; + pTemporalLayering->nBLayerCountActual = pHevcEnc->nTemporalLayerCountForB; + + pTemporalLayering->bBitrateRatiosSpecified = pHevcEnc->bUseTemporalLayerBitrateRatio; + if (pTemporalLayering->bBitrateRatiosSpecified == OMX_TRUE) { + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) + pTemporalLayering->nBitrateRatios[i] = (pHevcEnc->nTemporalLayerBitrateRatio[i] << 16); + } + } + break; +#endif + default: + ret = Exynos_OMX_VideoEncodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoHevc: + { + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = NULL; + OMX_VIDEO_PARAM_HEVCTYPE *pSrcHevcComponent = (OMX_VIDEO_PARAM_HEVCTYPE *)pComponentParameterStructure; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcHevcComponent, sizeof(OMX_VIDEO_PARAM_HEVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcHevcComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstHevcComponent = &pHevcEnc->HevcComponent[pSrcHevcComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstHevcComponent) + nOffset, + ((char *)pSrcHevcComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_HEVCTYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_HEVC_ENC_ROLE) || + !Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_HEVC_DRM_ENC_ROLE)) { + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingHEVC; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstHevcComponent = &pHevcEnc->HevcComponent[pSrcProfileLevel->nPortIndex]; + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstHevcComponent->eProfile = pSrcProfileLevel->eProfile; + pDstHevcComponent->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pHevcEnc->errorCorrectionType[OUTPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP) || + (pQpRange->qpRangeB.nMinQP > pQpRange->qpRangeB.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d], B[min:%d, max:%d])", __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP, + pQpRange->qpRangeB.nMinQP, pQpRange->qpRangeB.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pHevcEnc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pHevcEnc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pHevcEnc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + pHevcEnc->qpRangeB.nMinQP = pQpRange->qpRangeB.nMinQP; + pHevcEnc->qpRangeB.nMaxQP = pQpRange->qpRangeB.nMaxQP; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamPrependSPSPPSToIDR: + { + + ret = Exynos_OSAL_SetPrependSPSPPSToIDR(pComponentParameterStructure, &(pHevcEnc->hMFCHevcHandle.bPrependSpsPpsToIdr)); + } + break; + case OMX_IndexParamAndroidVideoTemporalLayering: + { + OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pTemporalLayering = (OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pTemporalLayering, sizeof(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pTemporalLayering->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pTemporalLayering->ePattern != OMX_VIDEO_AndroidTemporalLayeringPatternNone) { + /* ENABLE */ + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Temporal SVC is not supported", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + + if (pTemporalLayering->nLayerCountMax > OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] total layer : Max value(%d) > supportable Max value(%d)", + pExynosComponent, __FUNCTION__, pTemporalLayering->nLayerCountMax, OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pTemporalLayering->nBLayerCountMax > OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS_FOR_B) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] B layer : Max value(%d) > supportable Max value(%d)", + pExynosComponent, __FUNCTION__, pTemporalLayering->nBLayerCountMax, OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS_FOR_B); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.bTemporalSVC = OMX_TRUE; + pHevcEnc->nMaxTemporalLayerCount = pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual; + pHevcEnc->nMaxTemporalLayerCountForB = pTemporalLayering->nBLayerCountActual; + pHevcEnc->nTemporalLayerCount = pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual; + pHevcEnc->nTemporalLayerCountForB = pTemporalLayering->nBLayerCountActual; + + if (pHevcEnc->bDisableHBEncoding) { + pHevcEnc->nMaxTemporalLayerCountForB = 0; + pHevcEnc->nTemporalLayerCountForB = 0; + } + + pHevcEnc->bUseTemporalLayerBitrateRatio = pTemporalLayering->bBitrateRatiosSpecified; + if (pHevcEnc->bUseTemporalLayerBitrateRatio == OMX_TRUE) { + for (i = 0; i < (int)pHevcEnc->nMaxTemporalLayerCount; i++) + pHevcEnc->nTemporalLayerBitrateRatio[i] = (pTemporalLayering->nBitrateRatios[i] >> 16); + } + + /* HIGH_SPEED_ENCODING */ + if (pHevcEnc->nTemporalLayerCountForB > 0) { + int minRequiredInputs = pow(2, pHevcEnc->nTemporalLayerCount - 1); + if (minRequiredInputs > pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.nBufferCountActual) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Temporal Layering with B-frame, increase InputBufferNum(%d)", pExynosComponent, __FUNCTION__, minRequiredInputs); + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.nBufferCountActual = minRequiredInputs; + } + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Max(%d), B-Max(%d), layer(%d), B-layer(%d)", pExynosComponent, __FUNCTION__, + pHevcEnc->nMaxTemporalLayerCount, pHevcEnc->nMaxTemporalLayerCountForB, + pHevcEnc->nTemporalLayerCount, pHevcEnc->nTemporalLayerCountForB); + } else { + /* DISABLE */ + pHevcEnc->hMFCHevcHandle.bTemporalSVC = OMX_FALSE; + pHevcEnc->nMaxTemporalLayerCount = 0; + pHevcEnc->nMaxTemporalLayerCountForB = 0; + pHevcEnc->nTemporalLayerCount = 0; + pHevcEnc->nTemporalLayerCountForB = 0; + pHevcEnc->bUseTemporalLayerBitrateRatio = OMX_FALSE; + Exynos_OSAL_Memset(pHevcEnc->nTemporalLayerBitrateRatio, 0, sizeof(pHevcEnc->nTemporalLayerBitrateRatio)); + } + } + break; +#endif + case OMX_IndexParamVideoHevcEnableTemporalSVC: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *pSrcEnableTemporalSVC = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *)pComponentParameterStructure; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition); + int i; + + ret = Exynos_OMX_Check_SizeVersion(pSrcEnableTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcEnableTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) && + (pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Temporal SVC is not supported", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_TRUE) && + (pHevcEnc->hMFCHevcHandle.bTemporalSVC == OMX_FALSE)) { + /* ENABLE : not initialized yet */ + pHevcEnc->hMFCHevcHandle.bTemporalSVC = OMX_TRUE; + pHevcEnc->nMaxTemporalLayerCount = OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; + pHevcEnc->nMaxTemporalLayerCountForB = OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS_FOR_B; + pHevcEnc->nTemporalLayerCount = 1; + pHevcEnc->nTemporalLayerCountForB = 0; + pHevcEnc->bUseTemporalLayerBitrateRatio = OMX_TRUE; + pHevcEnc->nTemporalLayerBitrateRatio[0] = pPortDef->format.video.nBitrate; + } else if (pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_FALSE) { + /* DISABLE */ + pHevcEnc->hMFCHevcHandle.bTemporalSVC = OMX_FALSE; /* DISABLE */ + pHevcEnc->nMaxTemporalLayerCount = 0; + pHevcEnc->nMaxTemporalLayerCountForB = 0; + pHevcEnc->nTemporalLayerCount = 0; + pHevcEnc->nTemporalLayerCountForB = 0; + pHevcEnc->bUseTemporalLayerBitrateRatio = OMX_FALSE; + Exynos_OSAL_Memset(pHevcEnc->nTemporalLayerBitrateRatio, 0, sizeof(pHevcEnc->nTemporalLayerBitrateRatio)); + } + } + break; + case OMX_IndexParamVideoEnableRoiInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *pSrcEnableRoiInfo = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pSrcEnableRoiInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bRoiInfoSupport == VIDEO_FALSE) && + (pSrcEnableRoiInfo->bEnableRoiInfo == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Roi Info is not supported", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.bRoiInfo = pSrcEnableRoiInfo->bEnableRoiInfo; + } + break; + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bPVCSupport == VIDEO_FALSE) && + (pEnablePVC->nU32 != 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] PVC mode is not supported", pExynosComponent, __FUNCTION__); + } + + pVideoEnc->bPVCMode = (pEnablePVC->nU32 != 0)? OMX_TRUE:OMX_FALSE; + } + break; + case OMX_IndexParamNumberRefPframes: + { + OMX_PARAM_U32TYPE *pNumberRefPframes = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pNumberRefPframes, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.nRefForPframes = pNumberRefPframes->nU32; + } + break; + case OMX_IndexParamVideoEnableGPB: + { + OMX_CONFIG_BOOLEANTYPE *pEnableGPB = (OMX_CONFIG_BOOLEANTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnableGPB, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.bGPBEnable = pEnableGPB->bEnabled; + } + break; + case OMX_IndexParamVideoChromaQP: + { + OMX_VIDEO_PARAM_CHROMA_QP_OFFSET *pChromaQP = (OMX_VIDEO_PARAM_CHROMA_QP_OFFSET *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pChromaQP, sizeof(OMX_VIDEO_PARAM_CHROMA_QP_OFFSET)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pChromaQP->nCr < -12) || (pChromaQP->nCr > 12)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] nCr 0x%x is invalid [min:-12, max:12]", pExynosComponent, __FUNCTION__, pChromaQP->nCr); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if ((pChromaQP->nCb < -12) || (pChromaQP->nCb > 12)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] nCb 0x%x is invalid [min:-12, max:12]", pExynosComponent, __FUNCTION__, pChromaQP->nCb); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->chromaQPOffset.nCr = pChromaQP->nCr; + pHevcEnc->chromaQPOffset.nCb = pChromaQP->nCb; + } + break; + case OMX_IndexParamVideoDisableHBEncoding: + { + OMX_CONFIG_BOOLEANTYPE *pDisableHBEncoding = (OMX_CONFIG_BOOLEANTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDisableHBEncoding, sizeof(OMX_CONFIG_BOOLEANTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pHevcEnc->bDisableHBEncoding = pDisableHBEncoding->bEnabled; + } + break; + default: + ret = Exynos_OMX_VideoEncodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pHevcEnc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pHevcEnc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pHevcEnc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pHevcEnc->qpRangeP.nMaxQP; + pQpRange->qpRangeB.nMinQP = pHevcEnc->qpRangeB.nMinQP; + pQpRange->qpRangeB.nMaxQP = pHevcEnc->qpRangeB.nMaxQP; + } + break; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pDstTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pComponentConfigStructure; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstTemporalSVC->nKeyFrameInterval = pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].nKeyFrameInterval; + pDstTemporalSVC->nMinQuantizer = pHevcEnc->qpRangeI.nMinQP; + pDstTemporalSVC->nMaxQuantizer = pHevcEnc->qpRangeI.nMaxQP; + pDstTemporalSVC->nTemporalLayerCount = pHevcEnc->nTemporalLayerCount; + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) + pDstTemporalSVC->nTemporalLayerBitrateRatio[i] = pHevcEnc->nTemporalLayerBitrateRatio[i]; + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigVideoHdrStaticInfo: + ret = Exynos_OSAL_GetConfig(hComponent, nIndex, pComponentConfigStructure); + break; +#endif + default: + ret = Exynos_OMX_VideoEncodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoIntraPeriod: + { + pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].nKeyFrameInterval = *((OMX_U32 *)pComponentConfigStructure); + ret = OMX_ErrorNone; + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP) || + (pQpRange->qpRangeB.nMinQP > pQpRange->qpRangeB.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d], B[min:%d, max:%d])", + pExynosComponent, __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP, + pQpRange->qpRangeB.nMinQP, pQpRange->qpRangeB.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_FALSE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] only I-frame's QP range is applied", pExynosComponent, __FUNCTION__); + + pHevcEnc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pHevcEnc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pHevcEnc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pHevcEnc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + pHevcEnc->qpRangeB.nMinQP = pQpRange->qpRangeB.nMinQP; + pHevcEnc->qpRangeB.nMaxQP = pQpRange->qpRangeB.nMaxQP; + } + break; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pSrcTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pComponentConfigStructure; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.bTemporalSVC == OMX_FALSE) || + (pSrcTemporalSVC->nTemporalLayerCount > OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].nKeyFrameInterval = pSrcTemporalSVC->nKeyFrameInterval; + + pHevcEnc->qpRangeI.nMinQP = pSrcTemporalSVC->nMinQuantizer; + pHevcEnc->qpRangeI.nMaxQP = pSrcTemporalSVC->nMaxQuantizer; + + pHevcEnc->nTemporalLayerCount = pSrcTemporalSVC->nTemporalLayerCount; + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) + pHevcEnc->nTemporalLayerBitrateRatio[i] = pSrcTemporalSVC->nTemporalLayerBitrateRatio[i]; + } + break; + case OMX_IndexConfigVideoRoiInfo: + { + EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *pRoiInfo = (EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *)pComponentConfigStructure; + + if (pRoiInfo->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pHevcEnc->hMFCHevcHandle.bRoiInfo == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] RoiInfo is not enabled", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((pRoiInfo->bUseRoiInfo == OMX_TRUE) && + ((pRoiInfo->nRoiMBInfoSize <= 0) || (pRoiInfo->pRoiMBInfo == NULL))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] parameter is invalid : nRoiMBInfoSize(%d)/pRoiMBInfo(%p)", + pExynosComponent, __FUNCTION__, pRoiInfo->nRoiMBInfoSize, pRoiInfo->pRoiMBInfo); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + case OMX_IndexConfigIFrameRatio: + { + OMX_PARAM_U32TYPE *pIFrameRatio = (OMX_PARAM_U32TYPE *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pIFrameRatio, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pIFrameRatio->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bIFrameRatioSupport == VIDEO_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] I-Frame ratio feature is not supported", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorNoneExpiration; + goto EXIT; + } + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigAndroidVideoTemporalLayering: + { + OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *pTemporalLayering = (OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pTemporalLayering, sizeof(OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pTemporalLayering->nPortIndex != OUTPUT_PORT_INDEX) || + (pHevcEnc->hMFCHevcHandle.bTemporalSVC == OMX_FALSE)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pTemporalLayering->ePattern == OMX_VIDEO_AndroidTemporalLayeringPatternNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] can not disable TemporalSVC while encoding", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (((pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual) > pHevcEnc->nMaxTemporalLayerCount) || + ((pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual) == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] layer count is invalid(MAX(%d), layer(%d), B-layer(%d))", + pExynosComponent, __FUNCTION__, + pHevcEnc->nMaxTemporalLayerCount, + pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual, + pTemporalLayering->nBLayerCountActual); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->nTemporalLayerCount = pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual; + if (pHevcEnc->bDisableHBEncoding == OMX_TRUE) { + pHevcEnc->nTemporalLayerCountForB = 0; + } else { + pHevcEnc->nTemporalLayerCountForB = pTemporalLayering->nBLayerCountActual; + } + + pHevcEnc->bUseTemporalLayerBitrateRatio = pTemporalLayering->bBitrateRatiosSpecified; + if (pHevcEnc->bUseTemporalLayerBitrateRatio == OMX_TRUE) { + for (i = 0; i < (int)pHevcEnc->nMaxTemporalLayerCount; i++) + pHevcEnc->nTemporalLayerBitrateRatio[i] = (pTemporalLayering->nBitrateRatios[i] >> 16); + } else { + Exynos_OSAL_Memset(pHevcEnc->nTemporalLayerBitrateRatio, 0, sizeof(pHevcEnc->nTemporalLayerBitrateRatio)); + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Max(%d), layer(%d), B-layer(%d)", pExynosComponent, __FUNCTION__, + pHevcEnc->nMaxTemporalLayerCount, pHevcEnc->nTemporalLayerCount, pHevcEnc->nTemporalLayerCountForB); + } + break; + case OMX_IndexConfigVideoHdrStaticInfo: + ret = Exynos_OSAL_SetConfig(hComponent, nIndex, pComponentConfigStructure); + break; +#endif + default: + ret = Exynos_OMX_VideoEncodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + OMX_PTR pDynamicConfigCMD = NULL; + pDynamicConfigCMD = Exynos_OMX_MakeDynamicConfig(nIndex, pComponentConfigStructure); + Exynos_OSAL_Queue(&pExynosComponent->dynamicConfigQ, (void *)pDynamicConfigCMD); + } + + if (ret == (OMX_ERRORTYPE)OMX_ErrorNoneExpiration) + ret = OMX_ErrorNone; + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_TEMPORALSVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigVideoTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_HEVC_ENABLE_TEMPORALSVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoHevcEnableTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_ROIINFO) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigVideoRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_ENABLE_ROIINFO) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoEnableRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_PVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoEnablePVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_IFRAME_RATIO) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigIFrameRatio; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_REF_NUM_PFRAMES) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamNumberRefPframes; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_ENABLE_GPB) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoEnableGPB; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_ANDROID + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_PREPEND_SPSPPS_TO_IDR) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamPrependSPSPPSToIDR; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_HDR_STATIC_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoHdrStaticInfo; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + ret = Exynos_OMX_VideoEncodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || (cRole == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_HEVC_ENC_ROLE); + else + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_HEVC_DRM_ENC_ROLE); + + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_HEVCEnc_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + OMX_COLOR_FORMATTYPE eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; + + ExynosVideoInstInfo *pVideoInstInfo = &(pHevcEnc->hMFCHevcHandle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + + FunctionIn(); + + pHevcEnc->hMFCHevcHandle.bConfiguredMFCSrc = OMX_FALSE; + pHevcEnc->hMFCHevcHandle.bConfiguredMFCDst = OMX_FALSE; + pVideoEnc->bFirstInput = OMX_TRUE; + pVideoEnc->bFirstOutput = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + if (pInputPort->eMetaDataType != METADATA_TYPE_DISABLED) { + /* metadata buffer */ + pInputPort->bufferProcessType = BUFFER_SHARE; + +#ifdef USE_ANDROID + if ((pInputPort->eMetaDataType == METADATA_TYPE_DATA) && + (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque)) { + pInputPort->eMetaDataType = METADATA_TYPE_GRAPHIC; /* AndoridOpaque means GrallocSource */ + pInputPort->bufferProcessType = BUFFER_COPY; /* will determine a process type after getting a hal format at handle */ + } +#else + if (pInputPort->eMetaDataType == METADATA_TYPE_UBM_BUFFER) { + pInputPort->bufferProcessType = BUFFER_COPY; + } +#endif + } else { + /* data buffer */ + pInputPort->bufferProcessType = BUFFER_COPY; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pInputPort->portDefinition.format.video.nFrameWidth, + pInputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.format.video.nBitrate, + pInputPort->portDefinition.format.video.xFramerate); + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pInputPort->portDefinition.format.video.xFramerate; + + /* HEVC Codec Open */ + ret = HEVCCodecOpen(pHevcEnc, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + Exynos_SetPlaneToPort(pOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + + Exynos_OSAL_SemaphoreCreate(&pInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_OSAL_SemaphoreCreate(&pOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pHevcEnc->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pHevcEnc->hSourceStartEvent); + pHevcEnc->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pHevcEnc->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pHevcEnc->hDestinationOutStartEvent); + + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pHevcEnc->hMFCHevcHandle.indexTimestamp = 0; + pHevcEnc->hMFCHevcHandle.outputIndexTimestamp = 0; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pHevcEnc->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) { + pVideoEnc->csc_handle = csc_init(CSC_METHOD_HW); + csc_set_hw_property(pVideoEnc->csc_handle, CSC_HW_PROPERTY_FIXED_NODE, 2); + csc_set_hw_property(pVideoEnc->csc_handle, CSC_HW_PROPERTY_MODE_DRM, 1); + } else { + pVideoEnc->csc_handle = csc_init(csc_method); + } + if (pVideoEnc->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVideoEnc->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_HEVCEnc_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoEnc != NULL) { + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + + if (pVideoEnc->csc_handle != NULL) { + csc_deinit(pVideoEnc->csc_handle); + pVideoEnc->csc_handle = NULL; + } + + if (pHevcEnc != NULL) { + Exynos_OSAL_QueueTerminate(&pHevcEnc->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pHevcEnc->hDestinationInStartEvent); + pHevcEnc->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pHevcEnc->hDestinationOutStartEvent); + pHevcEnc->hDestinationOutStartEvent = NULL; + pHevcEnc->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pHevcEnc->hSourceStartEvent); + pHevcEnc->hSourceStartEvent = NULL; + pHevcEnc->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + + if (pHevcEnc != NULL) { + HEVCCodecClose(pHevcEnc); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_SrcIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE inputColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncOps *pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt, nConfigCnt; + + FunctionIn(); + +#ifdef USE_ANDROID + { + int fps = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + + if (pVideoEnc->pPerfHandle != NULL) + Exynos_OSAL_Performance(pVideoEnc->pPerfHandle, pHevcEnc->hMFCHevcHandle.indexTimestamp, fps); + } +#endif + + if (pHevcEnc->hMFCHevcHandle.bConfiguredMFCSrc == OMX_FALSE) { + ret = HEVCCodecSrcSetup(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to HEVCCodecSrcSetup(0x%x)", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + } + + if (pHevcEnc->hMFCHevcHandle.bConfiguredMFCDst == OMX_FALSE) { + ret = HEVCCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to HEVCCodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + } + + nConfigCnt = Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ); + if (nConfigCnt > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] has config message(%d)", pExynosComponent, __FUNCTION__, nConfigCnt); + while (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + Change_HEVCEnc_Param(pExynosComponent); + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] all config messages were handled", pExynosComponent, __FUNCTION__); + } + + /* DRC on Executing state through OMX_IndexConfigCommonOutputSize */ + if (pVideoEnc->bEncDRC == OMX_TRUE) { + ret = HevcCodecUpdateResolution(pOMXComponent); + pVideoEnc->bEncDRC = OMX_FALSE; + goto EXIT; + } + + if ((pSrcInputData->dataLen > 0) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + pExynosComponent->timeStamp[pHevcEnc->hMFCHevcHandle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->bTimestampSlotUsed[pHevcEnc->hMFCHevcHandle.indexTimestamp] = OMX_TRUE; + pExynosComponent->nFlags[pHevcEnc->hMFCHevcHandle.indexTimestamp] = pSrcInputData->nFlags; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pHevcEnc->hMFCHevcHandle.indexTimestamp); + + pEncOps->Set_FrameTag(hMFCHandle, pHevcEnc->hMFCHevcHandle.indexTimestamp); + pHevcEnc->hMFCHevcHandle.indexTimestamp++; + pHevcEnc->hMFCHevcHandle.indexTimestamp %= MAX_TIMESTAMP; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + { + OMX_S32 nTargetWidth, nTargetHeight; + + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + nTargetWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nTargetHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nTargetWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nTargetHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + /* rotation */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + nTargetWidth, nTargetHeight, + nDataLen, nAllocLen); + } else { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + nTargetHeight, nTargetWidth, + nDataLen, nAllocLen); + } + } + + if (pInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + if (pSrcInputData->dataLen == 0) { + for (i = 0; i < nPlaneCnt; i++) + nDataLen[i] = 0; + } else { + /* when having valid input */ + if (pSrcInputData->buffer.addr[2] != NULL) { + ExynosVideoMeta *pVideoMeta = (ExynosVideoMeta *)pSrcInputData->buffer.addr[2]; + + /* y-sum */ + if (pHevcEnc->hMFCHevcHandle.bWeightedPrediction == OMX_TRUE) { + if (pVideoMeta->eType & VIDEO_INFO_TYPE_YSUM_DATA) { + codecReturn = pEncOps->Set_YSumData(hMFCHandle, pVideoMeta->data.enc.sYsumData.high, + pVideoMeta->data.enc.sYsumData.low); + if (codecReturn != VIDEO_ERROR_NONE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Failed to Set_YSumData()", pExynosComponent, __FUNCTION__); + } + } + + if ((pVideoMeta->eType & VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT) && + ((pVideoEnc->surfaceFormat >= OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC) && + (pVideoEnc->surfaceFormat <= OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L80))) { + int nOMXFormat = OMX_COLOR_FormatUnused; + int nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + + nOMXFormat = Exynos_OSAL_HAL2OMXColorFormat(pVideoMeta->nPixelFormat); + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nVideoFormat = Exynos_OSAL_OMX2VideoFormat(nOMXFormat, pInputPort->ePlaneType); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + if (pEncOps->Set_ActualFormat(hMFCHandle, nVideoFormat) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] set change format is failed", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] video format is changed: %d", pExynosComponent, __FUNCTION__, nVideoFormat); + } + } + } + } + + /* update hdr dynamic info */ + if (pHevcEnc->hMFCHevcHandle.bHDRDynamicInfo == OMX_TRUE) + HEVCCodecUpdateHdrDynamicInfo(pOMXComponent, pSrcInputData); + } + + if ((pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bDropControlSupport == VIDEO_TRUE) && + (pVideoEnc->bDropControl == OMX_TRUE)) { + pEncOps->Set_DropControl(hMFCHandle, VIDEO_TRUE); + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + + HEVCCodecStart(pOMXComponent, INPUT_PORT_INDEX); + if (pHevcEnc->bSourceStart == OMX_FALSE) { + pHevcEnc->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pHevcEnc->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + if ((pHevcEnc->bDestinationStart == OMX_FALSE) && + (pHevcEnc->hMFCHevcHandle.bConfiguredMFCDst == OMX_TRUE)) { + pHevcEnc->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pHevcEnc->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pHevcEnc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_SrcOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else { + if (pVideoEnc->bEncDRCSync == OMX_TRUE) { + Exynos_OSAL_SignalSet(pVideoEnc->hEncDRCSyncEvent); + pVideoEnc->bEncDRCSync = OMX_FALSE; + } + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->allocSize = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->pPrivate = NULL; + } else { + int plane = 0, nPlaneCnt; + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pSrcOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pSrcOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pSrcOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == + pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]) { + pVideoEnc->pMFCEncInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoEnc->pMFCEncInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_DstIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + unsigned int nDataLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + nAllocLen[0] = pOutputPort->portDefinition.nBufferSize; + if ((pOutputPort->bufferProcessType & BUFFER_COPY) || + (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nAllocLen[0] = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nAllocLen[0] = Exynos_OSAL_GetOutBufferSize(pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.nBufferSize); +#endif + +#ifdef USE_SMALL_SECURE_MEMORY + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) { + if (nAllocLen[0] > CUSTOM_LIMITED_DRM_OUTPUT_BUFFER_SIZE) { + nAllocLen[0] = CUSTOM_LIMITED_DRM_OUTPUT_BUFFER_SIZE; + } + } +#endif + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + pDstInputData->bufferHeader); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + + HEVCCodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_DstOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + void *hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + + ExynosVideoEncOps *pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + ExynosVideoEncBufferOps *pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_S32 indexTimestamp = 0; + + FunctionIn(); + + if (pHevcEnc->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO)", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + pDstOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pDstOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + + pDstOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + pDstOutputData->dataLen = pVideoBuffer->planes[0].dataSize; + pDstOutputData->remainDataLen = pVideoBuffer->planes[0].dataSize; + pDstOutputData->usedDataLen = 0; + + pDstOutputData->pPrivate = pVideoBuffer; + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoEnc->pMFCEncOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + if (pVideoEnc->bFirstOutput == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] codec specific data is generated", pExynosComponent, __FUNCTION__); + pDstOutputData->timeStamp = 0; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + pVideoEnc->bFirstOutput = OMX_TRUE; + } else { + indexTimestamp = pEncOps->Get_FrameTag(pHevcEnc->hMFCHevcHandle.hMFCHandle); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d(0x%x)", pExynosComponent, __FUNCTION__, indexTimestamp, indexTimestamp); + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp == INDEX_AFTER_DRC) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid frame, buffer will be discard and reused", pExynosComponent, __FUNCTION__); + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + + if (indexTimestamp == INDEX_HEADER_DATA) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] codec specific data is generated", pExynosComponent, __FUNCTION__); + indexTimestamp = pHevcEnc->hMFCHevcHandle.outputIndexTimestamp; + pDstOutputData->timeStamp = pExynosComponent->nFlags[indexTimestamp]; + pDstOutputData->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, frameType: %d, dataLen: %d, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pVideoBuffer->frameType, pDstOutputData->dataLen, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + ret = OMX_ErrorNone; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Tag(%x) is invalid. changes to use outputIndexTimestamp(%d)", + pExynosComponent, __FUNCTION__, + indexTimestamp, pHevcEnc->hMFCHevcHandle.outputIndexTimestamp); + indexTimestamp = pHevcEnc->hMFCHevcHandle.outputIndexTimestamp; + } else { + pHevcEnc->hMFCHevcHandle.outputIndexTimestamp = indexTimestamp; + } + + /* In case of Video buffer batch mode, use timestamp from MFC device driver */ + if (pVideoBuffer->timestamp != 0) + pDstOutputData->timeStamp = pVideoBuffer->timestamp; + else + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + + pExynosComponent->bTimestampSlotUsed[indexTimestamp] = OMX_FALSE; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp]; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + } + + if (pVideoBuffer->frameType == VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, frameType: %d, dataLen: %d, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pVideoBuffer->frameType, pDstOutputData->dataLen, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pExynosOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] got end of stream", pExynosComponent, __FUNCTION__); + + if (pExynosComponent->bBehaviorEOS == OMX_FALSE) + pDstOutputData->remainDataLen = 0; + else + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_srcInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || + (!CHECK_PORT_POPULATED(pInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = Exynos_HEVCEnc_SrcIn(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_srcOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || + (!CHECK_PORT_POPULATED(pInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if ((pHevcEnc->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pInputPort))) { + Exynos_OSAL_SignalWait(pHevcEnc->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pHevcEnc->hSourceStartEvent); + } + + ret = Exynos_HEVCEnc_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_dstInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pHevcEnc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pHevcEnc->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pHevcEnc->hDestinationInStartEvent); + } + + if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pHevcEnc->bypassBufferInfoQ) > 0) { + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pHevcEnc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if (pHevcEnc->hMFCHevcHandle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_HEVCEnc_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCEnc_dstOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pHevcEnc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pHevcEnc->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pHevcEnc->hDestinationOutStartEvent); + } + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + if (Exynos_OSAL_GetElemNum(&pHevcEnc->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pHevcEnc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_HEVCEnc_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + OMX_BOOL bSecureMode = OMX_FALSE; + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || + (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_HEVC_ENC, componentName) == 0) { + bSecureMode = OMX_FALSE; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_HEVC_DRM_ENC, componentName) == 0) { + bSecureMode = OMX_TRUE; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = (bSecureMode == OMX_TRUE)? HW_VIDEO_ENC_SECURE_CODEC:HW_VIDEO_ENC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pHevcEnc = Exynos_OSAL_Malloc(sizeof(EXYNOS_HEVCENC_HANDLE)); + if (pHevcEnc == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pHevcEnc, 0, sizeof(EXYNOS_HEVCENC_HANDLE)); + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoEnc->hCodecHandle = (OMX_HANDLETYPE)pHevcEnc; + pHevcEnc->qpRangeI.nMinQP = 0; + pHevcEnc->qpRangeI.nMaxQP = 50; + pHevcEnc->qpRangeP.nMinQP = 0; + pHevcEnc->qpRangeP.nMaxQP = 50; + pHevcEnc->qpRangeB.nMinQP = 0; + pHevcEnc->qpRangeB.nMaxQP = 50; + + pVideoEnc->quantization.nQpI = 29; + pVideoEnc->quantization.nQpP = 30; + pVideoEnc->quantization.nQpB = 32; + + pHevcEnc->chromaQPOffset.nCr = 0; + pHevcEnc->chromaQPOffset.nCb = 0; + + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_HEVC_DRM_ENC); + else + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_HEVC_ENC); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + +#ifdef USE_SINGLE_PLANE_IN_DRM + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + pExynosPort->ePlaneType = PLANE_SINGLE; +#endif + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingHEVC; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/avc"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pHevcEnc->HevcComponent[i], OMX_VIDEO_PARAM_HEVCTYPE); + pHevcEnc->HevcComponent[i].nPortIndex = i; + pHevcEnc->HevcComponent[i].eProfile = OMX_VIDEO_HEVCProfileMain; + pHevcEnc->HevcComponent[i].eLevel = OMX_VIDEO_HEVCMainTierLevel4; + } + pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].nKeyFrameInterval = 30; + + pHevcEnc->hMFCHevcHandle.bTemporalSVC = OMX_FALSE; + pHevcEnc->nMaxTemporalLayerCount = 0; + pHevcEnc->nTemporalLayerCount = 0; + pHevcEnc->bUseTemporalLayerBitrateRatio = 0; + Exynos_OSAL_Memset(pHevcEnc->nTemporalLayerBitrateRatio, 0, sizeof(pHevcEnc->nTemporalLayerBitrateRatio)); + + pOMXComponent->GetParameter = &Exynos_HEVCEnc_GetParameter; + pOMXComponent->SetParameter = &Exynos_HEVCEnc_SetParameter; + pOMXComponent->GetConfig = &Exynos_HEVCEnc_GetConfig; + pOMXComponent->SetConfig = &Exynos_HEVCEnc_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_HEVCEnc_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_HEVCEnc_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_HEVCEnc_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_HEVCEnc_Terminate; + + pVideoEnc->exynos_codec_srcInputProcess = &Exynos_HEVCEnc_srcInputBufferProcess; + pVideoEnc->exynos_codec_srcOutputProcess = &Exynos_HEVCEnc_srcOutputBufferProcess; + pVideoEnc->exynos_codec_dstInputProcess = &Exynos_HEVCEnc_dstInputBufferProcess; + pVideoEnc->exynos_codec_dstOutputProcess = &Exynos_HEVCEnc_dstOutputBufferProcess; + + pVideoEnc->exynos_codec_start = &HEVCCodecStart; + pVideoEnc->exynos_codec_stop = &HEVCCodecStop; + pVideoEnc->exynos_codec_bufferProcessRun = &HEVCCodecOutputBufferProcessRun; + pVideoEnc->exynos_codec_enqueueAllBuffer = &HEVCCodecEnqueueAllBuffer; + + pVideoEnc->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pVideoEnc->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoEnc->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pHevcEnc); + pHevcEnc = pVideoEnc->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.videoInstInfo.eCodecType = VIDEO_CODING_HEVC; + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + pHevcEnc->hMFCHevcHandle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pHevcEnc->hMFCHevcHandle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + pHevcEnc->hMFCHevcHandle.nRefForPframes = 1; + + if (Exynos_Video_GetInstInfo(&(pHevcEnc->hMFCHevcHandle.videoInstInfo), VIDEO_FALSE /* enc */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pHevcEnc); + pHevcEnc = pVideoEnc->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for enc : temporal-svc(%d)/roi(%d)/qp-range(%d)/pvc(%d)/I-ratio(%d)/CA(%d)AdaptiveBR(%d)/HDR-ST(%d)/HDR-DY(%d)/ChromaQP(%d)", + pExynosComponent, __FUNCTION__, + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bRoiInfoSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bQpRangePBSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bPVCSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bIFrameRatioSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bColorAspectsSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bAdaptiveLayerBitrateSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bHDRStaticInfoSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bHDRDynamicInfoSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bChromaQpSupport)); + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-qp-range", (OMX_INDEXTYPE)OMX_IndexConfigVideoQPRange); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-ref-pframes", (OMX_INDEXTYPE)OMX_IndexParamNumberRefPframes); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-gpb", (OMX_INDEXTYPE)OMX_IndexParamVideoEnableGPB); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-drop-control", (OMX_INDEXTYPE)OMX_IndexParamVideoDropControl); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-disable-dfr", (OMX_INDEXTYPE)OMX_IndexParamVideoDisableDFR); + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bChromaQpSupport == VIDEO_TRUE) + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-chroma-qp-offset", (OMX_INDEXTYPE)OMX_IndexParamVideoChromaQP); + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_TRUE) + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-disable-hierarchical-b-encoding", (OMX_INDEXTYPE)OMX_IndexParamVideoDisableHBEncoding); +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoEnc->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc != NULL) { + Exynos_OSAL_Free(pHevcEnc); + pHevcEnc = pVideoEnc->hCodecHandle = NULL; + } + +#ifdef USE_ANDROID + Exynos_OSAL_DelVendorExts(hComponent); +#endif + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/enc/hevc/Exynos_OMX_HEVCenc.h b/openmax/component/video/enc/hevc/Exynos_OMX_HEVCenc.h new file mode 100644 index 0000000..67adf32 --- /dev/null +++ b/openmax/component/video/enc/hevc/Exynos_OMX_HEVCenc.h @@ -0,0 +1,109 @@ +/* + * + * Copyright 2014 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_HEVCenc.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2014.05.22 : Create + */ + +#ifndef EXYNOS_OMX_HEVC_ENC_COMPONENT +#define EXYNOS_OMX_HEVC_ENC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" + +#include "ExynosVideoApi.h" + +typedef struct _EXYNOS_MFC_HEVCENC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + OMX_BOOL bPrependSpsPpsToIdr; + OMX_BOOL bTemporalSVC; + OMX_BOOL bRoiInfo; + OMX_BOOL bWeightedPrediction; + OMX_BOOL bHDRDynamicInfo; + OMX_BOOL bGPBEnable; + + ExynosVideoEncOps *pEncOps; + ExynosVideoEncBufferOps *pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps; + ExynosVideoEncParam encParam; + ExynosVideoInstInfo videoInstInfo; + + OMX_U32 nRefForPframes; + + #define MAX_PROFILE_NUM 4 + OMX_VIDEO_HEVCPROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_HEVCLEVELTYPE maxLevel; +} EXYNOS_MFC_HEVCENC_HANDLE; + +typedef struct _EXYNOS_HEVCENC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_HEVCTYPE HevcComponent[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + OMX_VIDEO_QPRANGE qpRangeI; + OMX_VIDEO_QPRANGE qpRangeP; + OMX_VIDEO_QPRANGE qpRangeB; + OMX_VIDEO_PARAM_CHROMA_QP_OFFSET chromaQPOffset; + OMX_BOOL bDisableHBEncoding; + + /* Temporal SVC */ + OMX_U32 nMaxTemporalLayerCount; + OMX_U32 nMaxTemporalLayerCountForB; + OMX_U32 nTemporalLayerCount; + OMX_U32 nTemporalLayerCountForB; + OMX_BOOL bUseTemporalLayerBitrateRatio; + OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS]; + + /* SEC MFC Codec specific */ + EXYNOS_MFC_HEVCENC_HANDLE hMFCHevcHandle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_HEVCENC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/enc/hevc/NOTICE b/openmax/component/video/enc/hevc/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/enc/hevc/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/enc/hevc/library_register.c b/openmax/component/video/enc/hevc/library_register.c new file mode 100644 index 0000000..391044c --- /dev/null +++ b/openmax/component/video/enc/hevc/library_register.c @@ -0,0 +1,61 @@ +/* + * + * Copyright 2014 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2014.05.22 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents) +{ + FunctionIn(); + + if (exynosComponents == NULL) + goto EXIT; + + /* component 1 - video Encoder HEVC */ + Exynos_OSAL_Strcpy(exynosComponents[0]->componentName, EXYNOS_OMX_COMPONENT_HEVC_ENC); + Exynos_OSAL_Strcpy(exynosComponents[0]->roles[0], EXYNOS_OMX_COMPONENT_HEVC_ENC_ROLE); + exynosComponents[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 2 - video Encoder HEVC for DRM */ + Exynos_OSAL_Strcpy(exynosComponents[1]->componentName, EXYNOS_OMX_COMPONENT_HEVC_DRM_ENC); + Exynos_OSAL_Strcpy(exynosComponents[1]->roles[0], EXYNOS_OMX_COMPONENT_HEVC_DRM_ENC_ROLE); + exynosComponents[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} + diff --git a/openmax/component/video/enc/hevc/library_register.h b/openmax/component/video/enc/hevc/library_register.h new file mode 100644 index 0000000..37b5f4a --- /dev/null +++ b/openmax/component/video/enc/hevc/library_register.h @@ -0,0 +1,58 @@ +/* + * + * Copyright 2014 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2014.05.22 : Create + */ + +#ifndef EXYNOS_OMX_HEVC_REG +#define EXYNOS_OMX_HEVC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 2 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* HEVC */ +#define EXYNOS_OMX_COMPONENT_HEVC_ENC "OMX.Exynos.HEVC.Encoder" +#define EXYNOS_OMX_COMPONENT_HEVC_DRM_ENC "OMX.Exynos.HEVC.Encoder.secure" +#define EXYNOS_OMX_COMPONENT_HEVC_ENC_ROLE "video_encoder.hevc" +#define EXYNOS_OMX_COMPONENT_HEVC_DRM_ENC_ROLE "video_encoder.hevc-wfd" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/openmax/component/video/enc/hevcwfd/Android.mk b/openmax/component/video/enc/hevcwfd/Android.mk new file mode 100644 index 0000000..281aa63 --- /dev/null +++ b/openmax/component/video/enc/hevcwfd/Android.mk @@ -0,0 +1,74 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_HEVCenc_wfd.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.HEVC.WFD.Encoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libVendorVideoApi libExynosOMX_OSAL libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/enc \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label -Wno-unused-parameter -Wno-unused-function + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/enc/hevcwfd/Exynos_OMX_HEVCenc_wfd.c b/openmax/component/video/enc/hevcwfd/Exynos_OMX_HEVCenc_wfd.c new file mode 100644 index 0000000..05e07a2 --- /dev/null +++ b/openmax/component/video/enc/hevcwfd/Exynos_OMX_HEVCenc_wfd.c @@ -0,0 +1,5730 @@ +/* + * + * Copyright 2017 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_HEVCenc_wfd.c + * @brief + * @author Taehwan Kim (t_h.kim@samsung.com) + * ByungGwan Kang (bk0917.kang@samsung.com) + * @version 2.0.0 + * @history + * 2018.07.13 : Create + */ + +#include +#include +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Venc.h" +#include "Exynos_OMX_VencControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OMX_HEVCenc_wfd.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OSAL_Queue.h" + +#include "Exynos_OSAL_Platform.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_HEVC_WFD_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +typedef struct _OMX_BUFFERHEADER_ARRAY { + OMX_BUFFERHEADERTYPE *pBuffer; + OMX_BOOL bInOMX; +} OMX_BUFFERHEADER_ARRAY; + +static OMX_BUFFERHEADER_ARRAY inputBufArray[MAX_BUFFER_NUM]; +static OMX_BUFFERHEADER_ARRAY outputBufArray[MAX_BUFFER_NUM]; + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain; + pHevcEnc->hMFCHevcHandle.nProfileCnt = nProfileCnt; + + switch (pHevcEnc->hMFCHevcHandle.videoInstInfo.HwVersion) { + case MFC_1501: + case MFC_150: + case MFC_1400: + case MFC_140: + pHevcEnc->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10; + pHevcEnc->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10HDR10; + pHevcEnc->hMFCHevcHandle.nProfileCnt = nProfileCnt; + + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel6; + break; + case MFC_130: + case MFC_120: + case MFC_1220: + pHevcEnc->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10; + pHevcEnc->hMFCHevcHandle.profiles[nProfileCnt++] = OMX_VIDEO_HEVCProfileMain10HDR10; + pHevcEnc->hMFCHevcHandle.nProfileCnt = nProfileCnt; + + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel6; + break; + case MFC_110: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel6; + break; + case MFC_100: + case MFC_101: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel51; + break; + case MFC_90: + case MFC_1010: + case MFC_1120: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel5; + break; + case MFC_1011: + case MFC_1020: + case MFC_1021: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel41; + break; + case MFC_92: + default: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel4; + break; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + + int nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pHevcEnc->hMFCHevcHandle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pHevcEnc->hMFCHevcHandle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pHevcEnc->hMFCHevcHandle.maxLevel; +#else + while ((pHevcEnc->hMFCHevcHandle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pHevcEnc->hMFCHevcHandle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pHevcEnc->hMFCHevcHandle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pHevcEnc->hMFCHevcHandle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) + goto EXIT; + + while ((pHevcEnc->hMFCHevcHandle.maxLevel >> nLevelCnt++) > 0); + + if ((pHevcEnc->hMFCHevcHandle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pHevcEnc->hMFCHevcHandle.nProfileCnt; i++) { + if (pHevcEnc->hMFCHevcHandle.profiles[i] == pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +static OMX_U32 OMXHevcProfileToProfileIDC(OMX_VIDEO_HEVCPROFILETYPE profile) +{ + OMX_U32 ret = 0; + + switch (profile) { + case OMX_VIDEO_HEVCProfileMain: + ret = 0; + break; + case OMX_VIDEO_HEVCProfileMain10: + case OMX_VIDEO_HEVCProfileMain10HDR10: + case OMX_VIDEO_HEVCProfileMain10HDR10Plus: + ret = 3; + break; + default: + ret = 0; + break; + } + + return ret; +} + +static OMX_U32 OMXHevcLevelToTierIDC(OMX_VIDEO_HEVCLEVELTYPE level) +{ + OMX_U32 ret = 0; //default Main tier + + switch (level) { + case OMX_VIDEO_HEVCMainTierLevel1: + case OMX_VIDEO_HEVCMainTierLevel2: + case OMX_VIDEO_HEVCMainTierLevel21: + case OMX_VIDEO_HEVCMainTierLevel3: + case OMX_VIDEO_HEVCMainTierLevel31: + case OMX_VIDEO_HEVCMainTierLevel4: + case OMX_VIDEO_HEVCMainTierLevel41: + case OMX_VIDEO_HEVCMainTierLevel5: + case OMX_VIDEO_HEVCMainTierLevel51: + case OMX_VIDEO_HEVCMainTierLevel52: + case OMX_VIDEO_HEVCMainTierLevel6: + case OMX_VIDEO_HEVCMainTierLevel61: + case OMX_VIDEO_HEVCMainTierLevel62: + ret = 0; + break; + case OMX_VIDEO_HEVCHighTierLevel1: + case OMX_VIDEO_HEVCHighTierLevel2: + case OMX_VIDEO_HEVCHighTierLevel21: + case OMX_VIDEO_HEVCHighTierLevel3: + case OMX_VIDEO_HEVCHighTierLevel31: + case OMX_VIDEO_HEVCHighTierLevel4: + case OMX_VIDEO_HEVCHighTierLevel41: + case OMX_VIDEO_HEVCHighTierLevel5: + case OMX_VIDEO_HEVCHighTierLevel51: + case OMX_VIDEO_HEVCHighTierLevel52: + case OMX_VIDEO_HEVCHighTierLevel6: + case OMX_VIDEO_HEVCHighTierLevel61: + case OMX_VIDEO_HEVCHighTierLevel62: + ret = 1; + break; + default: + ret = 0; + break; + } + + return ret; +} + +/* need to add to header file */ +static OMX_U32 OMXHevcLevelToLevelIDC(OMX_VIDEO_HEVCLEVELTYPE eLevel) +{ + OMX_U32 ret = 40; //default OMX_VIDEO_HEVCLevel4 + + switch (eLevel) { + case OMX_VIDEO_HEVCMainTierLevel1: + case OMX_VIDEO_HEVCHighTierLevel1: + ret = 10; + break; + case OMX_VIDEO_HEVCMainTierLevel2: + case OMX_VIDEO_HEVCHighTierLevel2: + ret = 20; + break; + case OMX_VIDEO_HEVCMainTierLevel21: + case OMX_VIDEO_HEVCHighTierLevel21: + ret = 21; + break; + case OMX_VIDEO_HEVCMainTierLevel3: + case OMX_VIDEO_HEVCHighTierLevel3: + ret = 30; + break; + case OMX_VIDEO_HEVCMainTierLevel31: + case OMX_VIDEO_HEVCHighTierLevel31: + ret = 31; + break; + case OMX_VIDEO_HEVCMainTierLevel4: + case OMX_VIDEO_HEVCHighTierLevel4: + ret = 40; + break; + case OMX_VIDEO_HEVCMainTierLevel41: + case OMX_VIDEO_HEVCHighTierLevel41: + ret = 41; + break; + case OMX_VIDEO_HEVCMainTierLevel5: + case OMX_VIDEO_HEVCHighTierLevel5: + ret = 50; + break; + case OMX_VIDEO_HEVCMainTierLevel51: + case OMX_VIDEO_HEVCHighTierLevel51: + ret = 51; + break; + case OMX_VIDEO_HEVCMainTierLevel52: + case OMX_VIDEO_HEVCHighTierLevel52: + ret = 52; + break; + case OMX_VIDEO_HEVCMainTierLevel6: + case OMX_VIDEO_HEVCHighTierLevel6: + ret = 60; + break; + case OMX_VIDEO_HEVCMainTierLevel61: + case OMX_VIDEO_HEVCHighTierLevel61: + ret = 61; + break; + case OMX_VIDEO_HEVCMainTierLevel62: + case OMX_VIDEO_HEVCHighTierLevel62: + ret = 62; + break; + default: + ret = 40; + break; + } + + return ret; +} + +static void Print_HEVCWFDEnc_Param(ExynosVideoEncParam *pEncParam) +{ + ExynosVideoEncCommonParam *pCommonParam = &pEncParam->commonParam; + ExynosVideoEncHevcParam *pHEVCParam = &pEncParam->codecParam.hevc; + + /* common parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceWidth : %d", pCommonParam->SourceWidth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceHeight : %d", pCommonParam->SourceHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "IDRPeriod : %d", pCommonParam->IDRPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SliceMode : %d", pCommonParam->SliceMode); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RandomIntraMBRefresh : %d", pCommonParam->RandomIntraMBRefresh); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Bitrate : %d", pCommonParam->Bitrate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp : %d", pCommonParam->FrameQp); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_P : %d", pCommonParam->FrameQp_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(I) ranege : %d / %d", pCommonParam->QpRange.QpMin_I, pCommonParam->QpRange.QpMax_I); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(P) ranege : %d / %d", pCommonParam->QpRange.QpMin_P, pCommonParam->QpRange.QpMax_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(B) ranege : %d / %d", pCommonParam->QpRange.QpMin_B, pCommonParam->QpRange.QpMax_B); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + + /* HEVC specific parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "ProfileIDC : %d", pHEVCParam->ProfileIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "TierIDC : %d", pHEVCParam->TierIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LevelIDC : %d", pHEVCParam->LevelIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_B : %d", pHEVCParam->FrameQp_B); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameRate : %d", pHEVCParam->FrameRate); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "MaxPartitionDepth : %d", pHEVCParam->MaxPartitionDepth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberBFrames : %d", pHEVCParam->NumberBFrames); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberRefForPframes : %d", pHEVCParam->NumberRefForPframes); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterDisable : %d", pHEVCParam->LoopFilterDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterSliceFlag : %d", pHEVCParam->LoopFilterSliceFlag); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterTcOffset : %d", pHEVCParam->LoopFilterTcOffset); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LoopFilterBetaOffset : %d", pHEVCParam->LoopFilterBetaOffset); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LongtermRefEnable : %d", pHEVCParam->LongtermRefEnable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LongtermUserRef : %d", pHEVCParam->LongtermUserRef); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LongtermStoreRef : %d", pHEVCParam->LongtermStoreRef); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "DarkDisable : %d", pHEVCParam->DarkDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SmoothDisable : %d", pHEVCParam->SmoothDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "StaticDisable : %d", pHEVCParam->StaticDisable); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "ActivityDisable : %d", pHEVCParam->ActivityDisable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "ROIEnable: : %d", pHEVCParam->ROIEnable); + + /* rate control related parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableFRMRateControl : %d", pCommonParam->EnableFRMRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableMBRateControl : %d", pCommonParam->EnableMBRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CBRPeriodRf : %d", pCommonParam->CBRPeriodRf); +} + +static void Set_HEVCWFDEnc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + EXYNOS_MFC_HEVCWFDENC_HANDLE *pMFCHevcWFDHandle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncInitParam *pInitParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncHevcParam *pHevcParam = NULL; + + int i; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCHevcWFDHandle = &pHevcEnc->hMFCHevcHandle; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pEncParam = &pMFCHevcWFDHandle->encParam; + pInitParam = &pEncParam->initParam; + pCommonParam = &pEncParam->commonParam; + pHevcParam = &pEncParam->codecParam.hevc; + pEncParam->eCompressionFormat = VIDEO_CODING_HEVC; + + /* common parameters */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + pCommonParam->SourceWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + pCommonParam->SourceHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } else { + pCommonParam->SourceWidth = pOutputPort->portDefinition.format.video.nFrameHeight; + pCommonParam->SourceHeight = pOutputPort->portDefinition.format.video.nFrameWidth; + } + pCommonParam->IDRPeriod = pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].nKeyFrameInterval; + pCommonParam->SliceMode = 0; + pCommonParam->Bitrate = pOutputPort->portDefinition.format.video.nBitrate; + pCommonParam->FrameQp = pVideoEnc->quantization.nQpI; + pCommonParam->FrameQp_P = pVideoEnc->quantization.nQpP; + + pCommonParam->QpRange.QpMin_I = pHevcEnc->qpRangeI.nMinQP; + pCommonParam->QpRange.QpMax_I = pHevcEnc->qpRangeI.nMaxQP; + pCommonParam->QpRange.QpMin_P = pHevcEnc->qpRangeP.nMinQP; + pCommonParam->QpRange.QpMax_P = pHevcEnc->qpRangeP.nMaxQP; + pCommonParam->QpRange.QpMin_B = pHevcEnc->qpRangeB.nMinQP; + pCommonParam->QpRange.QpMax_B = pHevcEnc->qpRangeB.nMaxQP; + + pCommonParam->PadControlOn = 0; /* 0: disable, 1: enable */ + pCommonParam->LumaPadVal = 0; + pCommonParam->CbPadVal = 0; + pCommonParam->CrPadVal = 0; + + if (pVideoEnc->intraRefresh.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic) { + /* Cyclic Mode */ + pCommonParam->RandomIntraMBRefresh = pVideoEnc->intraRefresh.nCirMBs; + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + /* Perceptual Mode */ + pCommonParam->PerceptualMode = (pVideoEnc->bPVCMode)? VIDEO_TRUE:VIDEO_FALSE; + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + /* HEVC specific parameters */ + pHevcParam->ProfileIDC = OMXHevcProfileToProfileIDC(pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].eProfile); + pHevcParam->TierIDC = OMXHevcLevelToTierIDC(pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].eLevel); + pHevcParam->LevelIDC = OMXHevcLevelToLevelIDC(pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].eLevel); + + pHevcParam->FrameQp_B = pVideoEnc->quantization.nQpB; + pHevcParam->FrameRate = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + + /* there is no interface at OMX IL component */ + pHevcParam->NumberBFrames = 0; /* 0 ~ 2 */ + pHevcParam->NumberRefForPframes = 1; /* 1 ~ 2 */ + + pHevcParam->MaxPartitionDepth = 1; + pHevcParam->LoopFilterDisable = 0; /* 1: Loop Filter Disable, 0: Filter Enable */ + pHevcParam->LoopFilterSliceFlag = 1; + pHevcParam->LoopFilterTcOffset = 0; + pHevcParam->LoopFilterBetaOffset = 0; + + pHevcParam->LongtermRefEnable = 0; + pHevcParam->LongtermUserRef = 0; + pHevcParam->LongtermStoreRef = 0; + + pHevcParam->DarkDisable = 1; /* disable adaptive rate control on dark region */ + pHevcParam->SmoothDisable = 1; /* disable adaptive rate control on smooth region */ + pHevcParam->StaticDisable = 1; /* disable adaptive rate control on static region */ + pHevcParam->ActivityDisable = 1; /* disable adaptive rate control on high activity region */ + + /* Temporal SVC */ + /* If MaxTemporalLayerCount value is 0, codec supported max value will be set */ + pHevcParam->MaxTemporalLayerCount = 0; + pHevcParam->TemporalSVC.nTemporalLayerCount = (unsigned int)pHevcEnc->nTemporalLayerCount; + + if (pHevcEnc->bUseTemporalLayerBitrateRatio == OMX_TRUE) { + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) + pHevcParam->TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pHevcEnc->nTemporalLayerBitrateRatio[i]; + } else { + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) + pHevcParam->TemporalSVC.nTemporalLayerBitrateRatio[i] = pOutputPort->portDefinition.format.video.nBitrate; + } + + pHevcParam->ROIEnable = (pMFCHevcWFDHandle->bRoiInfo == OMX_TRUE)? 1:0; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eControlRate: 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]); + /* rate control related parameters */ + switch ((int)pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]) { + case OMX_Video_ControlRateDisable: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode DBR"); + pCommonParam->EnableFRMRateControl = 0; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 0; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + case OMX_Video_ControlRateConstantVTCall: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR VT Call"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 5; + pCommonParam->bFixedSlice = VIDEO_TRUE; + break; + case OMX_Video_ControlRateConstantSkipFrames: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR VT Call with Skip frame"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1: MB level RC */ + pCommonParam->CBRPeriodRf = 5; + pCommonParam->bFixedSlice = VIDEO_TRUE; + pInitParam->FrameSkip = VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT; + break; + case OMX_Video_ControlRateConstant: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 9; + break; + case OMX_Video_ControlRateVariable: + default: /*Android default */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode VBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + } + +// Print_HEVCEnc_Param(pEncParam); +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) + goto EXIT; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE HEVCWFDCodecOpen( + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc, + ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pHevcEnc == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pEncOps = (ExynosVideoEncOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncOps)); + pInbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + pOutbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + + if ((pEncOps == NULL) || + (pInbufOps == NULL) || + (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.pEncOps = pEncOps; + pHevcEnc->hMFCHevcHandle.pInbufOps = pInbufOps; + pHevcEnc->hMFCHevcHandle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pEncOps->nSize = sizeof(ExynosVideoEncOps); + pInbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + + if (Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for encoder ops */ + if ((pEncOps->Init == NULL) || + (pEncOps->Finalize == NULL) || + (pEncOps->Set_FrameTag == NULL) || + (pEncOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pHevcEnc->hMFCHevcHandle.hMFCHandle = pHevcEnc->hMFCHevcHandle.pEncOps->Init(pVideoInstInfo); + if (pHevcEnc->hMFCHevcHandle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pHevcEnc->hMFCHevcHandle.pEncOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pHevcEnc->hMFCHevcHandle.pInbufOps = NULL; + } + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pHevcEnc->hMFCHevcHandle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HEVCWFDCodecClose(EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pHevcEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + + if (hMFCHandle != NULL) { + pEncOps->Finalize(hMFCHandle); + hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle = NULL; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Encoder(pEncOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps = NULL; + } + + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HEVCWFDCodecStart( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + + if (nPortIndex == INPUT_PORT_INDEX) + pInbufOps->Run(hMFCHandle); + else if (nPortIndex == OUTPUT_PORT_INDEX) + pOutbufOps->Run(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HEVCWFDCodecStop( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) + pInbufOps->Stop(hMFCHandle); + else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) + pOutbufOps->Stop(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCWFDEnc_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nParamIndex %x", pExynosComponent, __FUNCTION__, (int)nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoHevc: + { + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = (OMX_VIDEO_PARAM_HEVCTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_HEVCTYPE *pSrcHevcComponent = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstHevcComponent, sizeof(OMX_VIDEO_PARAM_HEVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstHevcComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcHevcComponent = &pHevcEnc->HevcComponent[pDstHevcComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstHevcComponent) + nOffset, + ((char *)pSrcHevcComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_HEVCTYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_HEVC_WFD_ENC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + OMX_VIDEO_PARAM_HEVCTYPE *pSrcHevcComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcHevcComponent = &pHevcEnc->HevcComponent[pDstProfileLevel->nPortIndex]; + + pDstProfileLevel->eProfile = pSrcHevcComponent->eProfile; + pDstProfileLevel->eLevel = pSrcHevcComponent->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pHevcEnc->errorCorrectionType[OUTPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pHevcEnc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pHevcEnc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pHevcEnc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pHevcEnc->qpRangeP.nMaxQP; + pQpRange->qpRangeB.nMinQP = pHevcEnc->qpRangeB.nMinQP; + pQpRange->qpRangeB.nMaxQP = pHevcEnc->qpRangeB.nMaxQP; + } + break; + case OMX_IndexParamVideoHevcEnableTemporalSVC: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *pDstEnableTemporalSVC = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstEnableTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstEnableTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstEnableTemporalSVC->bEnableTemporalSVC = pHevcEnc->hMFCHevcHandle.bTemporalSVC; + } + break; + case OMX_IndexParamVideoEnableRoiInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *pDstEnableRoiInfo = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstEnableRoiInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstEnableRoiInfo->bEnableRoiInfo = pHevcEnc->hMFCHevcHandle.bRoiInfo; + } + break; + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pEnablePVC->nU32 = pVideoEnc->bPVCMode; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamAndroidVideoTemporalLayering: + { + OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pTemporalLayering = (OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pTemporalLayering, sizeof(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pTemporalLayering->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) { + pTemporalLayering->eSupportedPatterns = OMX_VIDEO_AndroidTemporalLayeringPatternNone; + pTemporalLayering->nLayerCountMax = 1; /* not supported */ + pTemporalLayering->nBLayerCountMax = 0; + pTemporalLayering->ePattern = OMX_VIDEO_AndroidTemporalLayeringPatternNone; + } else { + pTemporalLayering->eSupportedPatterns = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; + + if (pHevcEnc->hMFCHevcHandle.bTemporalSVC == OMX_TRUE) { + pTemporalLayering->nLayerCountMax = pHevcEnc->nMaxTemporalLayerCount; + pTemporalLayering->nBLayerCountMax = pHevcEnc->nMaxTemporalLayerCountForB; + pTemporalLayering->ePattern = OMX_VIDEO_AndroidTemporalLayeringPatternAndroid; + } else { + pTemporalLayering->nLayerCountMax = OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; + pTemporalLayering->nBLayerCountMax = OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS_FOR_B; + pTemporalLayering->ePattern = OMX_VIDEO_AndroidTemporalLayeringPatternNone; + } + } + + pTemporalLayering->nPLayerCountActual = pHevcEnc->nTemporalLayerCount; + pTemporalLayering->nBLayerCountActual = pHevcEnc->nTemporalLayerCountForB; + + pTemporalLayering->bBitrateRatiosSpecified = pHevcEnc->bUseTemporalLayerBitrateRatio; + if (pTemporalLayering->bBitrateRatiosSpecified == OMX_TRUE) { + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) + pTemporalLayering->nBitrateRatios[i] = (pHevcEnc->nTemporalLayerBitrateRatio[i] << 16); + } + } + break; +#endif + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *pPortParam = (OMX_PORT_PARAM_TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pPortParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pPortParam->nPorts = pExynosComponent->portParam.nPorts; + pPortParam->nStartPortNumber = pExynosComponent->portParam.nStartPortNumber; + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *pPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortFormat->nPortIndex; + OMX_U32 nIndex = pPortFormat->nIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (nIndex > (INPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pPortDef = &pExynosPort->portDefinition; + + pPortFormat->eCompressionFormat = OMX_VIDEO_CodingUnused; + pPortFormat->xFramerate = pPortDef->format.video.xFramerate; + + if (pExynosPort->supportFormat[nIndex] == OMX_COLOR_FormatUnused) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + pPortFormat->eColorFormat = pExynosPort->supportFormat[nIndex]; + } else if (nPortIndex == OUTPUT_PORT_INDEX) { + if (nIndex > (OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX - 1)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pPortDef = &pExynosPort->portDefinition; + + pPortFormat->eCompressionFormat = pPortDef->format.video.eCompressionFormat; + pPortFormat->xFramerate = pPortDef->format.video.xFramerate; + pPortFormat->eColorFormat = pPortDef->format.video.eColorFormat; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE *pVideoBitrate = (OMX_VIDEO_PARAM_BITRATETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoBitrate->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pPortDef = &pExynosPort->portDefinition; + + pVideoBitrate->eControlRate = pVideoEnc->eControlRate[nPortIndex]; + pVideoBitrate->nTargetBitrate = pPortDef->format.video.nBitrate; + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoQuantization: + { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *pVideoQuantization = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoQuantization->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pPortDef = &pExynosPort->portDefinition; + + pVideoQuantization->nQpI = pVideoEnc->quantization.nQpI; + pVideoQuantization->nQpP = pVideoEnc->quantization.nQpP; + pVideoQuantization->nQpB = pVideoEnc->quantization.nQpB; + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 portIndex = portDefinition->nPortIndex; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(portDefinition, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + Exynos_OSAL_Memcpy(((char *)portDefinition) + nOffset, + ((char *)&pExynosPort->portDefinition) + nOffset, + portDefinition->nSize - nOffset); + + ret = Exynos_OSAL_GetParameter(hComponent, nParamIndex, pComponentParameterStructure); + if (ret != OMX_ErrorNone) + goto EXIT; + } + break; + case OMX_IndexVendorNeedContigMemory: + { + EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *pPortMemType = (EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortMemType->nPortIndex; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortMemType, sizeof(EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + pPortMemType->bNeedContigMem = pExynosPort->bNeedContigMem; + } + break; + case OMX_IndexParamVideoIntraRefresh: + { + OMX_VIDEO_PARAM_INTRAREFRESHTYPE *pIntraRefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pIntraRefresh->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pIntraRefresh, sizeof(OMX_VIDEO_PARAM_INTRAREFRESHTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pIntraRefresh->eRefreshMode = pVideoEnc->intraRefresh.eRefreshMode; + pIntraRefresh->nAirMBs = pVideoEnc->intraRefresh.nAirMBs; + pIntraRefresh->nAirRef = pVideoEnc->intraRefresh.nAirRef; + pIntraRefresh->nCirMBs = pVideoEnc->intraRefresh.nCirMBs; + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamRotationInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *pRotationInfo = (EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *)pComponentParameterStructure; + OMX_U32 nPortIndex = pRotationInfo->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pRotationInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pRotationInfo->eRotationType = pVideoEnc->eRotationType; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamConsumerUsageBits: + { + ret = Exynos_OSAL_GetParameter(hComponent, nParamIndex, pComponentParameterStructure); + } + break; +#endif + case OMX_IndexParamAudioInit: + case OMX_IndexParamImageInit: + case OMX_IndexParamOtherInit: + { + OMX_PORT_PARAM_TYPE *portParam = (OMX_PORT_PARAM_TYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(portParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + portParam->nPorts = 0; + portParam->nStartPortNumber = 0; + } + break; + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *compPriority = (OMX_PRIORITYMGMTTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(compPriority, sizeof(OMX_PRIORITYMGMTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + compPriority->nGroupID = pExynosComponent->compPriority.nGroupID; + compPriority->nGroupPriority = pExynosComponent->compPriority.nGroupPriority; + } + break; + + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplier = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pComponentParameterStructure; + OMX_U32 portIndex = bufferSupplier->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort; + + if ((pExynosComponent->currentState == OMX_StateLoaded) || + (pExynosComponent->currentState == OMX_StateWaitForResources)) { + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(bufferSupplier, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + + + if (pExynosPort->portDefinition.eDir == OMX_DirInput) { + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyInput; + } else if (CHECK_PORT_TUNNELED(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyOutput; + } else { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyUnspecified; + } + } else { + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyOutput; + } else if (CHECK_PORT_TUNNELED(pExynosPort)) { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyInput; + } else { + bufferSupplier->eBufferSupplier = OMX_BufferSupplyUnspecified; + } + } + } + else + { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + break; + default: + { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCWFDEnc_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoHevc: + { + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = NULL; + OMX_VIDEO_PARAM_HEVCTYPE *pSrcHevcComponent = (OMX_VIDEO_PARAM_HEVCTYPE *)pComponentParameterStructure; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcHevcComponent, sizeof(OMX_VIDEO_PARAM_HEVCTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcHevcComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstHevcComponent = &pHevcEnc->HevcComponent[pSrcHevcComponent->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstHevcComponent) + nOffset, + ((char *)pSrcHevcComponent) + nOffset, + sizeof(OMX_VIDEO_PARAM_HEVCTYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_HEVC_WFD_ENC_ROLE)) { + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingHEVC; + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstHevcComponent = &pHevcEnc->HevcComponent[pSrcProfileLevel->nPortIndex]; + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstHevcComponent->eProfile = pSrcProfileLevel->eProfile; + pDstHevcComponent->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pHevcEnc->errorCorrectionType[OUTPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP) || + (pQpRange->qpRangeB.nMinQP > pQpRange->qpRangeB.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d], B[min:%d, max:%d])", __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP, + pQpRange->qpRangeB.nMinQP, pQpRange->qpRangeB.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pHevcEnc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pHevcEnc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pHevcEnc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + pHevcEnc->qpRangeB.nMinQP = pQpRange->qpRangeB.nMinQP; + pHevcEnc->qpRangeB.nMaxQP = pQpRange->qpRangeB.nMaxQP; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamPrependSPSPPSToIDR: + { + ret = Exynos_OSAL_SetPrependSPSPPSToIDR(pComponentParameterStructure, &(pHevcEnc->hMFCHevcHandle.bPrependSpsPpsToIdr)); + } + break; + case OMX_IndexParamAndroidVideoTemporalLayering: + { + OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *pTemporalLayering = (OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pTemporalLayering, sizeof(OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pTemporalLayering->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pTemporalLayering->ePattern != OMX_VIDEO_AndroidTemporalLayeringPatternNone) { + /* ENABLE */ + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Temporal SVC is not supported", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + + if (pTemporalLayering->nLayerCountMax > OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] total layer : Max value(%d) > supportable Max value(%d)", + pExynosComponent, __FUNCTION__, pTemporalLayering->nLayerCountMax, OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pTemporalLayering->nBLayerCountMax > OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS_FOR_B) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] B layer : Max value(%d) > supportable Max value(%d)", + pExynosComponent, __FUNCTION__, pTemporalLayering->nBLayerCountMax, OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS_FOR_B); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.bTemporalSVC = OMX_TRUE; + pHevcEnc->nMaxTemporalLayerCount = pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual; + pHevcEnc->nMaxTemporalLayerCountForB = pTemporalLayering->nBLayerCountActual; + pHevcEnc->nTemporalLayerCount = pTemporalLayering->nPLayerCountActual + pTemporalLayering->nBLayerCountActual; + pHevcEnc->nTemporalLayerCountForB = pTemporalLayering->nBLayerCountActual; + + pHevcEnc->bUseTemporalLayerBitrateRatio = pTemporalLayering->bBitrateRatiosSpecified; + if (pHevcEnc->bUseTemporalLayerBitrateRatio == OMX_TRUE) { + for (i = 0; i < (int)pHevcEnc->nMaxTemporalLayerCount; i++) + pHevcEnc->nTemporalLayerBitrateRatio[i] = (pTemporalLayering->nBitrateRatios[i] >> 16); + } + + /* HIGH_SPEED_ENCODING */ + if (pHevcEnc->nTemporalLayerCountForB > 0) { + int minRequiredInputs = pow(2, pHevcEnc->nTemporalLayerCount - 1); + if (minRequiredInputs > pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.nBufferCountActual) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Temporal Layering with B-frame, increase InputBufferNum(%d)", pExynosComponent, __FUNCTION__, minRequiredInputs); + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.nBufferCountActual = minRequiredInputs; + } + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Max(%d), B-Max(%d), layer(%d), B-layer(%d)", pExynosComponent, __FUNCTION__, + pHevcEnc->nMaxTemporalLayerCount, pHevcEnc->nMaxTemporalLayerCountForB, + pHevcEnc->nTemporalLayerCount, pHevcEnc->nTemporalLayerCountForB); + } else { + /* DISABLE */ + pHevcEnc->hMFCHevcHandle.bTemporalSVC = OMX_FALSE; + pHevcEnc->nMaxTemporalLayerCount = 0; + pHevcEnc->nMaxTemporalLayerCountForB = 0; + pHevcEnc->nTemporalLayerCount = 0; + pHevcEnc->nTemporalLayerCountForB = 0; + pHevcEnc->bUseTemporalLayerBitrateRatio = OMX_FALSE; + Exynos_OSAL_Memset(pHevcEnc->nTemporalLayerBitrateRatio, 0, sizeof(pHevcEnc->nTemporalLayerBitrateRatio)); + } + } + break; +#endif + case OMX_IndexParamVideoHevcEnableTemporalSVC: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *pSrcEnableTemporalSVC = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC *)pComponentParameterStructure; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition); + int i; + + ret = Exynos_OMX_Check_SizeVersion(pSrcEnableTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcEnableTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) && + (pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Temporal SVC is not supported", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_TRUE) && + (pHevcEnc->hMFCHevcHandle.bTemporalSVC == OMX_FALSE)) { + /* ENABLE : not initialized yet */ + pHevcEnc->hMFCHevcHandle.bTemporalSVC = OMX_TRUE; + pHevcEnc->nMaxTemporalLayerCount = OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; + pHevcEnc->nMaxTemporalLayerCountForB = OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS_FOR_B; + pHevcEnc->nTemporalLayerCount = 1; + pHevcEnc->nTemporalLayerCountForB = 0; + pHevcEnc->bUseTemporalLayerBitrateRatio = OMX_TRUE; + pHevcEnc->nTemporalLayerBitrateRatio[0] = pPortDef->format.video.nBitrate; + } else if (pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_FALSE) { + /* DISABLE */ + pHevcEnc->hMFCHevcHandle.bTemporalSVC = OMX_FALSE; /* DISABLE */ + pHevcEnc->nMaxTemporalLayerCount = 0; + pHevcEnc->nMaxTemporalLayerCountForB = 0; + pHevcEnc->nTemporalLayerCount = 0; + pHevcEnc->nTemporalLayerCountForB = 0; + pHevcEnc->bUseTemporalLayerBitrateRatio = OMX_FALSE; + Exynos_OSAL_Memset(pHevcEnc->nTemporalLayerBitrateRatio, 0, sizeof(pHevcEnc->nTemporalLayerBitrateRatio)); + } + } + break; + case OMX_IndexParamVideoEnableRoiInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *pSrcEnableRoiInfo = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pSrcEnableRoiInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bRoiInfoSupport == VIDEO_FALSE) && + (pSrcEnableRoiInfo->bEnableRoiInfo == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] MFC D/D doesn't support Roi Info", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.bRoiInfo = pSrcEnableRoiInfo->bEnableRoiInfo; + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortDef->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[nPortIndex];; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + if (pPortDef->nBufferCountActual < pExynosPort->portDefinition.nBufferCountMin) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pPortDef->format.video.xFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] xFramerate is invalid(%d)", + pExynosComponent, __FUNCTION__, pPortDef->format.video.xFramerate >> 16); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Memcpy(((char *)&pExynosPort->portDefinition) + nOffset, + ((char *)pPortDef) + nOffset, + pPortDef->nSize - nOffset); + if (nPortIndex == INPUT_PORT_INDEX) { + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + Exynos_UpdateFrameSize(pOMXComponent); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] pOutputPort->portDefinition.nBufferSize: %d", pExynosComponent, __FUNCTION__, pExynosPort->portDefinition.nBufferSize); + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bPVCSupport == VIDEO_FALSE) && + (pEnablePVC->nU32 != 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] PVC mode is not supported", pExynosComponent, __FUNCTION__); + } + + pVideoEnc->bPVCMode = (pEnablePVC->nU32)? OMX_TRUE:OMX_FALSE; + } + break; + + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *pPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortFormat->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pPortDef = &(pExynosComponent->pExynosPort[nPortIndex].portDefinition); + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pPortFormat->xFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] xFramerate is invalid(%d)", + pExynosComponent, __FUNCTION__, pPortFormat->xFramerate >> 16); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pPortDef->format.video.eColorFormat = pPortFormat->eColorFormat; + pPortDef->format.video.eCompressionFormat = pPortFormat->eCompressionFormat; + pPortDef->format.video.xFramerate = pPortFormat->xFramerate; + } + break; + case OMX_IndexParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE *pVideoBitrate = (OMX_VIDEO_PARAM_BITRATETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoBitrate->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pPortDef = &(pExynosComponent->pExynosPort[nPortIndex].portDefinition); + pVideoEnc->eControlRate[nPortIndex] = pVideoBitrate->eControlRate; + pPortDef->format.video.nBitrate = pVideoBitrate->nTargetBitrate; + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoQuantization: + { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *pVideoQuantization = (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoQuantization->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pPortDef = &pExynosPort->portDefinition; + + pVideoEnc->quantization.nQpI = pVideoQuantization->nQpI; + pVideoEnc->quantization.nQpP = pVideoQuantization->nQpP; + pVideoEnc->quantization.nQpB = pVideoQuantization->nQpB; + } + ret = OMX_ErrorNone; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamStoreMetaDataBuffer: + case OMX_IndexParamAllocateNativeHandle: + { + ret = Exynos_OSAL_SetParameter(hComponent, nIndex, pComponentParameterStructure); + } + break; +#endif + case OMX_IndexVendorNeedContigMemory: + { + EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *pPortMemType = (EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortMemType->nPortIndex; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortMemType, sizeof(EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + pExynosPort->bNeedContigMem = pPortMemType->bNeedContigMem; + } + break; + case OMX_IndexParamVideoIntraRefresh: + { + OMX_VIDEO_PARAM_INTRAREFRESHTYPE *pIntraRefresh = (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pIntraRefresh->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pIntraRefresh, sizeof(OMX_VIDEO_PARAM_INTRAREFRESHTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pIntraRefresh->eRefreshMode == OMX_VIDEO_IntraRefreshCyclic) { + pVideoEnc->intraRefresh.eRefreshMode = pIntraRefresh->eRefreshMode; + pVideoEnc->intraRefresh.nCirMBs = pIntraRefresh->nCirMBs; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX_VIDEO_IntraRefreshCyclic Enable, nCirMBs: %d", + pVideoEnc->intraRefresh.nCirMBs); + } else { + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamEnableBlurFilter: + { + EXYNOS_OMX_VIDEO_PARAM_ENABLE_BLURFILTER *pBlurMode = (EXYNOS_OMX_VIDEO_PARAM_ENABLE_BLURFILTER *)pComponentParameterStructure; + OMX_U32 nPortIndex = pBlurMode->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pBlurMode, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_BLURFILTER)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pVideoEnc->bUseBlurFilter = pBlurMode->bUseBlurFilter; + } + break; + case OMX_IndexParamRotationInfo: + { + EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *pRotationInfo = (EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO *)pComponentParameterStructure; + OMX_U32 nPortIndex = pRotationInfo->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pRotationInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pRotationInfo->eRotationType != ROTATE_0) && + (pRotationInfo->eRotationType != ROTATE_90) && + (pRotationInfo->eRotationType != ROTATE_180) && + (pRotationInfo->eRotationType != ROTATE_270)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] can't accecpt a rotation value(%d)", pExynosComponent, __FUNCTION__, + pRotationInfo->eRotationType); + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + pVideoEnc->eRotationType = pRotationInfo->eRotationType; + } + break; + + case OMX_IndexParamVideoInit: + { + OMX_PORT_PARAM_TYPE *portParam = (OMX_PORT_PARAM_TYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(portParam, sizeof(OMX_PORT_PARAM_TYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + /* ret = OMX_ErrorUndefined; */ + /* Exynos_OSAL_Memcpy(&pExynosComponent->portParam, portParam, sizeof(OMX_PORT_PARAM_TYPE)); */ + } + break; + case OMX_IndexParamPriorityMgmt: + { + OMX_PRIORITYMGMTTYPE *compPriority = (OMX_PRIORITYMGMTTYPE *)pComponentParameterStructure; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(compPriority, sizeof(OMX_PRIORITYMGMTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosComponent->compPriority.nGroupID = compPriority->nGroupID; + pExynosComponent->compPriority.nGroupPriority = compPriority->nGroupPriority; + } + break; + case OMX_IndexParamCompBufferSupplier: + { + OMX_PARAM_BUFFERSUPPLIERTYPE *bufferSupplier = (OMX_PARAM_BUFFERSUPPLIERTYPE *)pComponentParameterStructure; + OMX_U32 portIndex = bufferSupplier->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(bufferSupplier, sizeof(OMX_PARAM_BUFFERSUPPLIERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyUnspecified) { + ret = OMX_ErrorNone; + goto EXIT; + } + if (CHECK_PORT_TUNNELED(pExynosPort) == 0) { + ret = OMX_ErrorNone; /*OMX_ErrorNone ?????*/ + goto EXIT; + } + + if (pExynosPort->portDefinition.eDir == OMX_DirInput) { + if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyInput) { + /* + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorNone; + } + */ + pExynosPort->tunnelFlags |= EXYNOS_TUNNEL_IS_SUPPLIER; + bufferSupplier->nPortIndex = pExynosPort->tunneledPort; + ret = OMX_SetParameter(pExynosPort->tunneledComponent, OMX_IndexParamCompBufferSupplier, bufferSupplier); + goto EXIT; + } else if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyOutput) { + ret = OMX_ErrorNone; + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + pExynosPort->tunnelFlags &= ~EXYNOS_TUNNEL_IS_SUPPLIER; + bufferSupplier->nPortIndex = pExynosPort->tunneledPort; + ret = OMX_SetParameter(pExynosPort->tunneledComponent, OMX_IndexParamCompBufferSupplier, bufferSupplier); + } + goto EXIT; + } + } else if (pExynosPort->portDefinition.eDir == OMX_DirOutput) { + if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyInput) { + ret = OMX_ErrorNone; + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + pExynosPort->tunnelFlags &= ~EXYNOS_TUNNEL_IS_SUPPLIER; + ret = OMX_ErrorNone; + } + goto EXIT; + } else if (bufferSupplier->eBufferSupplier == OMX_BufferSupplyOutput) { + /* + if (CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorNone; + } + */ + pExynosPort->tunnelFlags |= EXYNOS_TUNNEL_IS_SUPPLIER; + ret = OMX_ErrorNone; + goto EXIT; + } + } + } + break; + default: + { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCWFDEnc_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pHevcEnc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pHevcEnc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pHevcEnc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pHevcEnc->qpRangeP.nMaxQP; + pQpRange->qpRangeB.nMinQP = pHevcEnc->qpRangeB.nMinQP; + pQpRange->qpRangeB.nMaxQP = pHevcEnc->qpRangeB.nMaxQP; + } + break; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pDstTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pComponentConfigStructure; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstTemporalSVC->nKeyFrameInterval = pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].nKeyFrameInterval; + pDstTemporalSVC->nMinQuantizer = pHevcEnc->qpRangeI.nMinQP; + pDstTemporalSVC->nMaxQuantizer = pHevcEnc->qpRangeI.nMaxQP; + pDstTemporalSVC->nTemporalLayerCount = pHevcEnc->nTemporalLayerCount; + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) + pDstTemporalSVC->nTemporalLayerBitrateRatio[i] = pHevcEnc->nTemporalLayerBitrateRatio[i]; + } + break; + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigBitrate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pConfigBitrate->nEncodeBitrate = pExynosPort->portDefinition.format.video.nBitrate; + } + } + break; + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pConfigFramerate->xEncodeFramerate = pExynosPort->portDefinition.format.video.xFramerate; + } + break; +#ifdef USE_ANDROID + case OMX_IndexConfigVideoHdrStaticInfo: + case OMX_IndexConfigVideoColorAspects: + { + ret = Exynos_OSAL_GetConfig(hComponent, nIndex, pComponentConfigStructure); + } + break; +#endif + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCWFDEnc_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + EXYNOS_MFC_HEVCWFDENC_HANDLE *pMFCHevcWFDHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + int i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + if (&(pHevcEnc->hMFCHevcHandle) == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMFCHevcWFDHandle = (EXYNOS_MFC_HEVCWFDENC_HANDLE *)&pHevcEnc->hMFCHevcHandle; + + if (pMFCHevcWFDHandle->pEncOps == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pEncOps = (ExynosVideoEncOps *)pMFCHevcWFDHandle->pEncOps; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_U32 nPFrames = (*((OMX_U32 *)pComponentConfigStructure)) - 1; + pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].nKeyFrameInterval = nPFrames; + pEncOps->Set_IDRPeriod(pHevcEnc->hMFCHevcHandle.hMFCHandle, nPFrames + 1); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] IDR period: %d", pExynosComponent, __FUNCTION__, nPFrames + 1); + ret = OMX_ErrorNone ; + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + ExynosVideoQPRange qpRange; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP) || + (pQpRange->qpRangeB.nMinQP > pQpRange->qpRangeB.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d], B[min:%d, max:%d])", __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP, + pQpRange->qpRangeB.nMinQP, pQpRange->qpRangeB.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pHevcEnc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pHevcEnc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pHevcEnc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + pHevcEnc->qpRangeB.nMinQP = pQpRange->qpRangeB.nMinQP; + pHevcEnc->qpRangeB.nMaxQP = pQpRange->qpRangeB.nMaxQP; + + qpRange.QpMin_I = pQpRange->qpRangeI.nMinQP; + qpRange.QpMax_I = pQpRange->qpRangeI.nMaxQP; + qpRange.QpMin_P = pQpRange->qpRangeP.nMinQP; + qpRange.QpMax_P = pQpRange->qpRangeP.nMaxQP; + qpRange.QpMin_B = pQpRange->qpRangeB.nMinQP; + qpRange.QpMax_B = pQpRange->qpRangeB.nMaxQP; + + pEncOps->Set_QpRange(pMFCHevcWFDHandle->hMFCHandle, qpRange); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qp range: I(%d, %d), P(%d, %d), B(%d, %d)", + pExynosComponent, __FUNCTION__, + qpRange.QpMin_I, qpRange.QpMax_I, + qpRange.QpMin_P, qpRange.QpMax_P, + qpRange.QpMin_B, qpRange.QpMax_B); + } + break; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pSrcTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pComponentConfigStructure; + ExynosVideoQPRange qpRange; + TemporalLayerShareBuffer TemporalSVC; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcTemporalSVC, sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.bTemporalSVC == OMX_FALSE) || + (pSrcTemporalSVC->nTemporalLayerCount > OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].nKeyFrameInterval = pSrcTemporalSVC->nKeyFrameInterval; + + pHevcEnc->qpRangeI.nMinQP = pSrcTemporalSVC->nMinQuantizer; + pHevcEnc->qpRangeI.nMaxQP = pSrcTemporalSVC->nMaxQuantizer; + + pHevcEnc->nTemporalLayerCount = pSrcTemporalSVC->nTemporalLayerCount; + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) + pHevcEnc->nTemporalLayerBitrateRatio[i] = pSrcTemporalSVC->nTemporalLayerBitrateRatio[i]; + + qpRange.QpMin_I = pSrcTemporalSVC->nMinQuantizer; + qpRange.QpMax_I = pSrcTemporalSVC->nMaxQuantizer; + qpRange.QpMin_P = pSrcTemporalSVC->nMinQuantizer; + qpRange.QpMax_P = pSrcTemporalSVC->nMaxQuantizer; + qpRange.QpMin_B = pSrcTemporalSVC->nMinQuantizer; + qpRange.QpMax_B = pSrcTemporalSVC->nMaxQuantizer; + + pEncOps->Set_QpRange(pMFCHevcWFDHandle->hMFCHandle, qpRange); + pEncOps->Set_IDRPeriod(pMFCHevcWFDHandle->hMFCHandle, pSrcTemporalSVC->nKeyFrameInterval); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // qp range: I(%d, %d), P(%d, %d), B(%d, %d)", + pExynosComponent, __FUNCTION__, + qpRange.QpMin_I, qpRange.QpMax_I, + qpRange.QpMin_P, qpRange.QpMax_P, + qpRange.QpMin_B, qpRange.QpMax_B); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // IDR period: %d", pExynosComponent, __FUNCTION__, pSrcTemporalSVC->nKeyFrameInterval); + + /* Temporal SVC */ + Exynos_OSAL_Memset(&TemporalSVC, 0, sizeof(TemporalLayerShareBuffer)); + + TemporalSVC.nTemporalLayerCount = (unsigned int)pSrcTemporalSVC->nTemporalLayerCount; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // layer count: %d", pExynosComponent, __FUNCTION__, TemporalSVC.nTemporalLayerCount); + + for (i = 0; i < OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS; i++) { + TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pSrcTemporalSVC->nTemporalLayerBitrateRatio[i]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] temporal svc // bitrate ratio[%d]: %d", + pExynosComponent, __FUNCTION__, + i, TemporalSVC.nTemporalLayerBitrateRatio[i]); + } + if (pEncOps->Set_LayerChange(pMFCHevcWFDHandle->hMFCHandle, TemporalSVC) != VIDEO_ERROR_NONE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Not supported control: Set_LayerChange", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigVideoRoiInfo: + { + EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *pRoiInfo = (EXYNOS_OMX_VIDEO_CONFIG_ROIINFO *)pComponentConfigStructure; + RoiInfoShareBuffer RoiInfo; + + if (pRoiInfo->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.bRoiInfo == OMX_FALSE) || + ((pRoiInfo->bUseRoiInfo == OMX_TRUE) && + ((pRoiInfo->nRoiMBInfoSize <= 0) || + (pRoiInfo->pRoiMBInfo == NULL)))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: bUseRoiInfo %d nRoiMBInfoSize %d pRoiMBInfo %p", __FUNCTION__, __LINE__, + pRoiInfo->bUseRoiInfo, pRoiInfo->nRoiMBInfoSize, pRoiInfo->pRoiMBInfo); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Memset(&RoiInfo, 0, sizeof(RoiInfo)); + RoiInfo.pRoiMBInfo = (OMX_U64)(unsigned long)(((OMX_U8 *)pComponentConfigStructure) + sizeof(EXYNOS_OMX_VIDEO_CONFIG_ROIINFO)); + RoiInfo.nRoiMBInfoSize = pRoiInfo->nRoiMBInfoSize; + RoiInfo.nUpperQpOffset = pRoiInfo->nUpperQpOffset; + RoiInfo.nLowerQpOffset = pRoiInfo->nLowerQpOffset; + RoiInfo.bUseRoiInfo = (pRoiInfo->bUseRoiInfo == OMX_TRUE)? VIDEO_TRUE:VIDEO_FALSE; + if (pEncOps->Set_RoiInfo != NULL) { + pEncOps->Set_RoiInfo(pMFCHevcWFDHandle->hMFCHandle, &RoiInfo); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] roi info: %s", pExynosComponent, __FUNCTION__, + (RoiInfo.bUseRoiInfo == VIDEO_TRUE)? "enabled":"disabled"); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s]: Not supported control: Set_RoiInfo", + pExynosComponent, __FUNCTION__); + } + } + break; + case OMX_IndexConfigIFrameRatio: + { + OMX_PARAM_U32TYPE *pIFrameRatio = (OMX_PARAM_U32TYPE *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pIFrameRatio, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pIFrameRatio->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bIFrameRatioSupport == VIDEO_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] I-Frame ratio feature is not supported", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorNoneExpiration; + goto EXIT; + } + + pEncOps->Set_IFrameRatio(pMFCHevcWFDHandle->hMFCHandle, pIFrameRatio->nU32); + } + break; + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigBitrate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + if (pVideoEnc->eControlRate[nPortIndex] == OMX_Video_ControlRateDisable) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Rate control(eControlRate) is disable. can not change a bitrate", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pExynosPort->portDefinition.format.video.nBitrate = pConfigBitrate->nEncodeBitrate; + pEncOps->Set_BitRate(pHevcEnc->hMFCHevcHandle.hMFCHandle, pConfigBitrate->nEncodeBitrate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bitrate: %d", pExynosComponent, __FUNCTION__, pConfigBitrate->nEncodeBitrate); + } + } + break; + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pConfigFramerate->xEncodeFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] xFramerate is invalid(%d)", + pExynosComponent, __FUNCTION__, pConfigFramerate->xEncodeFramerate >> 16); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + pExynosPort->portDefinition.format.video.xFramerate = pConfigFramerate->xEncodeFramerate; + + pEncOps->Set_FrameRate(pHevcEnc->hMFCHevcHandle.hMFCHandle, (pConfigFramerate->xEncodeFramerate) >> 16); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] framerate: %d", pExynosComponent, __FUNCTION__, (pConfigFramerate->xEncodeFramerate) >> 16); + } + break; + case OMX_IndexConfigOperatingRate: /* since M version */ + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pComponentConfigStructure; + OMX_U32 xFramerate = 0; + + ret = Exynos_OMX_Check_SizeVersion(pConfigRate, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + pVideoEnc->nQosRatio = pConfigRate->nU32 >> 16; + + if (pVideoEnc->nQosRatio == (((OMX_U32)INT_MAX) >> 16)) { + pVideoEnc->nQosRatio = 1000; + } else { + pVideoEnc->nQosRatio = ((xFramerate >> 16) == 0)? 100:(OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + } + + pEncOps->Set_QosRatio(pMFCHevcWFDHandle->hMFCHandle, pVideoEnc->nQosRatio); + + pVideoEnc->bQosChanged = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qos ratio: 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->nQosRatio); + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexConfigBlurInfo: + { + EXYNOS_OMX_VIDEO_CONFIG_BLURINFO *pBlurMode = (EXYNOS_OMX_VIDEO_CONFIG_BLURINFO *)pComponentConfigStructure; + OMX_U32 nPortIndex = pBlurMode->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + int nEncResol; + + ret = Exynos_OMX_Check_SizeVersion(pBlurMode, sizeof(EXYNOS_OMX_VIDEO_CONFIG_BLURINFO)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + nEncResol = pExynosPort->portDefinition.format.video.nFrameWidth * pExynosPort->portDefinition.format.video.nFrameHeight; + + if (pVideoEnc->bUseBlurFilter == OMX_TRUE) { + if ((pBlurMode->eBlurMode & BLUR_MODE_DOWNUP) && + (nEncResol < (int)pBlurMode->eTargetResol)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Resolution(%d x %d) is smaller than target resolution", + pExynosComponent, __FUNCTION__, + pExynosPort->portDefinition.format.video.nFrameWidth, + pExynosPort->portDefinition.format.video.nFrameHeight); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc->eBlurMode = pBlurMode->eBlurMode; + pVideoEnc->eBlurResol = pBlurMode->eTargetResol; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Blur Filter is not enabled, it will be discard", + pExynosComponent, __FUNCTION__); + } + + ret = (OMX_ERRORTYPE)OMX_ErrorNoneExpiration; + } + break; + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + if (ret == (OMX_ERRORTYPE)OMX_ErrorNoneExpiration) + ret = OMX_ErrorNone; + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCWFDEnc_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_TEMPORALSVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigVideoTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_HEVC_ENABLE_TEMPORALSVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoHevcEnableTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_ROIINFO) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigVideoRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_ENABLE_ROIINFO) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoEnableRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_PVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoEnablePVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_IFRAME_RATIO) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigIFrameRatio; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_ANDROID + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_PREPEND_SPSPPS_TO_IDR) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamPrependSPSPPSToIDR; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_HDR_STATIC_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoHdrStaticInfo; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_INTRAPERIOD) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexConfigVideoIntraPeriod; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_NEED_CONTIG_MEMORY) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorNeedContigMemory; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_GET_BUFFER_FD) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorGetBufferFD; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_QPRANGE_TYPE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamVideoQPRange; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_QPRANGE_TYPE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoQPRange; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_BLUR_FILTER) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamEnableBlurFilter; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_BLUR_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigBlurInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ROATION_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamRotationInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_ANDROID + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_STORE_METADATA_BUFFER) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamStoreMetaDataBuffer; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_COLOR_ASPECTS_INFO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigVideoColorAspects; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ALLOCATE_NATIVE_HANDLE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamAllocateNativeHandle; + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = OMX_ErrorBadParameter; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_HEVCWFDEnc_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((hComponent == NULL) || + (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_HEVC_WFD_ENC_ROLE); + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + OMX_BOOL bSecureMode = OMX_FALSE; + + ExynosVideoInstInfo *pVideoInstInfo = NULL; + + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || + (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_HEVC_WFD_ENC, componentName) == 0) { + bSecureMode = OMX_FALSE; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_HEVC_WFD_DRM_ENC, componentName) == 0) { + bSecureMode = OMX_TRUE; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit for WFD (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = (bSecureMode == OMX_TRUE)? HW_VIDEO_ENC_SECURE_CODEC:HW_VIDEO_ENC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pHevcEnc = Exynos_OSAL_Malloc(sizeof(EXYNOS_HEVCWFDENC_HANDLE)); + if (pHevcEnc == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pHevcEnc, 0, sizeof(EXYNOS_HEVCWFDENC_HANDLE)); + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoEnc->hCodecHandle = (OMX_HANDLETYPE)pHevcEnc; + pHevcEnc->qpRangeI.nMinQP = 0; + pHevcEnc->qpRangeI.nMaxQP = 50; + pHevcEnc->qpRangeP.nMinQP = 0; + pHevcEnc->qpRangeP.nMaxQP = 50; + pHevcEnc->qpRangeB.nMinQP = 0; + pHevcEnc->qpRangeB.nMaxQP = 50; + + pVideoEnc->quantization.nQpI = 29; + pVideoEnc->quantization.nQpP = 30; + pVideoEnc->quantization.nQpB = 32; + + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_HEVC_WFD_DRM_ENC); + else + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_HEVC_WFD_ENC); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + +#ifdef USE_SINGLE_PLANE_IN_DRM + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + pExynosPort->ePlaneType = PLANE_SINGLE; +#endif + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingHEVC; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/avc"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pHevcEnc->HevcComponent[i], OMX_VIDEO_PARAM_HEVCTYPE); + pHevcEnc->HevcComponent[i].nPortIndex = i; + pHevcEnc->HevcComponent[i].eProfile = OMX_VIDEO_HEVCProfileMain; + pHevcEnc->HevcComponent[i].eLevel = OMX_VIDEO_HEVCMainTierLevel4; + } + + pHevcEnc->HevcComponent[OUTPUT_PORT_INDEX].nKeyFrameInterval = 30; + + pHevcEnc->hMFCHevcHandle.videoInstInfo.bOTFMode = VIDEO_TRUE; + + pOMXComponent->GetParameter = &Exynos_HEVCWFDEnc_GetParameter; + pOMXComponent->SetParameter = &Exynos_HEVCWFDEnc_SetParameter; + pOMXComponent->GetConfig = &Exynos_HEVCWFDEnc_GetConfig; + pOMXComponent->SetConfig = &Exynos_HEVCWFDEnc_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_HEVCWFDEnc_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_HEVCWFDEnc_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pVideoEnc->exynos_codec_start = &HEVCWFDCodecStart; + pVideoEnc->exynos_codec_stop = &HEVCWFDCodecStop; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pHevcEnc->hMFCHevcHandle.videoInstInfo.eCodecType = VIDEO_CODING_HEVC; + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + pHevcEnc->hMFCHevcHandle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pHevcEnc->hMFCHevcHandle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + if (Exynos_Video_GetInstInfo(&(pHevcEnc->hMFCHevcHandle.videoInstInfo), VIDEO_FALSE /* enc */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pHevcEnc); + pHevcEnc = pVideoEnc->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for enc : temporal-svc(%d)/roi(%d)/qp-range(%d)", + pExynosComponent, __FUNCTION__, + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bRoiInfoSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.supportInfo.enc.bQpRangePBSupport)); + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-qp-range", (OMX_INDEXTYPE)OMX_IndexConfigVideoQPRange); +#endif + + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pVideoInstInfo = &(pHevcEnc->hMFCHevcHandle.videoInstInfo); + + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pInputPort->portDefinition.format.video.xFramerate; + + /* HEVC Codec Open */ + ret = HEVCWFDCodecOpen(pHevcEnc, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pHevcEnc != NULL) { + HEVCWFDCodecClose(pHevcEnc); + Exynos_OSAL_Free(pHevcEnc); + pHevcEnc = pVideoEnc->hCodecHandle = NULL; + } + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Port_Constructor(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_BASEPORT *pExynosInputPort = NULL; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = NULL; + int i = 0, j = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x) Line:%d", __FUNCTION__, ret, __LINE__); + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x) Line:%d", __FUNCTION__, ret, __LINE__); + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + INIT_SET_SIZE_VERSION(&pExynosComponent->portParam, OMX_PORT_PARAM_TYPE); + pExynosComponent->portParam.nPorts = ALL_PORT_NUM; + pExynosComponent->portParam.nStartPortNumber = INPUT_PORT_INDEX; + + pExynosPort = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BASEPORT) * ALL_PORT_NUM); + if (pExynosPort == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort, 0, sizeof(EXYNOS_OMX_BASEPORT) * ALL_PORT_NUM); + pExynosComponent->pExynosPort = pExynosPort; + + /* Input Port */ + pExynosInputPort = &pExynosPort[INPUT_PORT_INDEX]; + + pExynosInputPort->extendBufferHeader = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + if (pExynosInputPort->extendBufferHeader == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosInputPort->extendBufferHeader, 0, sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + + pExynosInputPort->bufferStateAllocate = Exynos_OSAL_Malloc(sizeof(OMX_U32) * MAX_BUFFER_NUM); + if (pExynosInputPort->bufferStateAllocate == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosInputPort->bufferStateAllocate, 0, sizeof(OMX_U32) * MAX_BUFFER_NUM); + + pExynosInputPort->bufferSemID = NULL; + pExynosInputPort->assignedBufferNum = 0; + pExynosInputPort->portState = EXYNOS_OMX_PortStateLoaded; + pExynosInputPort->tunneledComponent = NULL; + pExynosInputPort->tunneledPort = 0; + pExynosInputPort->tunnelBufferNum = 0; + pExynosInputPort->bufferSupplier = OMX_BufferSupplyUnspecified; + pExynosInputPort->tunnelFlags = 0; + pExynosInputPort->supportFormat = NULL; + pExynosInputPort->bNeedContigMem = OMX_FALSE; + pExynosInputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + + INIT_SET_SIZE_VERSION(&pExynosInputPort->portDefinition, OMX_PARAM_PORTDEFINITIONTYPE); + pExynosInputPort->portDefinition.nPortIndex = INPUT_PORT_INDEX; + pExynosInputPort->portDefinition.eDir = OMX_DirInput; + pExynosInputPort->portDefinition.nBufferCountActual = 0; + pExynosInputPort->portDefinition.nBufferCountMin = 0; + pExynosInputPort->portDefinition.nBufferSize = 0; + pExynosInputPort->portDefinition.bEnabled = OMX_FALSE; + pExynosInputPort->portDefinition.bPopulated = OMX_FALSE; + pExynosInputPort->portDefinition.eDomain = OMX_PortDomainMax; + pExynosInputPort->portDefinition.bBuffersContiguous = OMX_FALSE; + pExynosInputPort->portDefinition.nBufferAlignment = 0; + + /* Output Port */ + pExynosOutputPort = &pExynosPort[OUTPUT_PORT_INDEX]; + + pExynosOutputPort->extendBufferHeader = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + if (pExynosOutputPort->extendBufferHeader == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosOutputPort->extendBufferHeader, 0, sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + + pExynosOutputPort->bufferStateAllocate = Exynos_OSAL_Malloc(sizeof(OMX_U32) * MAX_BUFFER_NUM); + if (pExynosOutputPort->bufferStateAllocate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosOutputPort->bufferStateAllocate, 0, sizeof(OMX_U32) * MAX_BUFFER_NUM); + + pExynosOutputPort->bufferSemID = NULL; + pExynosOutputPort->assignedBufferNum = 0; + pExynosOutputPort->portState = EXYNOS_OMX_PortStateLoaded; + pExynosOutputPort->tunneledComponent = NULL; + pExynosOutputPort->tunneledPort = 0; + pExynosOutputPort->tunnelBufferNum = 0; + pExynosOutputPort->bufferSupplier = OMX_BufferSupplyUnspecified; + pExynosOutputPort->tunnelFlags = 0; + pExynosOutputPort->supportFormat = NULL; + pExynosOutputPort->bNeedContigMem = OMX_FALSE; + pExynosOutputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + + INIT_SET_SIZE_VERSION(&pExynosOutputPort->portDefinition, OMX_PARAM_PORTDEFINITIONTYPE); + pExynosOutputPort->portDefinition.nPortIndex = OUTPUT_PORT_INDEX; + pExynosOutputPort->portDefinition.eDir = OMX_DirOutput; + pExynosOutputPort->portDefinition.nBufferCountActual = 0; + pExynosOutputPort->portDefinition.nBufferCountMin = 0; + pExynosOutputPort->portDefinition.nBufferSize = 0; + pExynosOutputPort->portDefinition.bEnabled = OMX_FALSE; + pExynosOutputPort->portDefinition.bPopulated = OMX_FALSE; + pExynosOutputPort->portDefinition.eDomain = OMX_PortDomainMax; + pExynosOutputPort->portDefinition.bBuffersContiguous = OMX_FALSE; + pExynosOutputPort->portDefinition.nBufferAlignment = 0; + + pExynosComponent->checkTimeStamp.needSetStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.needCheckStartTimeStamp = OMX_FALSE; + pExynosComponent->checkTimeStamp.startTimeStamp = 0; + pExynosComponent->checkTimeStamp.nStartFlags = 0x0; + + pOMXComponent->EmptyThisBuffer = &Exynos_OMX_EmptyThisBuffer; + pOMXComponent->FillThisBuffer = &Exynos_OMX_FillThisBuffer; + + ret = OMX_ErrorNone; + +EXIT: + if ((ret != OMX_ErrorNone) && + (pExynosComponent != NULL) && + (pExynosComponent->pExynosPort != NULL)) { + for (i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + Exynos_OSAL_Free(pExynosPort->bufferStateAllocate); + pExynosPort->bufferStateAllocate = NULL; + Exynos_OSAL_Free(pExynosPort->extendBufferHeader); + pExynosPort->extendBufferHeader = NULL; + } + + Exynos_OSAL_Free(pExynosComponent->pExynosPort); + pExynosComponent->pExynosPort = NULL; + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Port_Destructor(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + int i = 0, j = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + for (i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + + Exynos_OSAL_Free(pExynosPort->bufferStateAllocate); + pExynosPort->bufferStateAllocate = NULL; + Exynos_OSAL_Free(pExynosPort->extendBufferHeader); + pExynosPort->extendBufferHeader = NULL; + } + + Exynos_OSAL_Free(pExynosComponent->pExynosPort); + pExynosComponent->pExynosPort = NULL; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_InputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE* bufferHeader) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_U32 i = 0; + + pExynosComponent->pCallbacks->EmptyBufferDone(pOMXComponent, + pExynosComponent->callbackData, + bufferHeader); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader: %p", pExynosComponent, __FUNCTION__, bufferHeader); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (bufferHeader == inputBufArray[i].pBuffer) { + inputBufArray[i].bInOMX = OMX_FALSE; + break; + } + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_OutputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE* bufferHeader) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 i = 0; + + pExynosComponent->pCallbacks->FillBufferDone(pOMXComponent, + pExynosComponent->callbackData, + bufferHeader); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader: %p", pExynosComponent, __FUNCTION__, bufferHeader); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (bufferHeader == outputBufArray[i].pBuffer) { + outputBufArray[i].bInOMX = OMX_FALSE; + break; + } + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferFlushProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex, + OMX_BOOL bEvent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + cnt = (nPortIndex == ALL_PORT_INDEX) ? ALL_PORT_NUM : 1; + for (i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Flush %s Port", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + + ret = pExynosComponent->exynos_BufferFlush(pOMXComponent, nIndex, bEvent); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port is flushed", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + if (ret == OMX_ErrorNone) { + pExynosComponent->pExynosPort[nIndex].portState = EXYNOS_OMX_PortStateIdle; + + if (bEvent == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(EventCmdComplete/Flush/%s port)", + pExynosComponent, __FUNCTION__, (nIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandFlush, nIndex, NULL); + } + } + } + +EXIT: + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + if ((pOMXComponent != NULL) && + (pExynosComponent != NULL)) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_EnablePort( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + OMX_U32 i = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_PortEnableProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + cnt = (nPortIndex == ALL_PORT_INDEX) ? ALL_PORT_NUM : 1; + for (i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + } + +EXIT: + if ((ret != OMX_ErrorNone) && + (pOMXComponent != NULL) && + (pExynosComponent != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_DisablePort( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + pExynosPort->portDefinition.bEnabled = OMX_FALSE; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_PortDisableProcess( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 nIndex = 0; + + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + cnt = (nPortIndex == ALL_PORT_INDEX ) ? ALL_PORT_NUM : 1; + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + /* port flush*/ + for(i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Before disabling %s port, do flush", + pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosComponent->pExynosPort[nIndex].portState = EXYNOS_OMX_PortStateFlushingForDisable; + ret = pExynosComponent->exynos_BufferFlush(pOMXComponent, nIndex, OMX_FALSE); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s Port is flushed", pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + if (ret != OMX_ErrorNone) + goto EXIT; + } + } + + for(i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + nIndex = i; + else + nIndex = nPortIndex; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Disable %s Port", + pExynosComponent, __FUNCTION__, + (nIndex == INPUT_PORT_INDEX)? "input":"output"); + pExynosComponent->pExynosPort[nIndex].portState = EXYNOS_OMX_PortStateDisabling; + ret = Exynos_OMX_DisablePort(pOMXComponent, nIndex); + } + +EXIT: + if ((ret != OMX_ErrorNone) && + (pOMXComponent != NULL) && + (pExynosComponent != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + + FunctionOut(); + + return ret; +} + +/* Change CHECK_SIZE_VERSION Macro */ +OMX_ERRORTYPE Exynos_OMX_Check_SizeVersion(OMX_PTR header, OMX_U32 size) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_VERSIONTYPE *version = NULL; + + if (header == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + version = (OMX_VERSIONTYPE*)((char*)header + sizeof(OMX_U32)); + if (*((OMX_U32*)header) != size) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_FUNC_TRACE, "[%s] nVersionMajor:%d, nVersionMinor:%d", __FUNCTION__, version->s.nVersionMajor, version->s.nVersionMinor); + + if ((version->s.nVersionMajor != VERSIONMAJOR_NUMBER) || + (version->s.nVersionMinor > VERSIONMINOR_NUMBER)) { + ret = OMX_ErrorVersionMismatch; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + return ret; +} + +int Exynos_GetPlaneFromPort(EXYNOS_OMX_BASEPORT *pPort) +{ + int ret = 0; + + if (pPort == NULL) + goto EXIT; + + ret = pPort->processData.buffer.nPlanes; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_SetPlaneToPort(EXYNOS_OMX_BASEPORT *pPort, int nPlaneNum) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pPort == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pPort->processData.buffer.nPlanes = nPlaneNum; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_EmptyThisBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + unsigned int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->pExynosPort == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pBuffer->nInputPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StateExecuting) && + (pExynosComponent->currentState != OMX_StatePause)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (inputBufArray[i].bInOMX == OMX_FALSE) { + inputBufArray[i].pBuffer = pBuffer; + inputBufArray[i].bInOMX = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] pBuffer[%d]: %p", + pExynosComponent, __FUNCTION__, i, pBuffer); + break; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FillThisBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + unsigned int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->pExynosPort == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pBuffer->nOutputPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pBuffer, sizeof(OMX_BUFFERHEADERTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateIdle) && + (pExynosComponent->currentState != OMX_StateExecuting) && + (pExynosComponent->currentState != OMX_StatePause)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (outputBufArray[i].bInOMX == OMX_FALSE) { + outputBufArray[i].pBuffer = pBuffer; + outputBufArray[i].bInOMX = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] pBuffer[%d]: %p", + pExynosComponent, __FUNCTION__, i, pBuffer); + break; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetComponentVersion( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STRING pComponentName, + OMX_OUT OMX_VERSIONTYPE *pComponentVersion, + OMX_OUT OMX_VERSIONTYPE *pSpecVersion, + OMX_OUT OMX_UUIDTYPE *pComponentUUID) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + unsigned long compUUID[3]; + + FunctionIn(); + + /* check parameters */ + if (hComponent == NULL || + pComponentName == NULL || pComponentVersion == NULL || + pSpecVersion == NULL || pComponentUUID == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Strcpy(pComponentName, pExynosComponent->componentName); + Exynos_OSAL_Memcpy(pComponentVersion, &(pExynosComponent->componentVersion), sizeof(OMX_VERSIONTYPE)); + Exynos_OSAL_Memcpy(pSpecVersion, &(pExynosComponent->specVersion), sizeof(OMX_VERSIONTYPE)); + + /* Fill UUID with handle address, PID and UID. + * This should guarantee uiniqness */ + compUUID[0] = (unsigned long)pOMXComponent; + compUUID[1] = (unsigned long)getpid(); + compUUID[2] = (unsigned long)getuid(); + Exynos_OSAL_Memcpy(*pComponentUUID, compUUID, 3 * sizeof(*compUUID)); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_GetState( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STATETYPE *pState) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL || pState == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + *pState = pExynosComponent->currentState; + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SetPortFlush(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nPortIndex = nParam; + unsigned int i; + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + if ((nPortIndex != ALL_PORT_INDEX) && + ((OMX_S32)nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateFlushing; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateFlushing; + } + } else { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_SetPortDisable(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nPortIndex = nParam; + unsigned int i; + + FunctionIn(); + + if ((nPortIndex != ALL_PORT_INDEX) && + ((OMX_S32)nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex != ALL_PORT_INDEX) && + ((OMX_S32)nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateDisabling; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (!CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateDisabling; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_SetPortEnable(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 nPortIndex = nParam; + + OMX_U16 i = 0; + + FunctionIn(); + + if ((nPortIndex != ALL_PORT_INDEX) && + ((OMX_S32)nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (nPortIndex == ALL_PORT_INDEX) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; + +} + +static OMX_ERRORTYPE Exynos_SetStateSet( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + OMX_U32 i = 0; + + FunctionIn(); + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + switch ((OMX_STATETYPE)nParam) { + case OMX_StateIdle: + { + /* Loaded to Idle */ + if (pExynosComponent->currentState == OMX_StateLoaded) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateLoadedToIdle; + + for(i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateEnabling; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateLoaded to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + /* Executing to Idle */ + if (pExynosComponent->currentState == OMX_StateExecuting) { + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + pExynosComponent->transientState = EXYNOS_OMX_TransStateExecutingToIdle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateExecuting to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + /* Pause to Idle */ + if (pExynosComponent->currentState == OMX_StatePause) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StatePause to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = OMX_ErrorNone; + } + break; + case OMX_StateExecuting: + { + /* Idle to Executing */ + if (pExynosComponent->currentState == OMX_StateIdle) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateIdleToExecuting; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateExecuting", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + /* Pause to Executing */ + if (pExynosComponent->currentState == OMX_StatePause) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StatePause to OMX_StateIdle", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = OMX_ErrorBadParameter; + } + break; + case OMX_StateLoaded: + { + /* Idle to Loaded */ + if (pExynosComponent->currentState == OMX_StateIdle) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateIdleToLoaded; + + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateDisabling; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateLoaded", pExynosComponent, __FUNCTION__); + } + } + break; + case OMX_StateInvalid: + { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateInvalid; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, stateString(pExynosComponent->currentState)); + } + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s to %s", pExynosComponent, __FUNCTION__, + stateString(pExynosComponent->currentState), stateString(nParam)); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_StateSet(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_U32 destState = nParam; + OMX_U32 i = 0; + + if ((destState == OMX_StateIdle) && (pExynosComponent->currentState == OMX_StateLoaded)) { + for(i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateEnabling; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateLoaded to OMX_StateIdle", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateLoaded) && (pExynosComponent->currentState == OMX_StateIdle)) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateDisabling; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateLoaded", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateIdle) && (pExynosComponent->currentState == OMX_StateExecuting)) { + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateExecuting to OMX_StateIdle", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateIdle) && (pExynosComponent->currentState == OMX_StatePause)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StatePause to OMX_StateIdle", pExynosComponent, __FUNCTION__); + } else if ((destState == OMX_StateExecuting) && (pExynosComponent->currentState == OMX_StateIdle)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] OMX_StateIdle to OMX_StateExecuting", pExynosComponent, __FUNCTION__); + } else if (destState == OMX_StateInvalid) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateInvalid; + } + } + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentStateSet(OMX_COMPONENTTYPE *pOMXComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + OMX_STATETYPE destState = nParam; + OMX_STATETYPE currentState = pExynosComponent->currentState; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_HEVCWFDENC_HANDLE *pHevcEnc = (EXYNOS_HEVCWFDENC_HANDLE *)pVideoEnc->hCodecHandle; + + + ExynosVideoEncOps *pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoGeometry bufferConf; + + unsigned int i = 0, j = 0; + int k = 0; + int nOutBufSize = 0, nOutputBufferCnt = 0; + + FunctionIn(); + + /* check parameters */ + if (currentState == destState) { + ret = OMX_ErrorSameState; + goto EXIT; + } + if (currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] current:(%s) dest:(%s)", pExynosComponent, __FUNCTION__, stateString(currentState), stateString(destState)); + switch (destState) { + case OMX_StateInvalid: + switch (currentState) { + case OMX_StateWaitForResources: + case OMX_StateIdle: + case OMX_StateExecuting: + case OMX_StatePause: + case OMX_StateLoaded: + pExynosComponent->currentState = OMX_StateInvalid; + + if (currentState != OMX_StateLoaded) + Exynos_ResetAllPortConfig(pOMXComponent); + + ret = OMX_ErrorInvalidState; + break; + default: + ret = OMX_ErrorInvalidState; + break; + } + break; + case OMX_StateLoaded: + switch (currentState) { + case OMX_StateIdle: + for(i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateDisabling; + + ret = Exynos_ResetAllPortConfig(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + else + goto NO_EVENT_EXIT; + + break; + case OMX_StateWaitForResources: + pExynosComponent->currentState = OMX_StateLoaded; + break; + case OMX_StateExecuting: + case OMX_StatePause: + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StateIdle: + switch (currentState) { + case OMX_StateLoaded: + Exynos_OSAL_Get_Log_Property(); // For debuging, Function called when GetHandle function is success + + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosPort = &(pExynosComponent->pExynosPort[i]); + pExynosPort->portState = EXYNOS_OMX_PortStateEnabling; + + ret = Exynos_SetPlaneToPort(pExynosPort, (i == INPUT_PORT_INDEX) ? MFC_DEFAULT_INPUT_BUFFER_PLANE : MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + if (ret != OMX_ErrorNone) + break; + } + + if (ret != OMX_ErrorNone) + goto EXIT; + else + goto NO_EVENT_EXIT; + + break; + case OMX_StateExecuting: + Exynos_SetPortFlush(pExynosComponent, ALL_PORT_INDEX); + Exynos_OMX_BufferFlushProcess(pOMXComponent, ALL_PORT_INDEX, OMX_FALSE); + pExynosComponent->currentState = OMX_StateIdle; + break; + case OMX_StatePause: + Exynos_SetPortFlush(pExynosComponent, ALL_PORT_INDEX); + Exynos_OMX_BufferFlushProcess(pOMXComponent, ALL_PORT_INDEX, OMX_FALSE); + pExynosComponent->currentState = OMX_StateIdle; + break; + case OMX_StateWaitForResources: + pExynosComponent->currentState = OMX_StateIdle; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StateExecuting: + switch (currentState) { + case OMX_StateLoaded: + ret = OMX_ErrorIncorrectStateTransition; + break; + case OMX_StateIdle: + pExynosComponent->currentState = OMX_StateExecuting; + + /* Set EncParam for input (src) */ + Set_HEVCWFDEnc_Param(pExynosComponent); + pEncParam = &(pHevcEnc->hMFCHevcHandle.encParam); + if (pEncOps->Set_EncParam) { + if(pEncOps->Set_EncParam(pHevcEnc->hMFCHevcHandle.hMFCHandle, pEncParam) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set encParam", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + Print_HEVCWFDEnc_Param(pEncParam); + + /* set geometry for output (dst) */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + nOutBufSize = pExynosPort->portDefinition.nBufferSize; + if ((pExynosPort->bufferProcessType & BUFFER_COPY) || + (pExynosPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nOutBufSize = ALIGN(pExynosPort->portDefinition.format.video.nFrameWidth * + pExynosPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nOutBufSize = Exynos_OSAL_GetOutBufferSize(pExynosPort->portDefinition.format.video.nFrameWidth, + pExynosPort->portDefinition.format.video.nFrameHeight, + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.nBufferSize); +#endif + + } + if (pOutbufOps->Set_Geometry) { + /* output buffer info: only 2 config values needed */ + bufferConf.eCompressionFormat = VIDEO_CODING_HEVC; + bufferConf.nSizeImage = nOutBufSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosPort); + + if (pOutbufOps->Set_Geometry(pHevcEnc->hMFCHevcHandle.hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + break; + case OMX_StatePause: + pExynosComponent->currentState = OMX_StateExecuting; + break; + case OMX_StateWaitForResources: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StatePause: + switch (currentState) { + case OMX_StateLoaded: + ret = OMX_ErrorIncorrectStateTransition; + break; + case OMX_StateIdle: + pExynosComponent->currentState = OMX_StatePause; + break; + case OMX_StateExecuting: + pExynosComponent->currentState = OMX_StatePause; + break; + case OMX_StateWaitForResources: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + case OMX_StateWaitForResources: + switch (currentState) { + case OMX_StateLoaded: + pExynosComponent->currentState = OMX_StateWaitForResources; + break; + case OMX_StateIdle: + case OMX_StateExecuting: + case OMX_StatePause: + ret = OMX_ErrorIncorrectStateTransition; + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + break; + default: + ret = OMX_ErrorIncorrectStateTransition; + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + if (pExynosComponent->pCallbacks != NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, OMX_CommandStateSet, + destState, NULL); + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] (0x%x)", pExynosComponent, __FUNCTION__, ret); + if (pExynosComponent->pCallbacks != NULL) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +NO_EVENT_EXIT: /* postpone to send event */ + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SendCommand( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_COMMANDTYPE Cmd, + OMX_IN OMX_U32 nParam, + OMX_IN OMX_PTR pCmdData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch (Cmd) { + case OMX_CommandStateSet : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandStateSet", pExynosComponent, __FUNCTION__); + ret = Exynos_StateSet(pExynosComponent, nParam); + if (ret == OMX_ErrorNone) + Exynos_SetStateSet(pExynosComponent, nParam); + ret = Exynos_OMX_ComponentStateSet(pOMXComponent, nParam); + break; + case OMX_CommandFlush : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandFlush", pExynosComponent, __FUNCTION__); + ret = Exynos_SetPortFlush(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + ret = Exynos_OMX_BufferFlushProcess(pOMXComponent, nParam, OMX_TRUE); + break; + case OMX_CommandPortDisable : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandPortDisable", pExynosComponent, __FUNCTION__); + ret = Exynos_SetPortDisable(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + ret = Exynos_OMX_PortDisableProcess(pOMXComponent, nParam); + break; + case OMX_CommandPortEnable : + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Command: OMX_CommandPortEnable", pExynosComponent, __FUNCTION__); + ret = Exynos_SetPortEnable(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + ret = Exynos_OMX_PortEnableProcess(pOMXComponent, nParam); + break; + default: + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_SetCallbacks( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_CALLBACKTYPE* pCallbacks, + OMX_IN OMX_PTR pAppData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pCallbacks == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + if (pExynosComponent->currentState != OMX_StateLoaded) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pExynosComponent->pCallbacks = pCallbacks; + pExynosComponent->callbackData = pAppData; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Constructor( + OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] lib version is %s", __FUNCTION__, IS_64BIT_OS? "64bit":"32bit"); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] OMX_ErrorBadParameter (0x%x)", __FUNCTION__, ret); + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BASECOMPONENT)); + if (pExynosComponent == NULL) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Malloc (0x%x)", __FUNCTION__, ret); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent, 0, sizeof(EXYNOS_OMX_BASECOMPONENT)); + pOMXComponent->pComponentPrivate = (OMX_PTR)pExynosComponent; + + pOMXComponent->GetComponentVersion = &Exynos_OMX_GetComponentVersion; + pOMXComponent->SendCommand = &Exynos_OMX_SendCommand; + pOMXComponent->GetState = &Exynos_OMX_GetState; + pOMXComponent->SetCallbacks = &Exynos_OMX_SetCallbacks; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Destructor( + OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + Exynos_OSAL_Free(pExynosComponent); + pExynosComponent = NULL; + + ret = OMX_ErrorNone; +EXIT: + FunctionOut(); + + return ret; +} + +void Exynos_UpdateFrameSize(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + exynosInputPort->portDefinition.nBufferSize = ALIGN(exynosInputPort->portDefinition.format.video.nFrameWidth, 16) * + ALIGN(exynosInputPort->portDefinition.format.video.nFrameHeight, 16) * 3 / 2; + + if ((exynosOutputPort->portDefinition.format.video.nFrameWidth != + exynosInputPort->portDefinition.format.video.nFrameWidth) || + (exynosOutputPort->portDefinition.format.video.nFrameHeight != + exynosInputPort->portDefinition.format.video.nFrameHeight)) { + OMX_U32 width = 0, height = 0; + + exynosOutputPort->portDefinition.format.video.nFrameWidth = + exynosInputPort->portDefinition.format.video.nFrameWidth; + exynosOutputPort->portDefinition.format.video.nFrameHeight = + exynosInputPort->portDefinition.format.video.nFrameHeight; + width = exynosOutputPort->portDefinition.format.video.nStride = + exynosInputPort->portDefinition.format.video.nStride; + height = exynosOutputPort->portDefinition.format.video.nSliceHeight = + exynosInputPort->portDefinition.format.video.nSliceHeight; + + if (width && height) + exynosOutputPort->portDefinition.nBufferSize = ALIGN((ALIGN(width, 16) * ALIGN(height, 16) * 3) / 2, 512); + } + + return; +} + +void Exynos_Input_SetSupportFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_COLOR_FORMATTYPE ret = OMX_COLOR_FormatUnused; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if ((pVideoEnc == NULL) || (pInputPort == NULL)) + return ; + + if (pInputPort->supportFormat != NULL) { + OMX_BOOL ret = OMX_FALSE; + int nLastIndex = INPUT_PORT_SUPPORTFORMAT_DEFAULT_NUM; + int i; + + /* default supported formats */ + pInputPort->supportFormat[0] = OMX_COLOR_FormatYUV420Planar; + pInputPort->supportFormat[1] = OMX_COLOR_FormatYUV420SemiPlanar; + pInputPort->supportFormat[2] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV21Linear; + pInputPort->supportFormat[3] = OMX_COLOR_Format32bitARGB8888; + pInputPort->supportFormat[4] = (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888; +#ifdef USE_ANDROID + pInputPort->supportFormat[nLastIndex++] = OMX_COLOR_FormatAndroidOpaque; +#endif + + /* add extra formats, if It is supported by H/W. (CSC doesn't exist) */ + /* OMX_SEC_COLOR_FormatNV12Tiled */ + ret = pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled); + if (ret == OMX_TRUE) + pInputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled; + + /* OMX_SEC_COLOR_FormatYVU420Planar */ + ret = pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420Planar); + if (ret == OMX_TRUE) + pInputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420Planar; + + /* OMX_COLOR_Format32bitBGRA8888 */ + ret = pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, OMX_COLOR_Format32bitBGRA8888); + if (ret == OMX_TRUE) + pInputPort->supportFormat[nLastIndex++] = OMX_COLOR_Format32bitBGRA8888; + + for (i = 0; i < nLastIndex; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] Supported Format[%d] : 0x%x", + pExynosComponent, __FUNCTION__, i, pInputPort->supportFormat[i]); + } + + pInputPort->supportFormat[nLastIndex] = OMX_COLOR_FormatUnused; + } + + return ; +} + +OMX_COLOR_FORMATTYPE Exynos_Input_GetActualColorFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_COLOR_FORMATTYPE ret = OMX_COLOR_FormatUnused; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; + +#ifdef USE_ANDROID + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) + eColorFormat = pVideoEnc->surfaceFormat; +#endif + + if (pVideoEnc->exynos_codec_checkFormatSupport(pExynosComponent, eColorFormat) == OMX_TRUE) { + ret = eColorFormat; + goto EXIT; + } + + switch ((int)eColorFormat) { + case OMX_COLOR_FormatYUV420SemiPlanar: + case OMX_COLOR_FormatYUV420Planar: /* converted to NV12 using CSC */ + case OMX_COLOR_Format32bitARGB8888: /* converted to NV12 using CSC */ + case OMX_COLOR_Format32BitRGBA8888: /* converted to NV12 using CSC */ + ret = OMX_COLOR_FormatYUV420SemiPlanar; + break; + case OMX_SEC_COLOR_FormatNV21Linear: + case OMX_SEC_COLOR_FormatNV12Tiled: + ret = eColorFormat; + break; + default: + ret = OMX_COLOR_FormatUnused; + break; + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_ResetAllPortConfig(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + /* Input port */ + pInputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pInputPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pInputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pInputPort->portDefinition.format.video.nSliceHeight = 0; + pInputPort->portDefinition.format.video.pNativeRender = 0; + pInputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pInputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + + pInputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + pInputPort->portDefinition.bEnabled = OMX_TRUE; + + pInputPort->bufferProcessType = BUFFER_COPY; + pInputPort->portWayType = WAY2_PORT; + Exynos_SetPlaneToPort(pInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + + /* Output port */ + pOutputPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pOutputPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pOutputPort->portDefinition.format.video.nStride = 0; /*DEFAULT_FRAME_WIDTH;*/ + pOutputPort->portDefinition.format.video.nSliceHeight = 0; + pOutputPort->portDefinition.format.video.pNativeRender = 0; + pOutputPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pOutputPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + + pOutputPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM; + pOutputPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM; + pOutputPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pOutputPort->portDefinition.bEnabled = OMX_TRUE; + + pOutputPort->bufferProcessType = BUFFER_SHARE; + pOutputPort->portWayType = WAY2_PORT; + pOutputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(OMX_COLOR_FormatYUV420Planar, pOutputPort->ePlaneType)); + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = Exynos_OMX_BaseComponent_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to construct BaseComponent for WFD", __FUNCTION__); + goto EXIT; + } + + ret = Exynos_OMX_Port_Constructor(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Port_Constructor", __FUNCTION__); + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pVideoEnc = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_VIDEOENC_COMPONENT)); + if (pVideoEnc == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_Port_Destructor(pOMXComponent); + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Memset(pVideoEnc, 0, sizeof(EXYNOS_OMX_VIDEOENC_COMPONENT)); + pExynosComponent->hComponentHandle = (OMX_HANDLETYPE)pVideoEnc; + + pVideoEnc->nQosRatio = 0; + pVideoEnc->quantization.nQpI = 4; // I frame quantization parameter + pVideoEnc->quantization.nQpP = 5; // P frame quantization parameter + pVideoEnc->quantization.nQpB = 5; // B frame quantization parameter + + pVideoEnc->bUseBlurFilter = OMX_FALSE; + pVideoEnc->eBlurMode = BLUR_MODE_NONE; + pVideoEnc->eBlurResol = BLUR_RESOL_240; + + pVideoEnc->eRotationType = ROTATE_0; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->supportFormat = Exynos_OSAL_Malloc(sizeof(OMX_COLOR_FORMATTYPE) * INPUT_PORT_SUPPORTFORMAT_NUM_MAX); + if (pExynosPort->supportFormat == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort->supportFormat, 0, (sizeof(OMX_COLOR_FORMATTYPE) * INPUT_PORT_SUPPORTFORMAT_NUM_MAX)); + + pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MAX_VIDEO_INPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = 0; + pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo; + + pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + if (pExynosPort->portDefinition.format.video.cMIMEType == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + + pExynosPort->portDefinition.format.video.nFrameWidth = 0; + pExynosPort->portDefinition.format.video.nFrameHeight= 0; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.format.video.nBitrate = 1000000; + pExynosPort->portDefinition.format.video.xFramerate = (15 << 16); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pVideoEnc->eControlRate[INPUT_PORT_INDEX] = OMX_Video_ControlRateVariable; + + pExynosPort->eMetaDataType = METADATA_TYPE_DISABLED; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->supportFormat = Exynos_OSAL_Malloc(sizeof(OMX_COLOR_FORMATTYPE) * OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX); + if (pExynosPort->supportFormat == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosPort->supportFormat, 0, (sizeof(OMX_COLOR_FORMATTYPE) * OUTPUT_PORT_SUPPORTFORMAT_NUM_MAX)); + + pExynosPort->portDefinition.nBufferCountActual = MAX_VIDEO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferCountMin = MAX_VIDEO_OUTPUTBUFFER_NUM; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.eDomain = OMX_PortDomainVideo; + + pExynosPort->portDefinition.format.video.cMIMEType = Exynos_OSAL_Malloc(MAX_OMX_MIMETYPE_SIZE); + if (pExynosPort->portDefinition.format.video.cMIMEType == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + + pExynosPort->portDefinition.format.video.nFrameWidth = 0; + pExynosPort->portDefinition.format.video.nFrameHeight= 0; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.format.video.nSliceHeight = 0; + pExynosPort->portDefinition.format.video.nBitrate = 1000000; + pExynosPort->portDefinition.format.video.xFramerate = (15 << 16); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] = OMX_Video_ControlRateVariable; + + pExynosPort->eMetaDataType = METADATA_TYPE_DISABLED; + + pOMXComponent->UseBuffer = &Exynos_OMX_UseBuffer; + pOMXComponent->AllocateBuffer = &Exynos_OMX_AllocateBuffer; + pOMXComponent->FreeBuffer = &Exynos_OMX_FreeBuffer; + + pExynosComponent->exynos_BufferFlush = &Exynos_OMX_BufferFlush; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + + int i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Free(pVideoEnc); + pExynosComponent->hComponentHandle = pVideoEnc = NULL; + + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + if (pExynosPort->processData.extInfo != NULL) { + Exynos_OSAL_Free(pExynosPort->processData.extInfo); + pExynosPort->processData.extInfo = NULL; + } + + for(i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + Exynos_OSAL_Free(pExynosPort->portDefinition.format.video.cMIMEType); + pExynosPort->portDefinition.format.video.cMIMEType = NULL; + + Exynos_OSAL_Free(pExynosPort->supportFormat); + pExynosPort->supportFormat = NULL; + } + + ret = Exynos_OMX_Port_Destructor(pOMXComponent); + + ret = Exynos_OMX_BaseComponent_Destructor(hComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pTempBufferHdr = NULL; + OMX_U8 *pTempBuffer = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (pExynosPort->portState != EXYNOS_OMX_PortStateEnabling) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pTempBuffer = (OMX_U8 *)Exynos_OSAL_Malloc(64); + if (pTempBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pTempBuffer, 0, 64); + + pTempBufferHdr = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (pTempBufferHdr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pTempBufferHdr, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = pTempBufferHdr; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ALLOCATED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(pTempBufferHdr, OMX_BUFFERHEADERTYPE); + + pTempBufferHdr->pBuffer = pTempBuffer; + pTempBufferHdr->nAllocLen = nSizeBytes; + pTempBufferHdr->pAppPrivate = pAppPrivate; + + if (nPortIndex == INPUT_PORT_INDEX) + pTempBufferHdr->nInputPortIndex = INPUT_PORT_INDEX; + else + pTempBufferHdr->nOutputPortIndex = OUTPUT_PORT_INDEX; + + pExynosPort->assignedBufferNum++; + + *ppBufferHdr = pTempBufferHdr; + + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + + if ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle)) { + if (CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, OMX_CommandStateSet, + OMX_StateIdle, NULL); + + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateIdle; + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateIdle; + } + } else if(!(CHECK_PORT_ENABLED(pExynosPort)) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + pExynosPort->portState = EXYNOS_OMX_PortStateIdle; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Enable %s Port", pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + ret = Exynos_OMX_EnablePort(pOMXComponent, nPortIndex); + + if ((ret == OMX_ErrorNone) && (pExynosComponent->pCallbacks != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(Enable/%s port)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX) ? "input" : "output"); + + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortEnable, + (nPortIndex == INPUT_PORT_INDEX) ? INPUT_PORT_INDEX : OUTPUT_PORT_INDEX, + NULL); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(EventCmdComplete/Enable/%s port)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + + } + } + } + + ret = OMX_ErrorNone; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p), size(%d)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + (*ppBufferHdr), nSizeBytes); + goto EXIT; + } + } + + ret = OMX_ErrorInsufficientResources; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pTempBufferHdr != NULL) + Exynos_OSAL_Free(pTempBufferHdr); + + if (pTempBuffer != NULL) + Exynos_OSAL_Free(pTempBuffer); + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pTempBufferHdr = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (pExynosPort->portState != EXYNOS_OMX_PortStateEnabling) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pTempBufferHdr = (OMX_BUFFERHEADERTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_BUFFERHEADERTYPE)); + if (pTempBufferHdr == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pTempBufferHdr, 0, sizeof(OMX_BUFFERHEADERTYPE)); + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (pExynosPort->bufferStateAllocate[i] == BUFFER_STATE_FREE) { + pExynosPort->extendBufferHeader[i].OMXBufferHeader = pTempBufferHdr; + pExynosPort->bufferStateAllocate[i] = (BUFFER_STATE_ASSIGNED | HEADER_STATE_ALLOCATED); + INIT_SET_SIZE_VERSION(pTempBufferHdr, OMX_BUFFERHEADERTYPE); + + pTempBufferHdr->pBuffer = pBuffer; + pTempBufferHdr->nAllocLen = nSizeBytes; + pTempBufferHdr->pAppPrivate = pAppPrivate; + + if (nPortIndex == INPUT_PORT_INDEX) + pTempBufferHdr->nInputPortIndex = INPUT_PORT_INDEX; + else + pTempBufferHdr->nOutputPortIndex = OUTPUT_PORT_INDEX; + + pExynosPort->assignedBufferNum++; + + *ppBufferHdr = pTempBufferHdr; + + if (pExynosPort->assignedBufferNum == (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) { + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + + if ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle)) { + if (CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, OMX_CommandStateSet, + OMX_StateIdle, NULL); + + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateIdle; + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateIdle; + } + } else if(!(CHECK_PORT_ENABLED(pExynosPort)) && + (pExynosPort->portState == EXYNOS_OMX_PortStateEnabling)) { + pExynosPort->portState = EXYNOS_OMX_PortStateIdle; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Enable %s Port", pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + ret = Exynos_OMX_EnablePort(pOMXComponent, nPortIndex); + + if ((ret == OMX_ErrorNone) && (pExynosComponent->pCallbacks != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete(Enable/%s port)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX) ? "input" : "output"); + + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortEnable, + (nPortIndex == INPUT_PORT_INDEX) ? INPUT_PORT_INDEX : OUTPUT_PORT_INDEX, + NULL); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(EventCmdComplete/Enable/%s port)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + } + } + } + + ret = OMX_ErrorNone; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p), size(%d)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + (*ppBufferHdr), nSizeBytes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pTempBufferHdr); + ret = OMX_ErrorInsufficientResources; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *pOMXBufferHdr = NULL; + OMX_U32 i = 0; + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter(0x%x)", pExynosComponent, __FUNCTION__, nPortIndex); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosPort->portState != EXYNOS_OMX_PortStateDisabling) && + (pExynosPort->portState != EXYNOS_OMX_PortStateFlushingForDisable) && + (pExynosPort->portState != EXYNOS_OMX_PortStateInvalid)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] %s port : invalid state : comp state(0x%x), port state(0x%x), enabled(0x%x)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosComponent->currentState, pExynosPort->portState, pExynosPort->portDefinition.bEnabled); + ret = OMX_ErrorIncorrectStateOperation; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", pExynosComponent, __FUNCTION__); + + (*(pExynosComponent->pCallbacks->EventHandler)) (pOMXComponent, + pExynosComponent->callbackData, + (OMX_U32)OMX_EventError, + (OMX_U32)OMX_ErrorPortUnpopulated, + nPortIndex, NULL); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + for (i = 0; i < /*pExynosPort->portDefinition.nBufferCountActual*/MAX_BUFFER_NUM; i++) { + if ((pExynosPort->bufferStateAllocate[i] != BUFFER_STATE_FREE) && + (pExynosPort->extendBufferHeader[i].OMXBufferHeader != NULL)) { + pOMXBufferHdr = pExynosPort->extendBufferHeader[i].OMXBufferHeader; + + if (pOMXBufferHdr->pBuffer == pBufferHdr->pBuffer) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s port: buffer header(%p)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output", + pOMXBufferHdr); + if (pExynosPort->bufferStateAllocate[i] & BUFFER_STATE_ALLOCATED) { + pOMXBufferHdr->pBuffer = NULL; + pBufferHdr->pBuffer = NULL; + } + + pExynosPort->assignedBufferNum--; + + if (pExynosPort->bufferStateAllocate[i] & HEADER_STATE_ALLOCATED) { + Exynos_OSAL_Free(pOMXBufferHdr); + pExynosPort->extendBufferHeader[i].OMXBufferHeader = NULL; + pBufferHdr = NULL; + } + + pExynosPort->bufferStateAllocate[i] = BUFFER_STATE_FREE; + ret = OMX_ErrorNone; + goto EXIT; + } + } + } + +EXIT: + if (ret == OMX_ErrorNone) { + if (pExynosPort->assignedBufferNum < (OMX_S32)pExynosPort->portDefinition.nBufferCountActual) + pExynosPort->portDefinition.bPopulated = OMX_FALSE; + + if (pExynosPort->assignedBufferNum == 0) { + if ((pExynosComponent->currentState == OMX_StateIdle) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateIdleToLoaded)) { + if (!CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[INPUT_PORT_INDEX]) && + !CHECK_PORT_POPULATED(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX])) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] OMX_EventCmdComplete", pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, OMX_CommandStateSet, + OMX_StateLoaded, NULL); + + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) + pExynosComponent->pExynosPort[i].portState = EXYNOS_OMX_PortStateLoaded; + + pExynosComponent->transientState = EXYNOS_OMX_TransStateMax; + pExynosComponent->currentState = OMX_StateLoaded; + } + } + + if (pExynosPort->portState == EXYNOS_OMX_PortStateDisabling) { + if (!CHECK_PORT_ENABLED(pExynosPort)) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortDisable, nPortIndex, NULL); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s]send event(EventCmdComplete/Disable/%s port)", + pExynosComponent, __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "input":"output"); + + pExynosPort->portState = EXYNOS_OMX_PortStateLoaded; + } + } + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_FlushPort( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *pBufferHdr = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + unsigned int i = 0; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if ((nPortIndex < 0) || + (nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + for (i = 0; i < pExynosPort->portDefinition.nBufferCountActual; i++) { + if (nPortIndex == INPUT_PORT_INDEX) { + if (inputBufArray[i].bInOMX == OMX_TRUE) { + if (inputBufArray[i].pBuffer != NULL) { + pBufferHdr = inputBufArray[i].pBuffer; + pBufferHdr->nFilledLen = 0; + Exynos_OMX_InputBufferReturn(pOMXComponent, pBufferHdr); + } + } + } else { + if (outputBufArray[i].bInOMX == OMX_TRUE) { + if (outputBufArray[i].pBuffer != NULL) { + pBufferHdr = outputBufArray[i].pBuffer; + pBufferHdr->nFilledLen = 0; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pBufferHdr); + } + } + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_BufferFlush( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_S32 nPortIndex, + OMX_BOOL bEvent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if ((nPortIndex < 0) || + (nPortIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] OMX_CommandFlush start, port:%d, event:%d", + pExynosComponent, __FUNCTION__, nPortIndex, bEvent); + + ret = Exynos_OMX_FlushPort(pOMXComponent, nPortIndex); + if (ret != OMX_ErrorNone) + goto EXIT; + + Exynos_ResetCodecData(&pExynosPort->processData); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] OMX_CommandFlush end, port:%d, event:%d", + pExynosComponent, __FUNCTION__, nPortIndex, bEvent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_ResetCodecData(EXYNOS_OMX_DATA *pData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pData == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + /* caution: nPlanes in buffer structure might be used all times */ + Exynos_OSAL_Memset(&(pData->buffer.fd), 0, sizeof(pData->buffer.fd)); + Exynos_OSAL_Memset(&(pData->buffer.addr), 0, sizeof(pData->buffer.addr)); + + pData->dataLen = 0; + pData->usedDataLen = 0; + pData->remainDataLen = 0; + pData->nFlags = 0; + pData->timeStamp = 0; + pData->pPrivate = NULL; + pData->bufferHeader = NULL; + +EXIT: + return ret; +} diff --git a/openmax/component/video/enc/hevcwfd/Exynos_OMX_HEVCenc_wfd.h b/openmax/component/video/enc/hevcwfd/Exynos_OMX_HEVCenc_wfd.h new file mode 100644 index 0000000..46440f6 --- /dev/null +++ b/openmax/component/video/enc/hevcwfd/Exynos_OMX_HEVCenc_wfd.h @@ -0,0 +1,132 @@ +/* + * + * Copyright 2017 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_HEVCenc_wfd.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * ByungGwan Kang (bk0917.kang@samsung.com) + * @version 2.0.0 + * @history + * 2018.07.13 : Create + */ + +#ifndef EXYNOS_OMX_HEVC_WFD_ENC_COMPONENT +#define EXYNOS_OMX_HEVC_WFD_ENC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" + +#include "ExynosVideoApi.h" +#include "library_register.h" + +typedef struct _EXYNOS_MFC_HEVCWFDENC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bPrependSpsPpsToIdr; + OMX_BOOL bTemporalSVC; + OMX_BOOL bRoiInfo; + OMX_U32 nLTRFrames; + + ExynosVideoEncOps *pEncOps; + ExynosVideoEncBufferOps *pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps; + ExynosVideoEncParam encParam; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 3 + OMX_VIDEO_HEVCPROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_HEVCLEVELTYPE maxLevel; +} EXYNOS_MFC_HEVCWFDENC_HANDLE; + +typedef struct _EXYNOS_HEVCWFDENC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_HEVCTYPE HevcComponent[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + OMX_VIDEO_QPRANGE qpRangeI; + OMX_VIDEO_QPRANGE qpRangeP; + OMX_VIDEO_QPRANGE qpRangeB; + + OMX_U32 nMaxTemporalLayerCount; + OMX_U32 nMaxTemporalLayerCountForB; + OMX_U32 nTemporalLayerCount; + OMX_U32 nTemporalLayerCountForB; + OMX_BOOL bUseTemporalLayerBitrateRatio; + OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS]; + + /* SEC MFC Codec specific */ + EXYNOS_MFC_HEVCWFDENC_HANDLE hMFCHevcHandle; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_HEVCWFDENC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +OMX_ERRORTYPE Exynos_OMX_Port_Constructor(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_Port_Destructor(OMX_HANDLETYPE hComponent); +int Exynos_GetPlaneFromPort(EXYNOS_OMX_BASEPORT *pPort); +OMX_ERRORTYPE Exynos_SetPlaneToPort(EXYNOS_OMX_BASEPORT *pPort, int nPlaneNum); +OMX_ERRORTYPE Exynos_OMX_EmptyThisBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer); +OMX_ERRORTYPE Exynos_OMX_FillThisBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer); + + +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Constructor(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_BaseComponent_Destructor(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_Check_SizeVersion(OMX_PTR header, OMX_U32 size); + +void Exynos_UpdateFrameSize(OMX_COMPONENTTYPE *pOMXComponent); +void Exynos_Input_SetSupportFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +OMX_COLOR_FORMATTYPE Exynos_Input_GetActualColorFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +OMX_ERRORTYPE Exynos_ResetAllPortConfig(OMX_COMPONENTTYPE *pOMXComponent); +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentInit(OMX_IN OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OMX_VideoEncodeComponentDeinit(OMX_IN OMX_HANDLETYPE hComponent); + +OMX_ERRORTYPE Exynos_OMX_UseBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8 *pBuffer); +OMX_ERRORTYPE Exynos_OMX_AllocateBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE **ppBuffer, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes); +OMX_ERRORTYPE Exynos_OMX_FreeBuffer( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE *pBufferHdr); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/enc/hevcwfd/NOTICE b/openmax/component/video/enc/hevcwfd/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/enc/hevcwfd/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/enc/hevcwfd/library_register.c b/openmax/component/video/enc/hevcwfd/library_register.c new file mode 100644 index 0000000..f6d5623 --- /dev/null +++ b/openmax/component/video/enc/hevcwfd/library_register.c @@ -0,0 +1,62 @@ +/* + * + * Copyright 2017 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * ByungGwan Kang (bk0917.kang@samsung.com) + * @version 2.0.0 + * @history + * 2018.07.13 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" +#include "Exynos_OSAL_Log.h" + + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents) +{ + FunctionIn(); + + if (exynosComponents == NULL) + goto EXIT; + + /* component 1 - video Encoder HEVC */ + Exynos_OSAL_Strcpy(exynosComponents[0]->componentName, EXYNOS_OMX_COMPONENT_HEVC_WFD_ENC); + Exynos_OSAL_Strcpy(exynosComponents[0]->roles[0], EXYNOS_OMX_COMPONENT_HEVC_WFD_ENC_ROLE); + exynosComponents[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 2 - video Encoder HEVC for DRM */ + Exynos_OSAL_Strcpy(exynosComponents[1]->componentName, EXYNOS_OMX_COMPONENT_HEVC_WFD_DRM_ENC); + Exynos_OSAL_Strcpy(exynosComponents[1]->roles[0], EXYNOS_OMX_COMPONENT_HEVC_WFD_ENC_ROLE); + exynosComponents[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} + diff --git a/openmax/component/video/enc/hevcwfd/library_register.h b/openmax/component/video/enc/hevcwfd/library_register.h new file mode 100644 index 0000000..e729a67 --- /dev/null +++ b/openmax/component/video/enc/hevcwfd/library_register.h @@ -0,0 +1,58 @@ +/* + * + * Copyright 2017 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * ByungGwan Kang (bk0917.kang@samsung.com) + * @version 2.0.0 + * @history + * 2018.07.13 : Create + */ + +#ifndef EXYNOS_OMX_HEVC_WFD_REG +#define EXYNOS_OMX_HEVC_WFD_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 2 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* HEVC */ +#define EXYNOS_OMX_COMPONENT_HEVC_WFD_ENC "OMX.Exynos.HEVC.WFD.Encoder" +#define EXYNOS_OMX_COMPONENT_HEVC_WFD_DRM_ENC "OMX.Exynos.HEVC.WFD.Encoder.secure" +#define EXYNOS_OMX_COMPONENT_HEVC_WFD_ENC_ROLE "video_encoder.hevc-wfd" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/openmax/component/video/enc/mpeg4/Android.mk b/openmax/component/video/enc/mpeg4/Android.mk new file mode 100644 index 0000000..84962e6 --- /dev/null +++ b/openmax/component/video/enc/mpeg4/Android.mk @@ -0,0 +1,79 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Mpeg4enc.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.MPEG4.Encoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Venc libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/enc \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label -Wno-unused-function + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.c b/openmax/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.c new file mode 100644 index 0000000..f88d368 --- /dev/null +++ b/openmax/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.c @@ -0,0 +1,3638 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Mpeg4enc.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Venc.h" +#include "Exynos_OMX_VencControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Mpeg4enc.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OSAL_Queue.h" + +#include "Exynos_OSAL_Platform.h" + +#include "VendorVideoAPI.h" + +/* To use CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */ +/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_MPEG4_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pMpeg4Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pMpeg4Enc->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) { + pMpeg4Enc->hMFCMpeg4Handle.profiles[nProfileCnt++] = (int)OMX_VIDEO_MPEG4ProfileSimple; + pMpeg4Enc->hMFCMpeg4Handle.profiles[nProfileCnt++] = (int)OMX_VIDEO_MPEG4ProfileAdvancedSimple; + pMpeg4Enc->hMFCMpeg4Handle.nProfileCnt = nProfileCnt; + pMpeg4Enc->hMFCMpeg4Handle.maxLevel = (int)OMX_VIDEO_MPEG4Level5; + } else { + pMpeg4Enc->hMFCMpeg4Handle.profiles[nProfileCnt++] = (int)OMX_VIDEO_H263ProfileBaseline; + pMpeg4Enc->hMFCMpeg4Handle.nProfileCnt = nProfileCnt; + pMpeg4Enc->hMFCMpeg4Handle.maxLevel = (int)OMX_VIDEO_H263Level70; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + + int nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pMpeg4Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pMpeg4Enc->hMFCMpeg4Handle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pMpeg4Enc->hMFCMpeg4Handle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pMpeg4Enc->hMFCMpeg4Handle.maxLevel; +#else + while ((pMpeg4Enc->hMFCMpeg4Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pMpeg4Enc->hMFCMpeg4Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pMpeg4Enc->hMFCMpeg4Handle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pMpeg4Enc->hMFCMpeg4Handle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pMpeg4Enc == NULL) + goto EXIT; + + while ((pMpeg4Enc->hMFCMpeg4Handle.maxLevel >> nLevelCnt++) > 0); + + if ((pMpeg4Enc->hMFCMpeg4Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pMpeg4Enc->hMFCMpeg4Handle.nProfileCnt; i++) { + if (pMpeg4Enc->hMFCMpeg4Handle.profiles[i] == (int)pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +static OMX_U32 OMXMpeg4ProfileToMFCProfile(OMX_VIDEO_MPEG4PROFILETYPE profile) +{ + OMX_U32 ret; + + switch (profile) { + case OMX_VIDEO_MPEG4ProfileSimple: + ret = 0; + break; + case OMX_VIDEO_MPEG4ProfileAdvancedSimple: + ret = 1; + break; + default: + ret = 0; + }; + + return ret; +} + +static OMX_U32 OMXMpeg4LevelToMFCLevel(OMX_VIDEO_MPEG4LEVELTYPE level) +{ + OMX_U32 ret; + + switch (level) { + case OMX_VIDEO_MPEG4Level0: + ret = 0; + break; + case OMX_VIDEO_MPEG4Level0b: + ret = 1; + break; + case OMX_VIDEO_MPEG4Level1: + ret = 2; + break; + case OMX_VIDEO_MPEG4Level2: + ret = 3; + break; + case OMX_VIDEO_MPEG4Level3: + ret = 4; + break; + case OMX_VIDEO_MPEG4Level4: + case OMX_VIDEO_MPEG4Level4a: + ret = 6; + break; + case OMX_VIDEO_MPEG4Level5: + ret = 7; + break; + default: + ret = 0; + }; + + return ret; +} + +static void Print_Mpeg4Enc_Param(ExynosVideoEncParam *pEncParam) +{ + ExynosVideoEncCommonParam *pCommonParam = &pEncParam->commonParam; + ExynosVideoEncMpeg4Param *pMpeg4Param = &pEncParam->codecParam.mpeg4; + + /* common parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceWidth : %d", pCommonParam->SourceWidth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceHeight : %d", pCommonParam->SourceHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "IDRPeriod : %d", pCommonParam->IDRPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SliceMode : %d", pCommonParam->SliceMode); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RandomIntraMBRefresh : %d", pCommonParam->RandomIntraMBRefresh); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Bitrate : %d", pCommonParam->Bitrate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp : %d", pCommonParam->FrameQp); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_P : %d", pCommonParam->FrameQp_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(I) ranege : %d / %d", pCommonParam->QpRange.QpMin_I, pCommonParam->QpRange.QpMax_I); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(P) ranege : %d / %d", pCommonParam->QpRange.QpMin_P, pCommonParam->QpRange.QpMax_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(B) ranege : %d / %d", pCommonParam->QpRange.QpMin_B, pCommonParam->QpRange.QpMax_B); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DropControl : %d", pCommonParam->bDropControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DisableDFR : %d", pCommonParam->bDisableDFR); + + /* Mpeg4 specific parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "ProfileIDC : %d", pMpeg4Param->ProfileIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LevelIDC : %d", pMpeg4Param->LevelIDC); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_B : %d", pMpeg4Param->FrameQp_B); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "TimeIncreamentRes : %d", pMpeg4Param->TimeIncreamentRes); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "VopTimeIncreament : %d", pMpeg4Param->VopTimeIncreament); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SliceArgument : %d", pMpeg4Param->SliceArgument); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberBFrames : %d", pMpeg4Param->NumberBFrames); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "DisableQpelME : %d", pMpeg4Param->DisableQpelME); + + /* rate control related parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableFRMRateControl : %d", pCommonParam->EnableFRMRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableMBRateControl : %d", pCommonParam->EnableMBRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CBRPeriodRf : %d", pCommonParam->CBRPeriodRf); +} + +static void Print_H263Enc_Param(ExynosVideoEncParam *pEncParam) +{ + ExynosVideoEncCommonParam *pCommonParam = &pEncParam->commonParam; + ExynosVideoEncH263Param *pH263Param = &pEncParam->codecParam.h263; + + /* common parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceWidth : %d", pCommonParam->SourceWidth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceHeight : %d", pCommonParam->SourceHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "IDRPeriod : %d", pCommonParam->IDRPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SliceMode : %d", pCommonParam->SliceMode); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RandomIntraMBRefresh : %d", pCommonParam->RandomIntraMBRefresh); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Bitrate : %d", pCommonParam->Bitrate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp : %d", pCommonParam->FrameQp); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_P : %d", pCommonParam->FrameQp_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(I) ranege : %d / %d", pCommonParam->QpRange.QpMin_I, pCommonParam->QpRange.QpMax_I); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(P) ranege : %d / %d", pCommonParam->QpRange.QpMin_P, pCommonParam->QpRange.QpMax_P); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DropControl : %d", pCommonParam->bDropControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DisableDFR : %d", pCommonParam->bDisableDFR); + + /* H263 specific parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameRate : %d", pH263Param->FrameRate); + + /* rate control related parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableFRMRateControl : %d", pCommonParam->EnableFRMRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableMBRateControl : %d", pCommonParam->EnableMBRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CBRPeriodRf : %d", pCommonParam->CBRPeriodRf); +} + +static void Set_Mpeg4Enc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + EXYNOS_MFC_MPEG4ENC_HANDLE *pMFCMpeg4Handle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncMpeg4Param *pMpeg4Param = NULL; + + OMX_S32 nWidth, nHeight; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCMpeg4Handle = &pMpeg4Enc->hMFCMpeg4Handle; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pEncParam = &pMFCMpeg4Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pMpeg4Param = &pEncParam->codecParam.mpeg4; + pEncParam->eCompressionFormat = VIDEO_CODING_MPEG4; + + /* uses specified target size instead of size on output port */ + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + nWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + + /* common parameters */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + pCommonParam->SourceWidth = nWidth; + pCommonParam->SourceHeight = nHeight; + } else { + pCommonParam->SourceWidth = nHeight; + pCommonParam->SourceHeight = nWidth; + } + + pCommonParam->IDRPeriod = pMpeg4Enc->mpeg4Component[OUTPUT_PORT_INDEX].nPFrames + 1; + pCommonParam->SliceMode = 0; + pCommonParam->Bitrate = pOutputPort->portDefinition.format.video.nBitrate; + pCommonParam->FrameQp = pVideoEnc->quantization.nQpI; + pCommonParam->FrameQp_P = pVideoEnc->quantization.nQpP; + + pCommonParam->QpRange.QpMin_I = pMpeg4Enc->qpRangeI.nMinQP; + pCommonParam->QpRange.QpMax_I = pMpeg4Enc->qpRangeI.nMaxQP; + pCommonParam->QpRange.QpMin_P = pMpeg4Enc->qpRangeP.nMinQP; + pCommonParam->QpRange.QpMax_P = pMpeg4Enc->qpRangeP.nMaxQP; + pCommonParam->QpRange.QpMin_B = pMpeg4Enc->qpRangeB.nMinQP; + pCommonParam->QpRange.QpMax_B = pMpeg4Enc->qpRangeB.nMaxQP; + + pCommonParam->PadControlOn = 0; /* 0: Use boundary pixel, 1: Use the below setting value */ + pCommonParam->LumaPadVal = 0; + pCommonParam->CbPadVal = 0; + pCommonParam->CrPadVal = 0; + + if (pVideoEnc->intraRefresh.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic) { + /* Cyclic Mode */ + pCommonParam->RandomIntraMBRefresh = pVideoEnc->intraRefresh.nCirMBs; + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + + /* Perceptual Mode MPEG4/H263 does not support */ + pCommonParam->PerceptualMode = VIDEO_FALSE; + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + pCommonParam->bDropControl = (pVideoEnc->bDropControl)? VIDEO_TRUE:VIDEO_FALSE; + pCommonParam->bDisableDFR = (pVideoEnc->bDisableDFR)? VIDEO_TRUE:VIDEO_FALSE; + + /* Mpeg4 specific parameters */ + pMpeg4Param->ProfileIDC = OMXMpeg4ProfileToMFCProfile(pMpeg4Enc->mpeg4Component[OUTPUT_PORT_INDEX].eProfile); + pMpeg4Param->LevelIDC = OMXMpeg4LevelToMFCLevel(pMpeg4Enc->mpeg4Component[OUTPUT_PORT_INDEX].eLevel); + pMpeg4Param->FrameQp_B = pVideoEnc->quantization.nQpB; + pMpeg4Param->TimeIncreamentRes = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + pMpeg4Param->VopTimeIncreament = 1; + pMpeg4Param->SliceArgument = 0; /* MB number or byte number */ + pMpeg4Param->NumberBFrames = pMpeg4Enc->mpeg4Component[OUTPUT_PORT_INDEX].nBFrames; /* 0 ~ 2 */ + pMpeg4Param->DisableQpelME = 1; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eControlRate: 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]); + /* rate control related parameters */ + switch ((int)pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]) { + case OMX_Video_ControlRateDisable: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode DBR"); + pCommonParam->EnableFRMRateControl = 0; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 0; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + case OMX_Video_ControlRateConstant: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 9; + break; + case OMX_Video_ControlRateVariable: + default: /*Android default */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode VBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + } + +// Print_Mpeg4Enc_Param(pEncParam); +} + +static void Set_H263Enc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + EXYNOS_MFC_MPEG4ENC_HANDLE *pMFCMpeg4Handle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH263Param *pH263Param = NULL; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pMpeg4Enc = pVideoEnc->hCodecHandle; + pMFCMpeg4Handle = &pMpeg4Enc->hMFCMpeg4Handle; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pEncParam = &pMFCMpeg4Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pH263Param = &pEncParam->codecParam.h263; + pEncParam->eCompressionFormat = VIDEO_CODING_H263; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "eCompressionFormat: %d", pEncParam->eCompressionFormat); + + /* common parameters */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + pCommonParam->SourceWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + pCommonParam->SourceHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } else { + pCommonParam->SourceWidth = pOutputPort->portDefinition.format.video.nFrameHeight; + pCommonParam->SourceHeight = pOutputPort->portDefinition.format.video.nFrameWidth; + } + pCommonParam->IDRPeriod = pMpeg4Enc->h263Component[OUTPUT_PORT_INDEX].nPFrames + 1; + pCommonParam->SliceMode = 0; + pCommonParam->Bitrate = pOutputPort->portDefinition.format.video.nBitrate; + pCommonParam->FrameQp = pVideoEnc->quantization.nQpI; + pCommonParam->FrameQp_P = pVideoEnc->quantization.nQpP; + + pCommonParam->QpRange.QpMin_I = pMpeg4Enc->qpRangeI.nMinQP; + pCommonParam->QpRange.QpMax_I = pMpeg4Enc->qpRangeI.nMaxQP; + pCommonParam->QpRange.QpMin_P = pMpeg4Enc->qpRangeP.nMinQP; + pCommonParam->QpRange.QpMax_P = pMpeg4Enc->qpRangeP.nMaxQP; + + pCommonParam->PadControlOn = 0; /* 0: Use boundary pixel, 1: Use the below setting value */ + pCommonParam->LumaPadVal = 0; + pCommonParam->CbPadVal = 0; + pCommonParam->CrPadVal = 0; + + if (pVideoEnc->intraRefresh.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic) { + /* Cyclic Mode */ + pCommonParam->RandomIntraMBRefresh = pVideoEnc->intraRefresh.nCirMBs; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "RandomIntraMBRefresh: %d", pCommonParam->RandomIntraMBRefresh); + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + + /* Perceptual Mode MPEG4 H263 does not support */ + pCommonParam->PerceptualMode = VIDEO_FALSE; + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + /* H263 specific parameters */ + pH263Param->FrameRate = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eControlRate: 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]); + /* rate control related parameters */ + switch (pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]) { + case OMX_Video_ControlRateDisable: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode DBR"); + pCommonParam->EnableFRMRateControl = 0; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 0; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + case OMX_Video_ControlRateConstant: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 9; + break; + case OMX_Video_ControlRateVariable: + default: /*Android default */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode VBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 100; + break; + } + +// Print_H263Enc_Param(pEncParam); +} + +static void Change_Mpeg4Enc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + EXYNOS_MFC_MPEG4ENC_HANDLE *pMFCMpeg4Handle = NULL; + OMX_PTR pDynamicConfigCMD = NULL; + OMX_PTR pConfigData = NULL; + OMX_S32 nCmdIndex = 0; + ExynosVideoEncOps *pEncOps = NULL; + int nValue = 0; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCMpeg4Handle = &pMpeg4Enc->hMFCMpeg4Handle; + pEncOps = pMFCMpeg4Handle->pEncOps; + + pDynamicConfigCMD = (OMX_PTR)Exynos_OSAL_Dequeue(&pExynosComponent->dynamicConfigQ); + if (pDynamicConfigCMD == NULL) + goto EXIT; + + nCmdIndex = *(OMX_S32 *)pDynamicConfigCMD; + pConfigData = (OMX_PTR)((OMX_U8 *)pDynamicConfigCMD + sizeof(OMX_S32)); + + switch ((int)nCmdIndex) { + case OMX_IndexConfigVideoIntraVOPRefresh: + { + nValue = VIDEO_FRAME_I; + pEncOps->Set_FrameType(pMFCMpeg4Handle->hMFCHandle, nValue); + pVideoEnc->IntraRefreshVOP = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] VOP Refresh", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_S32 nPFrames = (*((OMX_U32 *)pConfigData)) - 1; + nValue = nPFrames + 1; + pEncOps->Set_IDRPeriod(pMFCMpeg4Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] IDR period: %d", pExynosComponent, __FUNCTION__, nValue); + } + break; + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pConfigData; + + if (pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] != OMX_Video_ControlRateDisable) { + nValue = pConfigBitrate->nEncodeBitrate; + pEncOps->Set_BitRate(pMFCMpeg4Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bitrate: %d", pExynosComponent, __FUNCTION__, nValue); + } + } + break; + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pConfigData; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + + if (nPortIndex == INPUT_PORT_INDEX) { + nValue = (pConfigFramerate->xEncodeFramerate) >> 16; + pEncOps->Set_FrameRate(pMFCMpeg4Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] framerate: %d", pExynosComponent, __FUNCTION__, nValue); + } + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pConfigData; + ExynosVideoQPRange qpRange; + + qpRange.QpMin_I = pQpRange->qpRangeI.nMinQP; + qpRange.QpMax_I = pQpRange->qpRangeI.nMaxQP; + qpRange.QpMin_P = pQpRange->qpRangeP.nMinQP; + qpRange.QpMax_P = pQpRange->qpRangeP.nMaxQP; + qpRange.QpMin_B = pQpRange->qpRangeB.nMinQP; + qpRange.QpMax_B = pQpRange->qpRangeB.nMaxQP; + + pEncOps->Set_QpRange(pMFCMpeg4Handle->hMFCHandle, qpRange); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qp range: I(%d, %d), P(%d, %d), B(%d, %d)", + pExynosComponent, __FUNCTION__, + qpRange.QpMin_I, qpRange.QpMax_I, + qpRange.QpMin_P, qpRange.QpMax_P, + qpRange.QpMin_B, qpRange.QpMax_B); + } + break; + case OMX_IndexConfigOperatingRate: + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pConfigData; + OMX_U32 xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + + nValue = pConfigRate->nU32 >> 16; + + if (pMFCMpeg4Handle->videoInstInfo.supportInfo.enc.bOperatingRateSupport == VIDEO_TRUE) { + if (nValue == ((OMX_U32)INT_MAX >> 16)) { + nValue = (OMX_U32)INT_MAX; + } else { + nValue = nValue * 1000; + } + + pEncOps->Set_OperatingRate(pMFCMpeg4Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] operating rate: 0x%x", pExynosComponent, __FUNCTION__, nValue); + } else { + if (nValue == (((OMX_U32)INT_MAX) >> 16)) { + nValue = 1000; + } else { + nValue = ((xFramerate >> 16) == 0)? 100:(OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + } + + pEncOps->Set_QosRatio(pMFCMpeg4Handle->hMFCHandle, nValue); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qos ratio: 0x%x", pExynosComponent, __FUNCTION__, nValue); + } + + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; + case OMX_IndexConfigCommonOutputSize: + { + OMX_FRAMESIZETYPE *pFrameSize = (OMX_FRAMESIZETYPE *)pConfigData; + OMX_CONFIG_RECTTYPE *pTargetFrame = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].cropRectangle[IMG_CROP_OUTPUT_PORT]); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] resolution(%d x %d) is changed to (%d x %d)", pExynosComponent, __FUNCTION__, + pTargetFrame->nWidth, pTargetFrame->nHeight, + pFrameSize->nWidth, pFrameSize->nHeight); + + /* update target size */ + pTargetFrame->nTop = 0; + pTargetFrame->nLeft = 0; + pTargetFrame->nWidth = pFrameSize->nWidth; + pTargetFrame->nHeight = pFrameSize->nHeight; + + pVideoEnc->bEncDRC = OMX_TRUE; + } + break; + default: + break; + } + + Exynos_OSAL_Free(pDynamicConfigCMD); + + if (pMpeg4Enc->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) + Set_Mpeg4Enc_Param(pExynosComponent); + else + Set_H263Enc_Param(pExynosComponent); + +EXIT: + return; +} + +OMX_ERRORTYPE GetCodecOutputPrivateData( + OMX_PTR pCodecBuffer, + OMX_PTR *pVirtAddr, + OMX_U32 *pDataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pVideoBuffer = NULL; + + if (pCodecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoBuffer = (ExynosVideoBuffer *)pCodecBuffer; + + if (pVirtAddr != NULL) + *pVirtAddr = pVideoBuffer->planes[0].addr; + + if (pDataSize != NULL) + *pDataSize = pVideoBuffer->planes[0].allocSize; + +EXIT: + return ret; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pMpeg4Enc == NULL) + goto EXIT; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecOpen( + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc, + ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pMpeg4Enc == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pEncOps = (ExynosVideoEncOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncOps)); + pInbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + pOutbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + + if ((pEncOps == NULL) || + (pInbufOps == NULL) || + (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pMpeg4Enc->hMFCMpeg4Handle.pEncOps = pEncOps; + pMpeg4Enc->hMFCMpeg4Handle.pInbufOps = pInbufOps; + pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pEncOps->nSize = sizeof(ExynosVideoEncOps); + pInbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + + if (Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for encoder ops */ + if ((pEncOps->Init == NULL) || + (pEncOps->Finalize == NULL) || + (pEncOps->Set_FrameTag == NULL) || + (pEncOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.pEncOps->Init(pVideoInstInfo); + if (pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pMpeg4Enc->hMFCMpeg4Handle.pEncOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pMpeg4Enc->hMFCMpeg4Handle.pInbufOps = NULL; + } + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecClose(EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pMpeg4Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle; + pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + + if (hMFCHandle != NULL) { + pEncOps->Finalize(hMFCHandle); + hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle = NULL; + pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCSrc = OMX_FALSE; + pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Encoder(pEncOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps = NULL; + } + + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecStart( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pMpeg4Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle; + pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + + if (nPortIndex == INPUT_PORT_INDEX) + pInbufOps->Run(hMFCHandle); + else if (nPortIndex == OUTPUT_PORT_INDEX) + pOutbufOps->Run(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecStop( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pMpeg4Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle; + pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) + pInbufOps->Stop(hMFCHandle); + else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) + pOutbufOps->Stop(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecOutputBufferProcessRun( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pMpeg4Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pMpeg4Enc->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pMpeg4Enc->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pMpeg4Enc->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pMpeg4Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pMpeg4Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecEnqueueAllBuffer( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle; + + ExynosVideoEncBufferOps *pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + + int i; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && + (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pMpeg4Enc->bSourceStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoEnc->pMFCEncInputBuffer[i]->fd[0], pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, INPUT_PORT_INDEX, pVideoEnc->pMFCEncInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pMpeg4Enc->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoEnc->pMFCEncOutputBuffer[i]->fd[0], pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoEnc->pMFCEncOutputBuffer[i]); + } + + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + +void Mpeg4CodecSetHdrInfo(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_MPEG4ENC_HANDLE *pMFCMpeg4Handle = &pMpeg4Enc->hMFCMpeg4Handle; + void *hMFCHandle = pMFCMpeg4Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + + OMX_COLOR_FORMATTYPE eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + if (pMFCMpeg4Handle->videoInstInfo.supportInfo.enc.bColorAspectsSupport == VIDEO_TRUE) { + ExynosVideoColorAspects BSCA; + Exynos_OSAL_Memset(&BSCA, 0, sizeof(BSCA)); + +#ifdef USE_ANDROID + if (pVideoEnc->surfaceFormat == eColorFormat) { + Exynos_OSAL_GetColorAspectsForBitstream(&(pInputPort->ColorAspects), &(pOutputPort->ColorAspects)); + + /* in case of RGBA, re-update suitable values(transfer) */ + if (pVideoEnc->surfaceFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888) { + /* Eventhough frameworks already sent ColorAspects, + * sometimes dataspace has not set to OMX component because of timing. + * So get dataspace from frameworks ColorAspects. + */ + if (pInputPort->ColorAspects.nDataSpace == 0) { + Exynos_OSAL_UpdateDataSpaceFromAspects(&(pInputPort->ColorAspects)); + } + Exynos_OSAL_GetRGBColorTypeForBitStream(&pOutputPort->ColorAspects, pInputPort->ColorAspects.nDataSpace, eColorFormat); + } + } else { + /* in case of RGBA->YUV, color aspects for bitstream is already updated */ + if (pVideoEnc->surfaceFormat != (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888) + Exynos_OSAL_GetColorAspectsForBitstream(&(pInputPort->ColorAspects), &(pOutputPort->ColorAspects)); + } +#endif + + BSCA.eRangeType = (ExynosRangeType)pOutputPort->ColorAspects.nRangeType; + BSCA.ePrimariesType = (ExynosPrimariesType)pOutputPort->ColorAspects.nPrimaryType; + BSCA.eTransferType = (ExynosTransferType)pOutputPort->ColorAspects.nTransferType; + BSCA.eCoeffType = (ExynosMatrixCoeffType)pOutputPort->ColorAspects.nCoeffType; + + pEncOps->Set_ColorAspects(hMFCHandle, &BSCA); + } + + return ; +} + +OMX_ERRORTYPE Mpeg4CodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_MPEG4ENC_HANDLE *pMFCMpeg4Handle = &pMpeg4Enc->hMFCMpeg4Handle; + void *hMFCHandle = pMFCMpeg4Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + ExynosVideoEncOps *pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + ExynosVideoGeometry bufferConf; + + FunctionIn(); + + pVideoEnc->bEncDRCSync = OMX_TRUE; + + /* stream off */ + ret = Mpeg4CodecStop(pOMXComponent, INPUT_PORT_INDEX); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Mpeg4CodecStop() about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_SignalWait(pVideoEnc->hEncDRCSyncEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pVideoEnc->hEncDRCSyncEvent); + + /* get input buffer geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + if (pInbufOps->Get_Geometry) { + if (pInbufOps->Get_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + /* clear information */ + pInbufOps->Clear_RegisteredBuffer(hMFCHandle); + pInbufOps->Cleanup_Buffer(hMFCHandle); + + /* set input buffer geometry */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + bufferConf.nFrameHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + bufferConf.nStride = ALIGN(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth, 16); + } else { + bufferConf.nFrameWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + bufferConf.nFrameHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + bufferConf.nStride = ALIGN(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight, 16); + } + + if (pInbufOps->Set_Geometry) { + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, MAX_INPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + /* header with IDR */ + if (pEncOps->Set_HeaderMode(hMFCHandle, VIDEO_FALSE) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set header mode", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + /* stream on */ + Mpeg4CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + /* reset buffer queue */ + Mpeg4CodecEnqueueAllBuffer(pOMXComponent, INPUT_PORT_INDEX); + + /* clear timestamp */ + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + + /* reinitialize a value for reconfiguring CSC */ + pVideoEnc->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecSrcSetup( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_MPEG4ENC_HANDLE *pMFCMpeg4Handle = &pMpeg4Enc->hMFCMpeg4Handle; + void *hMFCHandle = pMFCMpeg4Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoEncOps *pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + ExynosVideoEncParam *pEncParam = NULL; + + ExynosVideoGeometry bufferConf; + OMX_U32 inputBufferNumber = 0; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pMpeg4Enc->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pMpeg4Enc->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_OSAL_SignalSet(pMpeg4Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pMpeg4Enc->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) + Set_Mpeg4Enc_Param(pExynosComponent); + else + Set_H263Enc_Param(pExynosComponent); + + pEncParam = &pMFCMpeg4Handle->encParam; + if (pEncOps->Set_EncParam) { + if(pEncOps->Set_EncParam(pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle, pEncParam) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set encParam", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + Print_Mpeg4Enc_Param(pEncParam); + +#ifdef USE_ANDROID + Mpeg4CodecSetHdrInfo(pOMXComponent); +#endif + + if (pMFCMpeg4Handle->videoInstInfo.supportInfo.enc.bPrioritySupport == VIDEO_TRUE) + pEncOps->Set_Priority(hMFCHandle, pVideoEnc->nPriority); + + if (pEncParam->commonParam.bDisableDFR == VIDEO_TRUE) + pEncOps->Disable_DynamicFrameRate(pMFCMpeg4Handle->hMFCHandle, VIDEO_TRUE); + + /* input buffer info: only 3 config values needed */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eColorFormat = pEncParam->commonParam.FrameMap; + + { + OMX_S32 nTargetWidth, nTargetHeight; + + /* uses specified target size instead of size on output port */ + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + /* use specified resolution */ + nTargetWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nTargetHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nTargetWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nTargetHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = nTargetWidth; + bufferConf.nFrameHeight = nTargetHeight; + bufferConf.nStride = ALIGN(nTargetWidth, 16); + } else { + bufferConf.nFrameWidth = nTargetHeight; + bufferConf.nFrameHeight = nTargetWidth; + bufferConf.nStride = ALIGN(nTargetHeight, 16); + } + } + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + pInbufOps->Set_Shareable(hMFCHandle); + inputBufferNumber = MAX_INPUTBUFFER_NUM_DYNAMIC; + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry) { + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, inputBufferNumber) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pInputPort->bufferProcessType & BUFFER_SHARE) && + (pInputPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + /* data buffer */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCSrc = OMX_TRUE; + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_MPEG4ENC_HANDLE *pMFCMpeg4Handle = &pMpeg4Enc->hMFCMpeg4Handle; + void *hMFCHandle = pMFCMpeg4Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + unsigned int nDataLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + int i, nOutBufSize = 0, nOutputBufferCnt = 0; + + FunctionIn(); + + nOutBufSize = pOutputPort->portDefinition.nBufferSize; + if ((pOutputPort->bufferProcessType & BUFFER_COPY) || + (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nOutBufSize = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * + pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nOutBufSize = Exynos_OSAL_GetOutBufferSize(pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.nBufferSize); +#endif + + } + + /* set geometry for output (dst) */ + if (pOutbufOps->Set_Geometry) { + /* only 2 config values needed */ + if (pMpeg4Enc->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) + bufferConf.eCompressionFormat = VIDEO_CODING_MPEG4; + else + bufferConf.eCompressionFormat = VIDEO_CODING_H263; + bufferConf.nSizeImage = nOutBufSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + + if (pOutbufOps->Set_Geometry(pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pOutputPort->bufferProcessType & BUFFER_COPY) + nOutputBufferCnt = MFC_OUTPUT_BUFFER_NUM_MAX; + else + nOutputBufferCnt = pOutputPort->portDefinition.nBufferCountActual; + + if (pOutbufOps->Setup(pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle, nOutputBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + nAllocLen[0] = nOutBufSize; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, MFC_OUTPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Allocate_CodecBuffers for output", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + /* Enqueue output buffer */ + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoEnc->pMFCEncOutputBuffer[i]->fd, + pVideoEnc->pMFCEncOutputBuffer[i]->bufferSize, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + NULL); + } + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /* Register output buffer */ + /*************/ + /* TBD */ + /*************/ + } + + pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_TRUE; + + if (Mpeg4CodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nParamIndex %x", pExynosComponent, __FUNCTION__, (int)nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoMpeg4: + { + OMX_VIDEO_PARAM_MPEG4TYPE *pDstMpeg4Component = (OMX_VIDEO_PARAM_MPEG4TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG4TYPE *pSrcMpeg4Component = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstMpeg4Component, sizeof(OMX_VIDEO_PARAM_MPEG4TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstMpeg4Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcMpeg4Component = &pMpeg4Enc->mpeg4Component[pDstMpeg4Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstMpeg4Component) + nOffset, + ((char *)pSrcMpeg4Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_MPEG4TYPE) - nOffset); + } + break; + case OMX_IndexParamVideoH263: + { + OMX_VIDEO_PARAM_H263TYPE *pDstH263Component = (OMX_VIDEO_PARAM_H263TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_H263TYPE *pSrcH263Component = NULL; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstH263Component, sizeof(OMX_VIDEO_PARAM_H263TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstH263Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcH263Component = &pMpeg4Enc->h263Component[pDstH263Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstH263Component) + nOffset, + ((char *)pSrcH263Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_H263TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_S32 codecType = pMpeg4Enc->hMFCMpeg4Handle.codecType; + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (codecType == CODEC_TYPE_MPEG4) + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_MPEG4_ENC_ROLE); + else + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H263_ENC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG4TYPE *pSrcMpeg4Component = NULL; + OMX_VIDEO_PARAM_H263TYPE *pSrcH263Component = NULL; + OMX_S32 codecType = pMpeg4Enc->hMFCMpeg4Handle.codecType; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (codecType == CODEC_TYPE_MPEG4) { + pSrcMpeg4Component = &pMpeg4Enc->mpeg4Component[pDstProfileLevel->nPortIndex]; + pDstProfileLevel->eProfile = pSrcMpeg4Component->eProfile; + pDstProfileLevel->eLevel = pSrcMpeg4Component->eLevel; + } else { + pSrcH263Component = &pMpeg4Enc->h263Component[pDstProfileLevel->nPortIndex]; + pDstProfileLevel->eProfile = pSrcH263Component->eProfile; + pDstProfileLevel->eLevel = pSrcH263Component->eLevel; + } + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pMpeg4Enc->errorCorrectionType[OUTPUT_PORT_INDEX]; + + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + OMX_S32 codecType = pMpeg4Enc->hMFCMpeg4Handle.codecType; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pMpeg4Enc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pMpeg4Enc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pMpeg4Enc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pMpeg4Enc->qpRangeP.nMaxQP; + + if (codecType == CODEC_TYPE_MPEG4) { + pQpRange->qpRangeB.nMinQP = pMpeg4Enc->qpRangeB.nMinQP; + pQpRange->qpRangeB.nMaxQP = pMpeg4Enc->qpRangeB.nMaxQP; + } + } + break; + default: + ret = Exynos_OMX_VideoEncodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoMpeg4: + { + OMX_VIDEO_PARAM_MPEG4TYPE *pDstMpeg4Component = NULL; + OMX_VIDEO_PARAM_MPEG4TYPE *pSrcMpeg4Component = (OMX_VIDEO_PARAM_MPEG4TYPE *)pComponentParameterStructure; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcMpeg4Component, sizeof(OMX_VIDEO_PARAM_MPEG4TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcMpeg4Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstMpeg4Component = &pMpeg4Enc->mpeg4Component[pSrcMpeg4Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstMpeg4Component) + nOffset, + ((char *)pSrcMpeg4Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_MPEG4TYPE) - nOffset); + + if (pDstMpeg4Component->nBFrames > 2) { /* 0 ~ 2 */ + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] nBFrames(%d) is over a maximum value(2). it is limited to max", + pExynosComponent, __FUNCTION__, pDstMpeg4Component->nBFrames); + pDstMpeg4Component->nBFrames = 2; + } + } + break; + case OMX_IndexParamVideoH263: + { + OMX_VIDEO_PARAM_H263TYPE *pDstH263Component = NULL; + OMX_VIDEO_PARAM_H263TYPE *pSrcH263Component = (OMX_VIDEO_PARAM_H263TYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcH263Component, sizeof(OMX_VIDEO_PARAM_H263TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcH263Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstH263Component = &pMpeg4Enc->h263Component[pSrcH263Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstH263Component) + nOffset, + ((char *)pSrcH263Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_H263TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_MPEG4_ENC_ROLE)) { + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4; + //((EXYNOS_MPEG4ENC_HANDLE *)(((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle))->hMFCMpeg4Handle.codecType = CODEC_TYPE_MPEG4; + } else if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_H263_ENC_ROLE)) { + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingH263; + //((EXYNOS_MPEG4ENC_HANDLE *)(((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle))->hMFCMpeg4Handle.codecType = CODEC_TYPE_H263; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG4TYPE *pDstMpeg4Component = NULL; + OMX_VIDEO_PARAM_H263TYPE *pDstH263Component = NULL; + OMX_S32 codecType = pMpeg4Enc->hMFCMpeg4Handle.codecType; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (codecType == CODEC_TYPE_MPEG4) { + /* + * To do: Check validity of profile & level parameters + */ + + pDstMpeg4Component = &pMpeg4Enc->mpeg4Component[pSrcProfileLevel->nPortIndex]; + pDstMpeg4Component->eProfile = pSrcProfileLevel->eProfile; + pDstMpeg4Component->eLevel = pSrcProfileLevel->eLevel; + } else { + /* + * To do: Check validity of profile & level parameters + */ + + pDstH263Component = &pMpeg4Enc->h263Component[pSrcProfileLevel->nPortIndex]; + pDstH263Component->eProfile = pSrcProfileLevel->eProfile; + pDstH263Component->eLevel = pSrcProfileLevel->eLevel; + } + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pMpeg4Enc->errorCorrectionType[OUTPUT_PORT_INDEX]; + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + OMX_S32 codecType = pMpeg4Enc->hMFCMpeg4Handle.codecType; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP) || + ((codecType == CODEC_TYPE_MPEG4) && + (pQpRange->qpRangeB.nMinQP > pQpRange->qpRangeB.nMaxQP))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d], B[min:%d, max:%d])", __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP, + pQpRange->qpRangeB.nMinQP, pQpRange->qpRangeB.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMpeg4Enc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pMpeg4Enc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pMpeg4Enc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pMpeg4Enc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + + if (codecType == CODEC_TYPE_MPEG4) { + pMpeg4Enc->qpRangeB.nMinQP = pQpRange->qpRangeB.nMinQP; + pMpeg4Enc->qpRangeB.nMaxQP = pQpRange->qpRangeB.nMaxQP; + } + } + break; + default: + ret = Exynos_OMX_VideoEncodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_GetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + OMX_S32 codecType = pMpeg4Enc->hMFCMpeg4Handle.codecType; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pMpeg4Enc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pMpeg4Enc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pMpeg4Enc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pMpeg4Enc->qpRangeP.nMaxQP; + + if (codecType == CODEC_TYPE_MPEG4) { + pQpRange->qpRangeB.nMinQP = pMpeg4Enc->qpRangeB.nMinQP; + pQpRange->qpRangeB.nMaxQP = pMpeg4Enc->qpRangeB.nMaxQP; + } + } + break; + default: + ret = Exynos_OMX_VideoEncodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_SetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + OMX_S32 codecType = pMpeg4Enc->hMFCMpeg4Handle.codecType; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP) || + ((codecType == CODEC_TYPE_MPEG4) && + (pQpRange->qpRangeB.nMinQP > pQpRange->qpRangeB.nMaxQP))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d], B[min:%d, max:%d])", + pExynosComponent, __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP, + pQpRange->qpRangeB.nMinQP, pQpRange->qpRangeB.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_FALSE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] only I-frame's QP range is applied", pExynosComponent, __FUNCTION__); + + pMpeg4Enc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pMpeg4Enc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pMpeg4Enc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pMpeg4Enc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + + if (codecType == CODEC_TYPE_MPEG4) { + pMpeg4Enc->qpRangeB.nMinQP = pQpRange->qpRangeB.nMinQP; + pMpeg4Enc->qpRangeB.nMaxQP = pQpRange->qpRangeB.nMaxQP; + } + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_U32 nPFrames = (*((OMX_U32 *)pComponentConfigStructure)) - 1; + + if (pMpeg4Enc->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) + pMpeg4Enc->mpeg4Component[OUTPUT_PORT_INDEX].nPFrames = nPFrames; + else + pMpeg4Enc->h263Component[OUTPUT_PORT_INDEX].nPFrames = nPFrames; + + ret = OMX_ErrorNone; + } + break; + default: + ret = Exynos_OMX_VideoEncodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + OMX_PTR pDynamicConfigCMD = NULL; + pDynamicConfigCMD = Exynos_OMX_MakeDynamicConfig(nIndex, pComponentConfigStructure); + Exynos_OSAL_Queue(&pExynosComponent->dynamicConfigQ, (void *)pDynamicConfigCMD); + } + + if (ret == (OMX_ERRORTYPE)OMX_ErrorNoneExpiration) + ret = OMX_ErrorNone; + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = Exynos_OMX_VideoEncodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_ComponentRoleEnum( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_U8 *cRole, + OMX_IN OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_S32 codecType; + + FunctionIn(); + + if ((hComponent == NULL) || + (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex != (MAX_COMPONENT_ROLE_NUM - 1)) { /* supports only one role */ + ret = OMX_ErrorNoMore; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + codecType = ((EXYNOS_MPEG4ENC_HANDLE *)(((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle))->hMFCMpeg4Handle.codecType; + if (codecType == CODEC_TYPE_MPEG4) + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_MPEG4_ENC_ROLE); + else + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_H263_ENC_ROLE); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle;; + OMX_COLOR_FORMATTYPE eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; + + ExynosVideoInstInfo *pVideoInstInfo = &(pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + + FunctionIn(); + + pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCSrc = OMX_FALSE; + pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_FALSE; + pVideoEnc->bFirstInput = OMX_TRUE; + pVideoEnc->bFirstOutput = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + if (pInputPort->eMetaDataType != METADATA_TYPE_DISABLED) { + /* metadata buffer */ + pInputPort->bufferProcessType = BUFFER_SHARE; + +#ifdef USE_ANDROID + if ((pInputPort->eMetaDataType == METADATA_TYPE_DATA) && + (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque)) { + pInputPort->eMetaDataType = METADATA_TYPE_GRAPHIC; /* AndoridOpaque means GrallocSource */ + pInputPort->bufferProcessType = BUFFER_COPY; /* will determine a process type after getting a hal format at handle */ + } +#else + if (pInputPort->eMetaDataType == METADATA_TYPE_UBM_BUFFER) { + pInputPort->bufferProcessType = BUFFER_COPY; + } +#endif + } else { + /* data buffer */ + pInputPort->bufferProcessType = BUFFER_COPY; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W: %d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, pInputPort->portDefinition.format.video.nFrameWidth, + pInputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.format.video.nBitrate, + pInputPort->portDefinition.format.video.xFramerate); + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pInputPort->portDefinition.format.video.xFramerate; + + /* Mpeg4/H.263 Codec Open */ + ret = Mpeg4CodecOpen(pMpeg4Enc, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + Exynos_SetPlaneToPort(pOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + + Exynos_OSAL_SemaphoreCreate(&pInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_OSAL_SemaphoreCreate(&pOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pMpeg4Enc->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pMpeg4Enc->hSourceStartEvent); + pMpeg4Enc->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pMpeg4Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pMpeg4Enc->hDestinationOutStartEvent); + + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp = 0; + pMpeg4Enc->hMFCMpeg4Handle.outputIndexTimestamp = 0; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pMpeg4Enc->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + pVideoEnc->csc_handle = csc_init(csc_method); + if (pVideoEnc->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVideoEnc->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_Mpeg4Enc_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoEnc != NULL) { + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + + if (pVideoEnc->csc_handle != NULL) { + csc_deinit(pVideoEnc->csc_handle); + pVideoEnc->csc_handle = NULL; + } + + if (pMpeg4Enc != NULL) { + Exynos_OSAL_QueueTerminate(&pMpeg4Enc->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pMpeg4Enc->hDestinationInStartEvent); + pMpeg4Enc->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pMpeg4Enc->hDestinationOutStartEvent); + pMpeg4Enc->hDestinationOutStartEvent = NULL; + pMpeg4Enc->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pMpeg4Enc->hSourceStartEvent); + pMpeg4Enc->hSourceStartEvent = NULL; + pMpeg4Enc->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + + if (pMpeg4Enc != NULL) { + Mpeg4CodecClose(pMpeg4Enc); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_MPEG4Enc_SrcIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + OMX_COLOR_FORMATTYPE inputColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncOps *pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt, nConfigCnt; + + FunctionIn(); + +#ifdef USE_ANDROID + { + int fps = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + + if (pVideoEnc->pPerfHandle != NULL) + Exynos_OSAL_Performance(pVideoEnc->pPerfHandle, pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp, fps); + } +#endif + + if (pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = Mpeg4CodecSrcSetup(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to HEVCCodecSrcSetup(0x%x)", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + } + + if (pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_FALSE) { + ret = Mpeg4CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to HEVCCodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + } + + nConfigCnt = Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ); + if (nConfigCnt > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] has config message(%d)", pExynosComponent, __FUNCTION__, nConfigCnt); + while (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + Change_Mpeg4Enc_Param(pExynosComponent); + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] all config messages were handled", pExynosComponent, __FUNCTION__); + } + + /* DRC on Executing state through OMX_IndexConfigCommonOutputSize */ + if (pVideoEnc->bEncDRC == OMX_TRUE) { + ret = Mpeg4CodecUpdateResolution(pOMXComponent); + pVideoEnc->bEncDRC = OMX_FALSE; + goto EXIT; + } + + if ((pSrcInputData->dataLen > 0) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + pExynosComponent->timeStamp[pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->bTimestampSlotUsed[pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp] = OMX_TRUE; + pExynosComponent->nFlags[pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp] = pSrcInputData->nFlags; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp); + pEncOps->Set_FrameTag(hMFCHandle, pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp); + pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp++; + pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp %= MAX_TIMESTAMP; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + { + OMX_S32 nTargetWidth, nTargetHeight; + + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + nTargetWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nTargetHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nTargetWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nTargetHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + /* rotation */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + nTargetWidth, nTargetHeight, + nDataLen, nAllocLen); + } else { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + nTargetHeight, nTargetWidth, + nDataLen, nAllocLen); + } + } + + if (pInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + if (pSrcInputData->dataLen == 0) { + for (i = 0; i < nPlaneCnt; i++) + nDataLen[i] = 0; + } else { + /* when having valid input */ + if (pSrcInputData->buffer.addr[2] != NULL) { + ExynosVideoMeta *pVideoMeta = (ExynosVideoMeta *)pSrcInputData->buffer.addr[2]; + + if ((pVideoMeta->eType & VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT) && + ((pVideoEnc->surfaceFormat >= OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC) && + (pVideoEnc->surfaceFormat <= OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L80))) { + int nOMXFormat = OMX_COLOR_FormatUnused; + int nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + + nOMXFormat = Exynos_OSAL_HAL2OMXColorFormat(pVideoMeta->nPixelFormat); + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nVideoFormat = Exynos_OSAL_OMX2VideoFormat(nOMXFormat, pInputPort->ePlaneType); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + if (pEncOps->Set_ActualFormat(hMFCHandle, nVideoFormat) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] set change format is failed", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] video format is changed: %d", pExynosComponent, __FUNCTION__, nVideoFormat); + } + } + } + } + } + + if ((pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.supportInfo.enc.bDropControlSupport == VIDEO_TRUE) && + (pVideoEnc->bDropControl == OMX_TRUE)) { + pEncOps->Set_DropControl(hMFCHandle, VIDEO_TRUE); + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + + Mpeg4CodecStart(pOMXComponent, INPUT_PORT_INDEX); + if (pMpeg4Enc->bSourceStart == OMX_FALSE) { + pMpeg4Enc->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pMpeg4Enc->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + if ((pMpeg4Enc->bDestinationStart == OMX_FALSE) && + (pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_TRUE)) { + pMpeg4Enc->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pMpeg4Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pMpeg4Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_SrcOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else { + if (pVideoEnc->bEncDRCSync == OMX_TRUE) { + Exynos_OSAL_SignalSet(pVideoEnc->hEncDRCSyncEvent); + pVideoEnc->bEncDRCSync = OMX_FALSE; + } + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->allocSize = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->pPrivate = NULL; + } else { + int plane = 0, nPlaneCnt; + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pSrcOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pSrcOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pSrcOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == + pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]) { + pVideoEnc->pMFCEncInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoEnc->pMFCEncInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_DstIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + unsigned int nDataLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + nAllocLen[0] = pOutputPort->portDefinition.nBufferSize; + if ((pOutputPort->bufferProcessType & BUFFER_COPY) || + (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nAllocLen[0] = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nAllocLen[0] = Exynos_OSAL_GetOutBufferSize(pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.nBufferSize); +#endif + + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + pDstInputData->bufferHeader); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + + Mpeg4CodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_DstOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + void *hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle; + + ExynosVideoEncOps *pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + ExynosVideoEncBufferOps *pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_S32 indexTimestamp = 0; + int i; + + FunctionIn(); + + if (pMpeg4Enc->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO)", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + pDstOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pDstOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + + pDstOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + pDstOutputData->dataLen = pVideoBuffer->planes[0].dataSize; + pDstOutputData->remainDataLen = pVideoBuffer->planes[0].dataSize; + pDstOutputData->usedDataLen = 0; + + pDstOutputData->pPrivate = pVideoBuffer; + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoEnc->pMFCEncOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + if (pVideoEnc->bFirstOutput == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] codec specific data is generated", pExynosComponent, __FUNCTION__); + pDstOutputData->timeStamp = 0; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + pVideoEnc->bFirstOutput = OMX_TRUE; + } else { + indexTimestamp = pEncOps->Get_FrameTag(pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d(0x%x)", pExynosComponent, __FUNCTION__, indexTimestamp, indexTimestamp); + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp == INDEX_AFTER_DRC) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid frame, buffer will be discard and reused", pExynosComponent, __FUNCTION__); + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + + if (indexTimestamp == INDEX_HEADER_DATA) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] codec specific data is generated", pExynosComponent, __FUNCTION__); + indexTimestamp = pMpeg4Enc->hMFCMpeg4Handle.outputIndexTimestamp; + pDstOutputData->timeStamp = pExynosComponent->nFlags[indexTimestamp]; + pDstOutputData->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, frameType: %d, dataLen: %d, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pVideoBuffer->frameType, pDstOutputData->dataLen, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + ret = OMX_ErrorNone; + goto EXIT; + } + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Tag(%x) is invalid. changes to use outputIndexTimestamp(%d)", + pExynosComponent, __FUNCTION__, + indexTimestamp, pMpeg4Enc->hMFCMpeg4Handle.outputIndexTimestamp); + indexTimestamp = pMpeg4Enc->hMFCMpeg4Handle.outputIndexTimestamp; + } else { + pMpeg4Enc->hMFCMpeg4Handle.outputIndexTimestamp = indexTimestamp; + } + + /* mpeg4 codec supports b-frame encoding */ + if ((pMpeg4Enc->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) && + (pMpeg4Enc->mpeg4Component[OUTPUT_PORT_INDEX].nBFrames > 0)) { + if ((pExynosComponent->nFlags[indexTimestamp] & OMX_BUFFERFLAG_EOS) && + (pVideoBuffer->frameType == VIDEO_FRAME_P)) { + /* move an EOS flag to previous slot + * B1 B2 P(EOS) -> P B1 B2(EOS) + * B1 P(EOS) -> P B1(EOS) + */ + int index = ((indexTimestamp - 1) < 0)? (MAX_TIMESTAMP - 1):(indexTimestamp - 1); + + if (pExynosComponent->bTimestampSlotUsed[index] == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] EOS flag is moved to %d from %d", + pExynosComponent, __FUNCTION__, + index, indexTimestamp); + pExynosComponent->nFlags[indexTimestamp] &= (~OMX_BUFFERFLAG_EOS); + pExynosComponent->nFlags[index] |= OMX_BUFFERFLAG_EOS; + } + } + } + + /* In case of Video buffer batch mode, use timestamp from MFC device driver */ + if (pVideoBuffer->timestamp != 0) + pDstOutputData->timeStamp = pVideoBuffer->timestamp; + else + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + + pExynosComponent->bTimestampSlotUsed[indexTimestamp] = OMX_FALSE; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp]; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + } + + if (pVideoBuffer->frameType == VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, frameType: %d, dataLen: %d, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pVideoBuffer->frameType, pDstOutputData->dataLen, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] got end of stream", pExynosComponent, __FUNCTION__); + + if (pExynosComponent->bBehaviorEOS == OMX_FALSE) + pDstOutputData->remainDataLen = 0; + else + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_srcInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || + (!CHECK_PORT_POPULATED(pInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = Exynos_MPEG4Enc_SrcIn(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_srcOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || + (!CHECK_PORT_POPULATED(pInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if ((pMpeg4Enc->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pInputPort))) { + Exynos_OSAL_SignalWait(pMpeg4Enc->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pMpeg4Enc->hSourceStartEvent); + } + + ret = Exynos_Mpeg4Enc_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_dstInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pMpeg4Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg4Enc->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pMpeg4Enc->hDestinationInStartEvent); + } + + if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pMpeg4Enc->bypassBufferInfoQ) > 0) { + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pMpeg4Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if (pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_Mpeg4Enc_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Mpeg4Enc_dstOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pMpeg4Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg4Enc->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pMpeg4Enc->hDestinationOutStartEvent); + } + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + if (Exynos_OSAL_GetElemNum(&pMpeg4Enc->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pMpeg4Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_Mpeg4Enc_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + OMX_S32 codecType = -1; + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || + (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MPEG4_ENC, componentName) == 0) { + codecType = CODEC_TYPE_MPEG4; + } else if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H263_ENC, componentName) == 0) { + codecType = CODEC_TYPE_H263; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = HW_VIDEO_ENC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pMpeg4Enc = Exynos_OSAL_Malloc(sizeof(EXYNOS_MPEG4ENC_HANDLE)); + if (pMpeg4Enc == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pMpeg4Enc, 0, sizeof(EXYNOS_MPEG4ENC_HANDLE)); + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoEnc->hCodecHandle = (OMX_HANDLETYPE)pMpeg4Enc; + pMpeg4Enc->qpRangeI.nMinQP = 3; + pMpeg4Enc->qpRangeI.nMaxQP = 30; + pMpeg4Enc->qpRangeP.nMinQP = 3; + pMpeg4Enc->qpRangeP.nMaxQP = 30; + pMpeg4Enc->qpRangeB.nMinQP = 3; + pMpeg4Enc->qpRangeB.nMaxQP = 30; + + pVideoEnc->quantization.nQpI = 15; + pVideoEnc->quantization.nQpP = 16; + pVideoEnc->quantization.nQpB = 18; + + pMpeg4Enc->hMFCMpeg4Handle.codecType = codecType; + if (codecType == CODEC_TYPE_MPEG4) + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_MPEG4_ENC); + else + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_H263_ENC); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nBitrate = 64000; + pExynosPort->portDefinition.format.video.xFramerate= (15 << 16); + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight= DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nBitrate = 64000; + pExynosPort->portDefinition.format.video.xFramerate= (15 << 16); + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + if (codecType == CODEC_TYPE_MPEG4) { + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/mpeg4"); + } else { + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingH263; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/h263"); + } + pExynosPort->portDefinition.format.video.pNativeRender = 0; + pExynosPort->portDefinition.format.video.bFlagErrorConcealment = OMX_FALSE; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + if (codecType == CODEC_TYPE_MPEG4) { + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pMpeg4Enc->mpeg4Component[i], OMX_VIDEO_PARAM_MPEG4TYPE); + pMpeg4Enc->mpeg4Component[i].nPortIndex = i; + pMpeg4Enc->mpeg4Component[i].eProfile = OMX_VIDEO_MPEG4ProfileSimple; + pMpeg4Enc->mpeg4Component[i].eLevel = OMX_VIDEO_MPEG4Level4; + + pMpeg4Enc->mpeg4Component[i].nPFrames = 29; + pMpeg4Enc->mpeg4Component[i].nBFrames = 0; + pMpeg4Enc->mpeg4Component[i].nMaxPacketSize = 256; /* Default value */ + pMpeg4Enc->mpeg4Component[i].nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; + pMpeg4Enc->mpeg4Component[i].bGov = OMX_FALSE; + + } + } else { + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pMpeg4Enc->h263Component[i], OMX_VIDEO_PARAM_H263TYPE); + pMpeg4Enc->h263Component[i].nPortIndex = i; + pMpeg4Enc->h263Component[i].eProfile = OMX_VIDEO_H263ProfileBaseline; + pMpeg4Enc->h263Component[i].eLevel = OMX_VIDEO_H263Level45; + + pMpeg4Enc->h263Component[i].nPFrames = 29; + pMpeg4Enc->h263Component[i].nBFrames = 0; /* No support for B frames */ + pMpeg4Enc->h263Component[i].bPLUSPTYPEAllowed = OMX_FALSE; + pMpeg4Enc->h263Component[i].nAllowedPictureTypes = OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP; + pMpeg4Enc->h263Component[i].bForceRoundingTypeToZero = OMX_TRUE; + pMpeg4Enc->h263Component[i].nPictureHeaderRepetition = 0; + pMpeg4Enc->h263Component[i].nGOBHeaderInterval = 0; + } + } + + pOMXComponent->GetParameter = &Exynos_Mpeg4Enc_GetParameter; + pOMXComponent->SetParameter = &Exynos_Mpeg4Enc_SetParameter; + pOMXComponent->GetConfig = &Exynos_Mpeg4Enc_GetConfig; + pOMXComponent->SetConfig = &Exynos_Mpeg4Enc_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_Mpeg4Enc_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_Mpeg4Enc_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_Mpeg4Enc_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_Mpeg4Enc_Terminate; + + pVideoEnc->exynos_codec_srcInputProcess = &Exynos_Mpeg4Enc_srcInputBufferProcess; + pVideoEnc->exynos_codec_srcOutputProcess = &Exynos_Mpeg4Enc_srcOutputBufferProcess; + pVideoEnc->exynos_codec_dstInputProcess = &Exynos_Mpeg4Enc_dstInputBufferProcess; + pVideoEnc->exynos_codec_dstOutputProcess = &Exynos_Mpeg4Enc_dstOutputBufferProcess; + + pVideoEnc->exynos_codec_start = &Mpeg4CodecStart; + pVideoEnc->exynos_codec_stop = &Mpeg4CodecStop; + pVideoEnc->exynos_codec_bufferProcessRun = &Mpeg4CodecOutputBufferProcessRun; + pVideoEnc->exynos_codec_enqueueAllBuffer = &Mpeg4CodecEnqueueAllBuffer; + + pVideoEnc->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pVideoEnc->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoEnc->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pMpeg4Enc); + pMpeg4Enc = pVideoEnc->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pMpeg4Enc->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) + pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.eCodecType = VIDEO_CODING_MPEG4; + else + pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.eCodecType = VIDEO_CODING_H263; + + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + if (Exynos_Video_GetInstInfo(&(pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo), VIDEO_FALSE /* enc */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pMpeg4Enc); + pMpeg4Enc = pVideoEnc->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for enc : qp-range(%d)", pExynosComponent, __FUNCTION__, + (pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.supportInfo.enc.bQpRangePBSupport)); + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-qp-range", (OMX_INDEXTYPE)OMX_IndexConfigVideoQPRange); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-drop-control", (OMX_INDEXTYPE)OMX_IndexParamVideoDropControl); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-disable-dfr", (OMX_INDEXTYPE)OMX_IndexParamVideoDisableDFR); +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoEnc->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pMpeg4Enc != NULL) { + Exynos_OSAL_Free(pMpeg4Enc); + pMpeg4Enc = pVideoEnc->hCodecHandle = NULL; + } + +#ifdef USE_ANDROID + Exynos_OSAL_DelVendorExts(hComponent); +#endif + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.h b/openmax/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.h new file mode 100644 index 0000000..45391cc --- /dev/null +++ b/openmax/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.h @@ -0,0 +1,99 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Mpeg4enc.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_MPEG4_ENC_COMPONENT +#define EXYNOS_OMX_MPEG4_ENC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" + +#include "ExynosVideoApi.h" + +typedef enum _CODEC_TYPE +{ + CODEC_TYPE_H263, + CODEC_TYPE_MPEG4 +} CODEC_TYPE; + +typedef struct _EXYNOS_MFC_MPEG4ENC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + CODEC_TYPE codecType; + + ExynosVideoEncOps *pEncOps; + ExynosVideoEncBufferOps *pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps; + ExynosVideoEncParam encParam; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 4 + OMX_S32 profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_S32 maxLevel; +} EXYNOS_MFC_MPEG4ENC_HANDLE; + +typedef struct _EXYNOS_MPEG4ENC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_H263TYPE h263Component[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_MPEG4TYPE mpeg4Component[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + + OMX_VIDEO_QPRANGE qpRangeI; + OMX_VIDEO_QPRANGE qpRangeP; + OMX_VIDEO_QPRANGE qpRangeB; /* MPEG4 ONLY */ + + /* SEC MFC Codec specific */ + EXYNOS_MFC_MPEG4ENC_HANDLE hMFCMpeg4Handle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_MPEG4ENC_HANDLE; + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); + OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/enc/mpeg4/NOTICE b/openmax/component/video/enc/mpeg4/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/enc/mpeg4/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/enc/mpeg4/library_register.c b/openmax/component/video/enc/mpeg4/library_register.c new file mode 100644 index 0000000..6b9f5ea --- /dev/null +++ b/openmax/component/video/enc/mpeg4/library_register.c @@ -0,0 +1,62 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_MPEG4_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - video encoder MPEG4 */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_MPEG4_ENC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_MPEG4_ENC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 2 - video encoder H.263 */ + Exynos_OSAL_Strcpy(ppExynosComponent[1]->componentName, EXYNOS_OMX_COMPONENT_H263_ENC); + Exynos_OSAL_Strcpy(ppExynosComponent[1]->roles[0], EXYNOS_OMX_COMPONENT_H263_ENC_ROLE); + ppExynosComponent[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/openmax/component/video/enc/mpeg4/library_register.h b/openmax/component/video/enc/mpeg4/library_register.h new file mode 100644 index 0000000..60f6037 --- /dev/null +++ b/openmax/component/video/enc/mpeg4/library_register.h @@ -0,0 +1,59 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_MPEG4_ENC_REG +#define EXYNOS_OMX_MPEG4_ENC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 2 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* MPEG4 */ +#define EXYNOS_OMX_COMPONENT_MPEG4_ENC "OMX.Exynos.MPEG4.Encoder" +#define EXYNOS_OMX_COMPONENT_MPEG4_ENC_ROLE "video_encoder.mpeg4" + +/* H.263 */ +#define EXYNOS_OMX_COMPONENT_H263_ENC "OMX.Exynos.H263.Encoder" +#define EXYNOS_OMX_COMPONENT_H263_ENC_ROLE "video_encoder.h263" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/openmax/component/video/enc/vp8/Android.mk b/openmax/component/video/enc/vp8/Android.mk new file mode 100644 index 0000000..4187d2a --- /dev/null +++ b/openmax/component/video/enc/vp8/Android.mk @@ -0,0 +1,80 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Vp8enc.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.VP8.Encoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := +LOCAL_CFLAGS += -DUSE_VP8_SUPPORT + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Venc libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/enc \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label -Wno-unused-function + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/enc/vp8/Exynos_OMX_Vp8enc.c b/openmax/component/video/enc/vp8/Exynos_OMX_Vp8enc.c new file mode 100644 index 0000000..26d44c9 --- /dev/null +++ b/openmax/component/video/enc/vp8/Exynos_OMX_Vp8enc.c @@ -0,0 +1,3565 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Vp8enc.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2013.02.14 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Venc.h" +#include "Exynos_OMX_VencControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Vp8enc.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OSAL_Queue.h" + +#include "Exynos_OSAL_Platform.h" + +#include "VendorVideoAPI.h" + +/* To use CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */ +/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VP8_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +#define VP8_QP_INDEX_RANGE 64 + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + + int nProfileCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp8Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Enc->hMFCVp8Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP8ProfileMain; + pVp8Enc->hMFCVp8Handle.nProfileCnt = nProfileCnt; + pVp8Enc->hMFCVp8Handle.maxLevel = OMX_VIDEO_VP8Level_Version3; + +EXIT: + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + + int nLevelCnt = 0; + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp8Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pVp8Enc->hMFCVp8Handle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pVp8Enc->hMFCVp8Handle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pVp8Enc->hMFCVp8Handle.maxLevel; +#else + while ((pVp8Enc->hMFCVp8Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pVp8Enc->hMFCVp8Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pVp8Enc->hMFCVp8Handle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pVp8Enc->hMFCVp8Handle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp8Enc == NULL) + goto EXIT; + + while ((pVp8Enc->hMFCVp8Handle.maxLevel >> nLevelCnt++) > 0); + + if ((pVp8Enc->hMFCVp8Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pVp8Enc->hMFCVp8Handle.nProfileCnt; i++) { + if (pVp8Enc->hMFCVp8Handle.profiles[i] == pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +static OMX_U32 OMXVP8ProfileToProfileIDC(OMX_VIDEO_VP8PROFILETYPE eProfile) +{ + OMX_U32 ret; + + switch (eProfile) { + case OMX_VIDEO_VP8ProfileMain: + ret = 0; + break; + default: + ret = 0; + break; + } + + return ret; +} + +static OMX_U32 OMXVP8LevelToMFCVersion(OMX_VIDEO_VP8LEVELTYPE eLevel) +{ + OMX_U32 ret; + + switch (eLevel) { + case OMX_VIDEO_VP8Level_Version0: + ret = 0; + break; + case OMX_VIDEO_VP8Level_Version1: + ret = 1; + break; + case OMX_VIDEO_VP8Level_Version2: + ret = 2; + break; + case OMX_VIDEO_VP8Level_Version3: + ret = 3; + break; + default: + ret = 0; + break; + } + + return ret; +} + +static void Print_VP8Enc_Param(ExynosVideoEncParam *pEncParam) +{ + ExynosVideoEncCommonParam *pCommonParam = &pEncParam->commonParam; + ExynosVideoEncVp8Param *pVp8Param = &pEncParam->codecParam.vp8; + + /* common parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceWidth : %d", pCommonParam->SourceWidth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceHeight : %d", pCommonParam->SourceHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "IDRPeriod : %d", pCommonParam->IDRPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SliceMode : %d", pCommonParam->SliceMode); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RandomIntraMBRefresh : %d", pCommonParam->RandomIntraMBRefresh); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Bitrate : %d", pCommonParam->Bitrate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp : %d", pCommonParam->FrameQp); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_P : %d", pCommonParam->FrameQp_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(I) ranege : %d / %d", pCommonParam->QpRange.QpMin_I, pCommonParam->QpRange.QpMax_I); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(P) ranege : %d / %d", pCommonParam->QpRange.QpMin_P, pCommonParam->QpRange.QpMax_P); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DropControl : %d", pCommonParam->bDropControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DisableDFR : %d", pCommonParam->bDisableDFR); + + /* Vp8 specific parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameRate : %d", pVp8Param->FrameRate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Vp8Version : %d", pVp8Param->Vp8Version); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Vp8NumberOfPartitions : %d", pVp8Param->Vp8NumberOfPartitions); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Vp8FilterLevel : %d", pVp8Param->Vp8FilterLevel); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Vp8FilterSharpness : %d", pVp8Param->Vp8FilterSharpness); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Vp8GoldenFrameSel : %d", pVp8Param->Vp8GoldenFrameSel); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Vp8GFRefreshPeriod : %d", pVp8Param->Vp8GFRefreshPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RefNumberForPFrame : %d", pVp8Param->RefNumberForPFrame); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "DisableIntraMd4x4 : %d", pVp8Param->DisableIntraMd4x4); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumTemporalLayer : %d", pVp8Param->TemporalSVC.nTemporalLayerCount); + + /* rate control related parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableFRMRateControl : %d", pCommonParam->EnableFRMRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableMBRateControl : %d", pCommonParam->EnableMBRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CBRPeriodRf : %d", pCommonParam->CBRPeriodRf); +} + +static void Set_VP8Enc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + EXYNOS_MFC_VP8ENC_HANDLE *pMFCVp8Handle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncVp8Param *pVp8Param = NULL; + + OMX_S32 nWidth, nHeight; + int i; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCVp8Handle = &pVp8Enc->hMFCVp8Handle; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pEncParam = &pMFCVp8Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pVp8Param = &pEncParam->codecParam.vp8; + + pEncParam->eCompressionFormat = VIDEO_CODING_VP8; + + /* uses specified target size instead of size on output port */ + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + nWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + + /* common parameters */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + pCommonParam->SourceWidth = nWidth; + pCommonParam->SourceHeight = nHeight; + } else { + pCommonParam->SourceWidth = nHeight; + pCommonParam->SourceHeight = nWidth; + } + pCommonParam->IDRPeriod = pVp8Enc->nPFrames + 1; + pCommonParam->SliceMode = 0; + pCommonParam->Bitrate = pOutputPort->portDefinition.format.video.nBitrate; + pCommonParam->FrameQp = pVideoEnc->quantization.nQpI; + pCommonParam->FrameQp_P = pVideoEnc->quantization.nQpP; + + pCommonParam->QpRange.QpMin_I = pVp8Enc->qpRangeI.nMinQP; + pCommonParam->QpRange.QpMax_I = pVp8Enc->qpRangeI.nMaxQP; + pCommonParam->QpRange.QpMin_P = pVp8Enc->qpRangeP.nMinQP; + pCommonParam->QpRange.QpMax_P = pVp8Enc->qpRangeP.nMaxQP; + + pCommonParam->PadControlOn = 0; /* 0: Use boundary pixel, 1: Use the below setting value */ + pCommonParam->LumaPadVal = 0; + pCommonParam->CbPadVal = 0; + pCommonParam->CrPadVal = 0; + + if (pVideoEnc->intraRefresh.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic) { + /* Cyclic Mode */ + pCommonParam->RandomIntraMBRefresh = pVideoEnc->intraRefresh.nCirMBs; + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + + /* Perceptual Mode */ + pCommonParam->PerceptualMode = (pVideoEnc->bPVCMode)? VIDEO_TRUE:VIDEO_FALSE; + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + pCommonParam->bDropControl = (pVideoEnc->bDropControl)? VIDEO_TRUE:VIDEO_FALSE; + pCommonParam->bDisableDFR = (pVideoEnc->bDisableDFR)? VIDEO_TRUE:VIDEO_FALSE; + + /* Vp8 specific parameters */ + pVp8Param->Vp8Version = OMXVP8LevelToMFCVersion(pVp8Enc->VP8Component[OUTPUT_PORT_INDEX].eLevel); + pVp8Param->FrameRate = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + if (pVp8Param->FrameRate <= 0) + pVp8Param->FrameRate = 30; /* default : 30fps, zero means that DynamicFramerateChange mode is set */ + + pVp8Param->RefNumberForPFrame = pMFCVp8Handle->nRefForPframes; + + /* there is no interface at OMX IL component */ + pVp8Param->Vp8NumberOfPartitions = pVp8Enc->VP8Component[OUTPUT_PORT_INDEX].nDCTPartitions; + pVp8Param->Vp8FilterLevel = 28; + pVp8Param->Vp8FilterSharpness = 6; + pVp8Param->Vp8GoldenFrameSel = 0; + pVp8Param->Vp8GFRefreshPeriod = 10; + pVp8Param->DisableIntraMd4x4 = 0; + + /* Temporal SVC */ + pVp8Param->TemporalSVC.nTemporalLayerCount = (unsigned int)pVp8Enc->AndroidVp8EncoderType.nTemporalLayerCount; + pVp8Param->TemporalSVC.nTemporalLayerBitrateRatio[0] = (unsigned int)(pOutputPort->portDefinition.format.video.nBitrate * + pVp8Enc->AndroidVp8EncoderType.nTemporalLayerBitrateRatio[0] / 100); + for (i = 1; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { + pVp8Param->TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)(pOutputPort->portDefinition.format.video.nBitrate * + (pVp8Enc->AndroidVp8EncoderType.nTemporalLayerBitrateRatio[i] - + pVp8Enc->AndroidVp8EncoderType.nTemporalLayerBitrateRatio[i - 1]) + / 100); + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eControlRate: 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]); + /* rate control related parameters */ + switch (pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]) { + case OMX_Video_ControlRateDisable: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode DBR"); + pCommonParam->EnableFRMRateControl = 0; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 0; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 200; + break; + case OMX_Video_ControlRateConstant: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 9; + break; + case OMX_Video_ControlRateVariable: + default: /*Android default */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode VBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 200; + break; + } + +// Print_VP8Enc_Param(pEncParam); +} + +static void Change_VP8Enc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + EXYNOS_MFC_VP8ENC_HANDLE *pMFCVp8Handle = NULL; + OMX_PTR pDynamicConfigCMD = NULL; + OMX_PTR pConfigData = NULL; + OMX_S32 nCmdIndex = 0; + ExynosVideoEncOps *pEncOps = NULL; + int nValue = 0; + + int i; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCVp8Handle = &pVp8Enc->hMFCVp8Handle; + pEncOps = pMFCVp8Handle->pEncOps; + + pDynamicConfigCMD = (OMX_PTR)Exynos_OSAL_Dequeue(&pExynosComponent->dynamicConfigQ); + if (pDynamicConfigCMD == NULL) + goto EXIT; + + nCmdIndex = *(OMX_S32 *)pDynamicConfigCMD; + pConfigData = (OMX_PTR)((OMX_U8 *)pDynamicConfigCMD + sizeof(OMX_S32)); + + switch ((int)nCmdIndex) { + case OMX_IndexConfigVideoIntraVOPRefresh: + { + nValue = VIDEO_FRAME_I; + pEncOps->Set_FrameType(pMFCVp8Handle->hMFCHandle, nValue); + pVideoEnc->IntraRefreshVOP = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] VOP Refresh", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_S32 nPFrames = (*((OMX_U32 *)pConfigData)) - 1; + nValue = nPFrames + 1; + pEncOps->Set_IDRPeriod(pMFCVp8Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] IDR period: %d", pExynosComponent, __FUNCTION__, nValue); + } + break; + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pConfigData; + + if (pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] != OMX_Video_ControlRateDisable) { + /* bitrate : main */ + nValue = pConfigBitrate->nEncodeBitrate; + pEncOps->Set_BitRate(pMFCVp8Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bitrate: %d", pExynosComponent, __FUNCTION__, nValue); + /* bitrate : layer */ + TemporalLayerShareBuffer TemporalSVC; + Exynos_OSAL_Memset(&TemporalSVC, 0, sizeof(TemporalLayerShareBuffer)); + TemporalSVC.nTemporalLayerCount = (unsigned int)pVp8Enc->AndroidVp8EncoderType.nTemporalLayerCount; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "nTemporalLayerCount : %d", TemporalSVC.nTemporalLayerCount); + TemporalSVC.nTemporalLayerBitrateRatio[0] = (unsigned int)(pConfigBitrate->nEncodeBitrate * + pVp8Enc->AndroidVp8EncoderType.nTemporalLayerBitrateRatio[0] / 100); + for (i = 1; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { + TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)(pConfigBitrate->nEncodeBitrate * + (pVp8Enc->AndroidVp8EncoderType.nTemporalLayerBitrateRatio[i] - + pVp8Enc->AndroidVp8EncoderType.nTemporalLayerBitrateRatio[i - 1]) + / 100); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "nTempBitrateRatio[%d] : %d", i, TemporalSVC.nTemporalLayerBitrateRatio[i]); + } + pEncOps->Set_LayerChange(pMFCVp8Handle->hMFCHandle, TemporalSVC); + } + } + break; + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pConfigData; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + + if (nPortIndex == INPUT_PORT_INDEX) { + nValue = (pConfigFramerate->xEncodeFramerate) >> 16; + pEncOps->Set_FrameRate(pMFCVp8Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] framerate: %d", pExynosComponent, __FUNCTION__, nValue); + } + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pConfigData; + ExynosVideoQPRange qpRange; + + Exynos_OSAL_Memset(&qpRange, 0, sizeof(ExynosVideoQPRange)); + + qpRange.QpMin_I = pQpRange->qpRangeI.nMinQP; + qpRange.QpMax_I = pQpRange->qpRangeI.nMaxQP; + qpRange.QpMin_P = pQpRange->qpRangeP.nMinQP; + qpRange.QpMax_P = pQpRange->qpRangeP.nMaxQP; + + pEncOps->Set_QpRange(pMFCVp8Handle->hMFCHandle, qpRange); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qp range: I(%d, %d), P(%d, %d)", + pExynosComponent, __FUNCTION__, + qpRange.QpMin_I, qpRange.QpMax_I, + qpRange.QpMin_P, qpRange.QpMax_P); + } + break; + case OMX_IndexConfigOperatingRate: + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pConfigData; + OMX_U32 xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + + nValue = pConfigRate->nU32 >> 16; + + if (pMFCVp8Handle->videoInstInfo.supportInfo.enc.bOperatingRateSupport == VIDEO_TRUE) { + if (nValue == ((OMX_U32)INT_MAX >> 16)) { + nValue = (OMX_U32)INT_MAX; + } else { + nValue = nValue * 1000; + } + + pEncOps->Set_OperatingRate(pMFCVp8Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] operating rate: 0x%x", pExynosComponent, __FUNCTION__, nValue); + } else { + if (nValue == (((OMX_U32)INT_MAX) >> 16)) { + nValue = 1000; + } else { + nValue = ((xFramerate >> 16) == 0)? 100:(OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + } + + pEncOps->Set_QosRatio(pMFCVp8Handle->hMFCHandle, nValue); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qos ratio: %d", pExynosComponent, __FUNCTION__, nValue); + } + + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; + case OMX_IndexConfigCommonOutputSize: + { + OMX_FRAMESIZETYPE *pFrameSize = (OMX_FRAMESIZETYPE *)pConfigData; + OMX_CONFIG_RECTTYPE *pTargetFrame = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].cropRectangle[IMG_CROP_OUTPUT_PORT]); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] resolution(%d x %d) is changed to (%d x %d)", pExynosComponent, __FUNCTION__, + pTargetFrame->nWidth, pTargetFrame->nHeight, + pFrameSize->nWidth, pFrameSize->nHeight); + + /* update target size */ + pTargetFrame->nTop = 0; + pTargetFrame->nLeft = 0; + pTargetFrame->nWidth = pFrameSize->nWidth; + pTargetFrame->nHeight = pFrameSize->nHeight; + + pVideoEnc->bEncDRC = OMX_TRUE; + } + break; + default: + break; + } + + Exynos_OSAL_Free(pDynamicConfigCMD); + + Set_VP8Enc_Param(pExynosComponent); + +EXIT: + return; +} + +OMX_ERRORTYPE GetCodecOutputPrivateData( + OMX_PTR pCodecBuffer, + OMX_PTR *pVirtAddr, + OMX_U32 *pDataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pVideoBuffer = NULL; + + if (pCodecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoBuffer = (ExynosVideoBuffer *)pCodecBuffer; + + if (pVirtAddr != NULL) + *pVirtAddr = pVideoBuffer->planes[0].addr; + + if (pDataSize != NULL) + *pDataSize = pVideoBuffer->planes[0].allocSize; + +EXIT: + return ret; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp8Enc == NULL) + goto EXIT; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pVp8Enc->hMFCVp8Handle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pVp8Enc->hMFCVp8Handle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE VP8CodecOpen( + EXYNOS_VP8ENC_HANDLE *pVp8Enc, + ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pVp8Enc == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pEncOps = (ExynosVideoEncOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncOps)); + pInbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + pOutbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + + if ((pEncOps == NULL) || + (pInbufOps == NULL) || + (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVp8Enc->hMFCVp8Handle.pEncOps = pEncOps; + pVp8Enc->hMFCVp8Handle.pInbufOps = pInbufOps; + pVp8Enc->hMFCVp8Handle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pEncOps->nSize = sizeof(ExynosVideoEncOps); + pInbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + + if (Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for encoder ops */ + if ((pEncOps->Init == NULL) || + (pEncOps->Finalize == NULL) || + (pEncOps->Set_FrameTag == NULL) || + (pEncOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pVp8Enc->hMFCVp8Handle.hMFCHandle = pVp8Enc->hMFCVp8Handle.pEncOps->Init(pVideoInstInfo); + if (pVp8Enc->hMFCVp8Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pVp8Enc->hMFCVp8Handle.pEncOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pVp8Enc->hMFCVp8Handle.pInbufOps = NULL; + } + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pVp8Enc->hMFCVp8Handle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecClose(EXYNOS_VP8ENC_HANDLE *pVp8Enc) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pVp8Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp8Enc->hMFCVp8Handle.hMFCHandle; + pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps; + pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + pOutbufOps = pVp8Enc->hMFCVp8Handle.pOutbufOps; + + if (hMFCHandle != NULL) { + pEncOps->Finalize(hMFCHandle); + hMFCHandle = pVp8Enc->hMFCVp8Handle.hMFCHandle = NULL; + pVp8Enc->hMFCVp8Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp8Enc->hMFCVp8Handle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Encoder(pEncOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pOutbufOps = pVp8Enc->hMFCVp8Handle.pOutbufOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps = NULL; + } + + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecStart( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp8Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp8Enc->hMFCVp8Handle.hMFCHandle; + pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + pOutbufOps = pVp8Enc->hMFCVp8Handle.pOutbufOps; + + if (nPortIndex == INPUT_PORT_INDEX) + pInbufOps->Run(hMFCHandle); + else if (nPortIndex == OUTPUT_PORT_INDEX) + pOutbufOps->Run(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecStop( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp8Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp8Enc->hMFCVp8Handle.hMFCHandle; + pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + pOutbufOps = pVp8Enc->hMFCVp8Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) + pInbufOps->Stop(hMFCHandle); + else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) + pOutbufOps->Stop(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecOutputBufferProcessRun( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp8Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pVp8Enc->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pVp8Enc->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pVp8Enc->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pVp8Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pVp8Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecEnqueueAllBuffer( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pVp8Enc->hMFCVp8Handle.hMFCHandle; + int i; + + ExynosVideoEncBufferOps *pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pVp8Enc->hMFCVp8Handle.pOutbufOps; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && + (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pVp8Enc->bSourceStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoEnc->pMFCEncInputBuffer[i]->fd[0], pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, INPUT_PORT_INDEX, pVideoEnc->pMFCEncInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pVp8Enc->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoEnc->pMFCEncOutputBuffer[i]->fd[0], pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoEnc->pMFCEncOutputBuffer[i]); + } + + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + + +void VP8CodecSetHdrInfo(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_VP8ENC_HANDLE *pMFCVp8Handle = &pVp8Enc->hMFCVp8Handle; + void *hMFCHandle = pMFCVp8Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps; + + OMX_COLOR_FORMATTYPE eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + if (pMFCVp8Handle->videoInstInfo.supportInfo.enc.bColorAspectsSupport == VIDEO_TRUE) { + ExynosVideoColorAspects BSCA; + Exynos_OSAL_Memset(&BSCA, 0, sizeof(BSCA)); + +#ifdef USE_ANDROID + if (pVideoEnc->surfaceFormat == eColorFormat) { + Exynos_OSAL_GetColorAspectsForBitstream(&(pInputPort->ColorAspects), &(pOutputPort->ColorAspects)); + + /* in case of RGBA, re-update suitable values(transfer) */ + if (pVideoEnc->surfaceFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888) { + /* Eventhough frameworks already sent ColorAspects, + * sometimes dataspace has not set to OMX component because of timing. + * So get dataspace from frameworks ColorAspects. + */ + if (pInputPort->ColorAspects.nDataSpace == 0) { + Exynos_OSAL_UpdateDataSpaceFromAspects(&(pInputPort->ColorAspects)); + } + Exynos_OSAL_GetRGBColorTypeForBitStream(&pOutputPort->ColorAspects, pInputPort->ColorAspects.nDataSpace, eColorFormat); + } + } else { + /* in case of RGBA->YUV, color aspects for bitstream is already updated */ + if (pVideoEnc->surfaceFormat != (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888) + Exynos_OSAL_GetColorAspectsForBitstream(&(pInputPort->ColorAspects), &(pOutputPort->ColorAspects)); + } +#endif + + BSCA.eRangeType = (ExynosRangeType)pOutputPort->ColorAspects.nRangeType; + BSCA.ePrimariesType = (ExynosPrimariesType)pOutputPort->ColorAspects.nPrimaryType; + BSCA.eTransferType = (ExynosTransferType)pOutputPort->ColorAspects.nTransferType; + BSCA.eCoeffType = (ExynosMatrixCoeffType)pOutputPort->ColorAspects.nCoeffType; + + pEncOps->Set_ColorAspects(hMFCHandle, &BSCA); + } + + return ; +} + +OMX_ERRORTYPE Vp8CodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_VP8ENC_HANDLE *pMFCVp8Handle = &pVp8Enc->hMFCVp8Handle; + void *hMFCHandle = pMFCVp8Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + ExynosVideoEncOps *pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + ExynosVideoGeometry bufferConf; + + FunctionIn(); + + pVideoEnc->bEncDRCSync = OMX_TRUE; + + /* stream off */ + ret = VP8CodecStop(pOMXComponent, INPUT_PORT_INDEX); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VP8CodecStop() about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_SignalWait(pVideoEnc->hEncDRCSyncEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pVideoEnc->hEncDRCSyncEvent); + + /* get input buffer geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + if (pInbufOps->Get_Geometry) { + if (pInbufOps->Get_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + /* clear information */ + pInbufOps->Clear_RegisteredBuffer(hMFCHandle); + pInbufOps->Cleanup_Buffer(hMFCHandle); + + /* set input buffer geometry */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + bufferConf.nFrameHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + bufferConf.nStride = ALIGN(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth, 16); + } else { + bufferConf.nFrameWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + bufferConf.nFrameHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + bufferConf.nStride = ALIGN(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight, 16); + } + + if (pInbufOps->Set_Geometry) { + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, MAX_INPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + /* header with IDR */ + if (pEncOps->Set_HeaderMode(hMFCHandle, VIDEO_FALSE) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set header mode", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + /* stream on */ + VP8CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + /* reset buffer queue */ + VP8CodecEnqueueAllBuffer(pOMXComponent, INPUT_PORT_INDEX); + + /* clear timestamp */ + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + + /* reinitialize a value for reconfiguring CSC */ + pVideoEnc->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecSrcSetup( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_VP8ENC_HANDLE *pMFCVp8Handle = &pVp8Enc->hMFCVp8Handle; + void *hMFCHandle = pMFCVp8Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoEncOps *pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + ExynosVideoEncParam *pEncParam = NULL; + + ExynosVideoGeometry bufferConf; + OMX_U32 inputBufferNumber = 0; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pVp8Enc->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pVp8Enc->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_OSAL_SignalSet(pVp8Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + Set_VP8Enc_Param(pExynosComponent); + + pEncParam = &pMFCVp8Handle->encParam; + if (pEncOps->Set_EncParam) { + if(pEncOps->Set_EncParam(pVp8Enc->hMFCVp8Handle.hMFCHandle, pEncParam) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + Print_VP8Enc_Param(pEncParam); + +#ifdef USE_ANDROID + VP8CodecSetHdrInfo(pOMXComponent); +#endif + + if (pMFCVp8Handle->videoInstInfo.supportInfo.enc.bPrioritySupport == VIDEO_TRUE) + pEncOps->Set_Priority(hMFCHandle, pVideoEnc->nPriority); + + if (pEncParam->commonParam.bDisableDFR == VIDEO_TRUE) + pEncOps->Disable_DynamicFrameRate(pMFCVp8Handle->hMFCHandle, VIDEO_TRUE); + + /* input buffer info: only 3 config values needed */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eColorFormat = pEncParam->commonParam.FrameMap; + + { + OMX_S32 nTargetWidth, nTargetHeight; + + /* uses specified target size instead of size on output port */ + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + /* use specified resolution */ + nTargetWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nTargetHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nTargetWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nTargetHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = nTargetWidth; + bufferConf.nFrameHeight = nTargetHeight; + bufferConf.nStride = ALIGN(nTargetWidth, 16); + } else { + bufferConf.nFrameWidth = nTargetHeight; + bufferConf.nFrameHeight = nTargetWidth; + bufferConf.nStride = ALIGN(nTargetHeight, 16); + } + } + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + pInbufOps->Set_Shareable(hMFCHandle); + inputBufferNumber = MAX_INPUTBUFFER_NUM_DYNAMIC; + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry) { + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, inputBufferNumber) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pInputPort->bufferProcessType & BUFFER_SHARE) && + (pInputPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + /* data buffer */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pVp8Enc->hMFCVp8Handle.bConfiguredMFCSrc = OMX_TRUE; + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_VP8ENC_HANDLE *pMFCVp8Handle = &pVp8Enc->hMFCVp8Handle; + void *hMFCHandle = pMFCVp8Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pOutbufOps = pVp8Enc->hMFCVp8Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + unsigned int nDataLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + int i, nOutBufSize = 0, nOutputBufferCnt = 0; + + FunctionIn(); + + nOutBufSize = pOutputPort->portDefinition.nBufferSize; + if ((pOutputPort->bufferProcessType & BUFFER_COPY) || + (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nOutBufSize = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * + pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nOutBufSize = Exynos_OSAL_GetOutBufferSize(pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.nBufferSize); +#endif + + } + + /* set geometry for output (dst) */ + if (pOutbufOps->Set_Geometry) { + /* only 2 config values needed */ + bufferConf.eCompressionFormat = VIDEO_CODING_VP8; + bufferConf.nSizeImage = nOutBufSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + + if (pOutbufOps->Set_Geometry(pVp8Enc->hMFCVp8Handle.hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pOutputPort->bufferProcessType & BUFFER_COPY) + nOutputBufferCnt = MFC_OUTPUT_BUFFER_NUM_MAX; + else + nOutputBufferCnt = pOutputPort->portDefinition.nBufferCountActual; + + if (pOutbufOps->Setup(pVp8Enc->hMFCVp8Handle.hMFCHandle, nOutputBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + nAllocLen[0] = nOutBufSize; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, MFC_OUTPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Allocate_CodecBuffers for output", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + /* Enqueue output buffer */ + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoEnc->pMFCEncOutputBuffer[i]->fd, + pVideoEnc->pMFCEncOutputBuffer[i]->bufferSize, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + NULL); + } + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /* Register output buffer */ + /*************/ + /* TBD */ + /*************/ + } + + pVp8Enc->hMFCVp8Handle.bConfiguredMFCDst = OMX_TRUE; + + if (VP8CodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nParamIndex %x", pExynosComponent, __FUNCTION__, (int)nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoVp8: + { + OMX_VIDEO_PARAM_VP8TYPE *pDstVP8Component = (OMX_VIDEO_PARAM_VP8TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP8TYPE *pSrcVP8Component = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstVP8Component, sizeof(OMX_VIDEO_PARAM_VP8TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstVP8Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVP8Component = &pVp8Enc->VP8Component[pDstVP8Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstVP8Component) + nOffset, + ((char *)pSrcVP8Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_VP8TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_VP8_ENC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP8TYPE *pSrcVP8Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVP8Component = &pVp8Enc->VP8Component[pDstProfileLevel->nPortIndex]; + pDstProfileLevel->eProfile = pSrcVP8Component->eProfile; + pDstProfileLevel->eLevel = pSrcVP8Component->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pVp8Enc->errorCorrectionType[OUTPUT_PORT_INDEX]; + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pVp8Enc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pVp8Enc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pVp8Enc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pVp8Enc->qpRangeP.nMaxQP; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamVideoAndroidVp8Encoder: + { + + OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *pDstVp8EncoderType = (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *pSrcVp8EncoderType = &pVp8Enc->AndroidVp8EncoderType; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstVp8EncoderType, sizeof(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstVp8EncoderType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVp8EncoderType->nKeyFrameInterval = pVp8Enc->nPFrames + 1; + pSrcVp8EncoderType->nMinQuantizer = pVp8Enc->qpRangeI.nMinQP; + pSrcVp8EncoderType->nMaxQuantizer = pVp8Enc->qpRangeI.nMaxQP; + + Exynos_OSAL_Memcpy(((char *)pDstVp8EncoderType) + nOffset, + ((char *)pSrcVp8EncoderType) + nOffset, + sizeof(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE) - nOffset); + } + break; +#endif + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pEnablePVC->nU32 = pVideoEnc->bPVCMode; + } + break; + case OMX_IndexParamNumberRefPframes: + { + OMX_PARAM_U32TYPE *pNumberRefPframes = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pNumberRefPframes, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pNumberRefPframes->nU32 = pVp8Enc->hMFCVp8Handle.nRefForPframes; + } + break; + default: + ret = Exynos_OMX_VideoEncodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoVp8: + { + OMX_VIDEO_PARAM_VP8TYPE *pDstVP8Component = NULL; + OMX_VIDEO_PARAM_VP8TYPE *pSrcVP8Component = (OMX_VIDEO_PARAM_VP8TYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcVP8Component, sizeof(OMX_VIDEO_PARAM_VP8TYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcVP8Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstVP8Component = &pVp8Enc->VP8Component[pSrcVP8Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstVP8Component) + nOffset, + ((char *)pSrcVP8Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_VP8TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_VP8_ENC_ROLE)) { + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP8TYPE *pDstVP8Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstVP8Component = &pVp8Enc->VP8Component[pSrcProfileLevel->nPortIndex]; + + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstVP8Component->eProfile = pSrcProfileLevel->eProfile; + pDstVP8Component->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pVp8Enc->errorCorrectionType[OUTPUT_PORT_INDEX]; + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *pPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortFormat->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pPortDef = &(pExynosComponent->pExynosPort[nPortIndex].portDefinition); + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pPortDef->format.video.xFramerate >> 16) > 0) && + ((pPortFormat->xFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] xFramerate is changed to invalid value(%d)", + pExynosComponent, __FUNCTION__, pPortFormat->xFramerate >> 16); + } + + pPortDef->format.video.eColorFormat = pPortFormat->eColorFormat; + pPortDef->format.video.eCompressionFormat = pPortFormat->eCompressionFormat; + pPortDef->format.video.xFramerate = pPortFormat->xFramerate; + } + break; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortDef->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pPortDef, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + if (pExynosPort->portDefinition.bEnabled == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + } + + if (pPortDef->nBufferCountActual < pExynosPort->portDefinition.nBufferCountMin) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pExynosPort->portDefinition.format.video.xFramerate >> 16) > 0) && + ((pPortDef->format.video.xFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] xFramerate is invalid(%d)", + pExynosComponent, __FUNCTION__, pPortDef->format.video.xFramerate >> 16); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Memcpy(((char *)&pExynosPort->portDefinition) + nOffset, + ((char *)pPortDef) + nOffset, + pPortDef->nSize - nOffset); + if (nPortIndex == INPUT_PORT_INDEX) { + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + Exynos_UpdateFrameSize(pOMXComponent); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pOutputPort->portDefinition.nBufferSize: %d", + pExynosPort->portDefinition.nBufferSize); + } + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d])", __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Enc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pVp8Enc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pVp8Enc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pVp8Enc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamVideoAndroidVp8Encoder: + { + OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *pSrcVp8EncoderType = (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *pDstVp8EncoderType = &pVp8Enc->AndroidVp8EncoderType; + + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcVp8EncoderType, sizeof(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcVp8EncoderType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pVp8Enc->hMFCVp8Handle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) && + (pSrcVp8EncoderType->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Temporal SVC is not supported", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((pSrcVp8EncoderType->nMinQuantizer > pSrcVp8EncoderType->nMaxQuantizer) || + (pSrcVp8EncoderType->nMaxQuantizer >= VP8_QP_INDEX_RANGE)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] QP value is invalid(min:%d, max:%d)", pExynosComponent, __FUNCTION__, + pSrcVp8EncoderType->nMinQuantizer, pSrcVp8EncoderType->nMaxQuantizer); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp8Enc->nPFrames = pSrcVp8EncoderType->nKeyFrameInterval - 1; + + pVp8Enc->qpRangeI.nMinQP = pSrcVp8EncoderType->nMinQuantizer; + pVp8Enc->qpRangeI.nMaxQP = pSrcVp8EncoderType->nMaxQuantizer; + + Exynos_OSAL_Memcpy(((char *)pDstVp8EncoderType) + nOffset, + ((char *)pSrcVp8EncoderType) + nOffset, + sizeof(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE) - nOffset); + } + break; +#endif + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoEnc->bPVCMode = (pEnablePVC->nU32)? OMX_TRUE:OMX_FALSE; + } + break; + case OMX_IndexParamNumberRefPframes: + { + OMX_PARAM_U32TYPE *pNumberRefPframes = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pNumberRefPframes, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVp8Enc->hMFCVp8Handle.nRefForPframes = pNumberRefPframes->nU32; + } + break; + default: + ret = Exynos_OMX_VideoEncodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pVp8Enc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pVp8Enc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pVp8Enc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pVp8Enc->qpRangeP.nMaxQP; + } + break; + default: + ret = Exynos_OMX_VideoEncodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((nPortIndex == INPUT_PORT_INDEX) && + ((pExynosPort->portDefinition.format.video.xFramerate >> 16) > 0) && + ((pConfigFramerate->xEncodeFramerate >> 16) <= 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s[%x] xFramerate is changed to invalid value(%d)", + __FUNCTION__, OMX_IndexConfigVideoFramerate, pConfigFramerate->xEncodeFramerate >> 16); + } + pExynosPort->portDefinition.format.video.xFramerate = pConfigFramerate->xEncodeFramerate; + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_U32 nPFrames = (*((OMX_U32 *)pComponentConfigStructure)) - 1; + + pVp8Enc->nPFrames = nPFrames; + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d])", + pExynosComponent, __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pVp8Enc->hMFCVp8Handle.videoInstInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_FALSE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] only I-frame's QP range is applied", pExynosComponent, __FUNCTION__); + + pVp8Enc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pVp8Enc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pVp8Enc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pVp8Enc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + } + break; + default: + ret = Exynos_OMX_VideoEncodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + OMX_PTR pDynamicConfigCMD = NULL; + pDynamicConfigCMD = Exynos_OMX_MakeDynamicConfig(nIndex, pComponentConfigStructure); + Exynos_OSAL_Queue(&pExynosComponent->dynamicConfigQ, (void *)pDynamicConfigCMD); + } + + if (ret == (OMX_ERRORTYPE)OMX_ErrorNoneExpiration) + ret = OMX_ErrorNone; + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_PVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoEnablePVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_REF_NUM_PFRAMES) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamNumberRefPframes; + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = Exynos_OMX_VideoEncodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((hComponent == NULL) || + (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_VP8_ENC_ROLE); + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_VP8Enc_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + OMX_COLOR_FORMATTYPE eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; + + ExynosVideoInstInfo *pVideoInstInfo = &(pVp8Enc->hMFCVp8Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + + FunctionIn(); + + pVp8Enc->hMFCVp8Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp8Enc->hMFCVp8Handle.bConfiguredMFCDst = OMX_FALSE; + pVideoEnc->bFirstInput = OMX_TRUE; + pVideoEnc->bFirstOutput = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + if (pInputPort->eMetaDataType != METADATA_TYPE_DISABLED) { + /* metadata buffer */ + pInputPort->bufferProcessType = BUFFER_SHARE; + +#ifdef USE_ANDROID + if ((pInputPort->eMetaDataType == METADATA_TYPE_DATA) && + (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque)) { + pInputPort->eMetaDataType = METADATA_TYPE_GRAPHIC; /* AndoridOpaque means GrallocSource */ + pInputPort->bufferProcessType = BUFFER_COPY; /* will determine a process type after getting a hal format at handle */ + } +#else + if (pInputPort->eMetaDataType == METADATA_TYPE_UBM_BUFFER) { + pInputPort->bufferProcessType = BUFFER_COPY; + } +#endif + } else { + /* data buffer */ + pInputPort->bufferProcessType = BUFFER_COPY; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pInputPort->portDefinition.format.video.nFrameWidth, + pInputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.format.video.nBitrate, + pInputPort->portDefinition.format.video.xFramerate); + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pInputPort->portDefinition.format.video.xFramerate; + + /* VP8 Codec Open */ + ret = VP8CodecOpen(pVp8Enc, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + Exynos_SetPlaneToPort(pOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + + Exynos_OSAL_SemaphoreCreate(&pInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_OSAL_SemaphoreCreate(&pOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pVp8Enc->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pVp8Enc->hSourceStartEvent); + pVp8Enc->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pVp8Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pVp8Enc->hDestinationOutStartEvent); + + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pVp8Enc->hMFCVp8Handle.indexTimestamp = 0; + pVp8Enc->hMFCVp8Handle.outputIndexTimestamp = 0; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pVp8Enc->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + + pVideoEnc->csc_handle = csc_init(csc_method); + if (pVideoEnc->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVideoEnc->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_VP8Enc_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoEnc != NULL) { + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + + if (pVideoEnc->csc_handle != NULL) { + csc_deinit(pVideoEnc->csc_handle); + pVideoEnc->csc_handle = NULL; + } + + if (pVp8Enc != NULL) { + Exynos_OSAL_QueueTerminate(&pVp8Enc->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pVp8Enc->hDestinationInStartEvent); + pVp8Enc->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pVp8Enc->hDestinationOutStartEvent); + pVp8Enc->hDestinationOutStartEvent = NULL; + pVp8Enc->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pVp8Enc->hSourceStartEvent); + pVp8Enc->hSourceStartEvent = NULL; + pVp8Enc->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + + if (pVp8Enc != NULL) { + VP8CodecClose(pVp8Enc); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_SrcIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pVp8Enc->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE inputColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncOps *pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt, nConfigCnt; + + FunctionIn(); + +#ifdef USE_ANDROID + { + int fps = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + + if (pVideoEnc->pPerfHandle != NULL) + Exynos_OSAL_Performance(pVideoEnc->pPerfHandle, pVp8Enc->hMFCVp8Handle.indexTimestamp, fps); + } +#endif + + if (pVp8Enc->hMFCVp8Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = VP8CodecSrcSetup(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VP8CodecSrcSetup(0x%x)", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + } + + if (pVp8Enc->hMFCVp8Handle.bConfiguredMFCDst == OMX_FALSE) { + ret = VP8CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VP8CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + } + + nConfigCnt = Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ); + if (nConfigCnt > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] has config message(%d)", pExynosComponent, __FUNCTION__, nConfigCnt); + while (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + Change_VP8Enc_Param(pExynosComponent); + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] all config messages were handled", pExynosComponent, __FUNCTION__); + } + + /* DRC on Executing state through OMX_IndexConfigCommonOutputSize */ + if (pVideoEnc->bEncDRC == OMX_TRUE) { + ret = Vp8CodecUpdateResolution(pOMXComponent); + pVideoEnc->bEncDRC = OMX_FALSE; + goto EXIT; + } + + if ((pSrcInputData->dataLen > 0) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + pExynosComponent->timeStamp[pVp8Enc->hMFCVp8Handle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->bTimestampSlotUsed[pVp8Enc->hMFCVp8Handle.indexTimestamp] = OMX_TRUE; + pExynosComponent->nFlags[pVp8Enc->hMFCVp8Handle.indexTimestamp] = pSrcInputData->nFlags; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pVp8Enc->hMFCVp8Handle.indexTimestamp); + pEncOps->Set_FrameTag(hMFCHandle, pVp8Enc->hMFCVp8Handle.indexTimestamp); + pVp8Enc->hMFCVp8Handle.indexTimestamp++; + pVp8Enc->hMFCVp8Handle.indexTimestamp %= MAX_TIMESTAMP; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + { + OMX_S32 nTargetWidth, nTargetHeight; + + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + nTargetWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nTargetHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nTargetWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nTargetHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + /* rotation */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + nTargetWidth, nTargetHeight, + nDataLen, nAllocLen); + } else { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + nTargetHeight, nTargetWidth, + nDataLen, nAllocLen); + } + } + + if (pInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + if (pSrcInputData->dataLen == 0) { + for (i = 0; i < nPlaneCnt; i++) + nDataLen[i] = 0; + } else { + /* when having valid input */ + if (pSrcInputData->buffer.addr[2] != NULL) { + ExynosVideoMeta *pVideoMeta = (ExynosVideoMeta *)pSrcInputData->buffer.addr[2]; + + if ((pVideoMeta->eType & VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT) && + ((pVideoEnc->surfaceFormat >= OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC) && + (pVideoEnc->surfaceFormat <= OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L80))) { + int nOMXFormat = OMX_COLOR_FormatUnused; + int nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + + nOMXFormat = Exynos_OSAL_HAL2OMXColorFormat(pVideoMeta->nPixelFormat); + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nVideoFormat = Exynos_OSAL_OMX2VideoFormat(nOMXFormat, pInputPort->ePlaneType); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + if (pEncOps->Set_ActualFormat(hMFCHandle, nVideoFormat) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] set change format is failed", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] video format is changed: %d", pExynosComponent, __FUNCTION__, nVideoFormat); + } + } + } + } + } + + if ((pVp8Enc->hMFCVp8Handle.videoInstInfo.supportInfo.enc.bDropControlSupport == VIDEO_TRUE) && + (pVideoEnc->bDropControl == OMX_TRUE)) { + pEncOps->Set_DropControl(hMFCHandle, VIDEO_TRUE); + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + + VP8CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + if (pVp8Enc->bSourceStart == OMX_FALSE) { + pVp8Enc->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp8Enc->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + if ((pVp8Enc->bDestinationStart == OMX_FALSE) && + (pVp8Enc->hMFCVp8Handle.bConfiguredMFCDst == OMX_TRUE)) { + pVp8Enc->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp8Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pVp8Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_SrcOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pVp8Enc->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else { + if (pVideoEnc->bEncDRCSync == OMX_TRUE) { + Exynos_OSAL_SignalSet(pVideoEnc->hEncDRCSyncEvent); + pVideoEnc->bEncDRCSync = OMX_FALSE; + } + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->allocSize = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->pPrivate = NULL; + } else { + int plane = 0, nPlaneCnt; + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pSrcOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pSrcOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pSrcOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == + pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]) { + pVideoEnc->pMFCEncInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoEnc->pMFCEncInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_DstIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pVp8Enc->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pOutbufOps = pVp8Enc->hMFCVp8Handle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + unsigned int nDataLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + nAllocLen[0] = pOutputPort->portDefinition.nBufferSize; + if ((pOutputPort->bufferProcessType & BUFFER_COPY) || + (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nAllocLen[0] = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nAllocLen[0] = Exynos_OSAL_GetOutBufferSize(pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.nBufferSize); +#endif + + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)&pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + pDstInputData->bufferHeader); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + + VP8CodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_DstOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + void *hMFCHandle = pVp8Enc->hMFCVp8Handle.hMFCHandle; + + ExynosVideoEncOps *pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps; + ExynosVideoEncBufferOps *pOutbufOps = pVp8Enc->hMFCVp8Handle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_S32 indexTimestamp = 0; + + FunctionIn(); + + if (pVp8Enc->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO)", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + pDstOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pDstOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + + pDstOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + pDstOutputData->dataLen = pVideoBuffer->planes[0].dataSize; + pDstOutputData->remainDataLen = pVideoBuffer->planes[0].dataSize; + pDstOutputData->usedDataLen = 0; + + pDstOutputData->pPrivate = pVideoBuffer; + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoEnc->pMFCEncOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + indexTimestamp = pEncOps->Get_FrameTag(pVp8Enc->hMFCVp8Handle.hMFCHandle); + + if (pVideoEnc->bFirstOutput == OMX_FALSE) { + /* Because of Codec2 requirement, Driver doesn't send only CSD buffer in VP8, VP9 encoders. */ + if (indexTimestamp == INDEX_HEADER_DATA) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] codec specific data is generated", pExynosComponent, __FUNCTION__); + + pDstOutputData->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; + pDstOutputData->timeStamp = 0; + } else { + pDstOutputData->timeStamp = pExynosComponent->timeStamp[pVp8Enc->hMFCVp8Handle.outputIndexTimestamp]; + } + + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + pVideoEnc->bFirstOutput = OMX_TRUE; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d(0x%x)", pExynosComponent, __FUNCTION__, indexTimestamp, indexTimestamp); + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp == INDEX_AFTER_DRC) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid frame, buffer will be discard and reused", pExynosComponent, __FUNCTION__); + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + + if (indexTimestamp == INDEX_HEADER_DATA) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] codec specific data is generated", pExynosComponent, __FUNCTION__); + indexTimestamp = pVp8Enc->hMFCVp8Handle.outputIndexTimestamp; + pDstOutputData->timeStamp = pExynosComponent->nFlags[indexTimestamp]; + pDstOutputData->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, frameType: %d, dataLen: %d, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pVideoBuffer->frameType, pDstOutputData->dataLen, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + ret = OMX_ErrorNone; + goto EXIT; + } + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Tag(%x) is invalid. changes to use outputIndexTimestamp(%d)", + pExynosComponent, __FUNCTION__, + indexTimestamp, pVp8Enc->hMFCVp8Handle.outputIndexTimestamp); + indexTimestamp = pVp8Enc->hMFCVp8Handle.outputIndexTimestamp; + } else { + pVp8Enc->hMFCVp8Handle.outputIndexTimestamp = indexTimestamp; + } + + /* In case of Video buffer batch mode, use timestamp from MFC device driver */ + if (pVideoBuffer->timestamp != 0) + pDstOutputData->timeStamp = pVideoBuffer->timestamp; + else + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + + pExynosComponent->bTimestampSlotUsed[indexTimestamp] = OMX_FALSE; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp]; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + } + + if (pVideoBuffer->frameType == VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, frameType: %d, dataLen: %d, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pVideoBuffer->frameType, pDstOutputData->dataLen, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] got end of stream", pExynosComponent, __FUNCTION__); + + if (pExynosComponent->bBehaviorEOS == OMX_FALSE) + pDstOutputData->remainDataLen = 0; + else + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_srcInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || + (!CHECK_PORT_POPULATED(pInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = Exynos_VP8Enc_SrcIn(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_srcOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || + (!CHECK_PORT_POPULATED(pInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if ((pVp8Enc->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pInputPort))) { + Exynos_OSAL_SignalWait(pVp8Enc->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp8Enc->hSourceStartEvent); + } + + ret = Exynos_VP8Enc_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_dstInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pVp8Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pVp8Enc->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp8Enc->hDestinationInStartEvent); + } + + if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pVp8Enc->bypassBufferInfoQ) > 0) { + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pVp8Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if (pVp8Enc->hMFCVp8Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_VP8Enc_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP8Enc_dstOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pVp8Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pVp8Enc->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp8Enc->hDestinationOutStartEvent); + } + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + if (Exynos_OSAL_GetElemNum(&pVp8Enc->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pVp8Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_VP8Enc_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || + (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP8_ENC, componentName) != 0) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = HW_VIDEO_ENC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pVp8Enc = Exynos_OSAL_Malloc(sizeof(EXYNOS_VP8ENC_HANDLE)); + if (pVp8Enc == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVp8Enc, 0, sizeof(EXYNOS_VP8ENC_HANDLE)); + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoEnc->hCodecHandle = (OMX_HANDLETYPE)pVp8Enc; + pVp8Enc->qpRangeI.nMinQP = 2; /* index = 2, value = 2 */ + pVp8Enc->qpRangeI.nMaxQP = 63; /* index = 63, value = 127 */ + pVp8Enc->qpRangeP.nMinQP = 2; /* index = 2, value = 2 */; + pVp8Enc->qpRangeP.nMaxQP = 63; /* index = 63, value = 127 */ + + pVideoEnc->quantization.nQpI = 37; + pVideoEnc->quantization.nQpP = 40; + pVideoEnc->quantization.nQpB = 40; + + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_VP8_ENC); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/avc"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pVp8Enc->VP8Component[i], OMX_VIDEO_PARAM_VP8TYPE); + pVp8Enc->VP8Component[i].nPortIndex = i; + pVp8Enc->VP8Component[i].eProfile = OMX_VIDEO_VP8ProfileMain; + pVp8Enc->VP8Component[i].eLevel = OMX_VIDEO_VP8Level_Version0; + } + pVp8Enc->nPFrames = -1; /* for GTS issue */ + + Exynos_OSAL_Memset(&pVp8Enc->AndroidVp8EncoderType, 0, sizeof(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE)); + INIT_SET_SIZE_VERSION(&pVp8Enc->AndroidVp8EncoderType, OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE); + pVp8Enc->AndroidVp8EncoderType.nKeyFrameInterval = pVp8Enc->nPFrames + 1; + pVp8Enc->AndroidVp8EncoderType.eTemporalPattern = OMX_VIDEO_VPXTemporalLayerPatternNone; + pVp8Enc->AndroidVp8EncoderType.nTemporalLayerCount = 1; + for (i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) + pVp8Enc->AndroidVp8EncoderType.nTemporalLayerBitrateRatio[i] = 100; + + pVp8Enc->AndroidVp8EncoderType.nMinQuantizer = pVp8Enc->qpRangeI.nMinQP; + pVp8Enc->AndroidVp8EncoderType.nMaxQuantizer = pVp8Enc->qpRangeI.nMaxQP; + + pOMXComponent->GetParameter = &Exynos_VP8Enc_GetParameter; + pOMXComponent->SetParameter = &Exynos_VP8Enc_SetParameter; + pOMXComponent->GetConfig = &Exynos_VP8Enc_GetConfig; + pOMXComponent->SetConfig = &Exynos_VP8Enc_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_VP8Enc_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_VP8Enc_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_VP8Enc_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_VP8Enc_Terminate; + + pVideoEnc->exynos_codec_srcInputProcess = &Exynos_VP8Enc_srcInputBufferProcess; + pVideoEnc->exynos_codec_srcOutputProcess = &Exynos_VP8Enc_srcOutputBufferProcess; + pVideoEnc->exynos_codec_dstInputProcess = &Exynos_VP8Enc_dstInputBufferProcess; + pVideoEnc->exynos_codec_dstOutputProcess = &Exynos_VP8Enc_dstOutputBufferProcess; + + pVideoEnc->exynos_codec_start = &VP8CodecStart; + pVideoEnc->exynos_codec_stop = &VP8CodecStop; + pVideoEnc->exynos_codec_bufferProcessRun = &VP8CodecOutputBufferProcessRun; + pVideoEnc->exynos_codec_enqueueAllBuffer = &VP8CodecEnqueueAllBuffer; + + pVideoEnc->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pVideoEnc->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoEnc->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pVp8Enc); + pVp8Enc = pVideoEnc->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVp8Enc->hMFCVp8Handle.videoInstInfo.eCodecType = VIDEO_CODING_VP8; + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + pVp8Enc->hMFCVp8Handle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pVp8Enc->hMFCVp8Handle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + pVp8Enc->hMFCVp8Handle.nRefForPframes = 1; + + if (Exynos_Video_GetInstInfo(&(pVp8Enc->hMFCVp8Handle.videoInstInfo), VIDEO_FALSE /* enc */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to GetInstInfo", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pVp8Enc); + pVp8Enc = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for enc : temporal-svc(%d)/qp-range(%d)/pvc(%d)", + pExynosComponent, __FUNCTION__, + (pVp8Enc->hMFCVp8Handle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport), + (pVp8Enc->hMFCVp8Handle.videoInstInfo.supportInfo.enc.bQpRangePBSupport), + (pVp8Enc->hMFCVp8Handle.videoInstInfo.supportInfo.enc.bPVCSupport)); + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-qp-range", (OMX_INDEXTYPE)OMX_IndexConfigVideoQPRange); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-ref-pframes", (OMX_INDEXTYPE)OMX_IndexParamNumberRefPframes); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-drop-control", (OMX_INDEXTYPE)OMX_IndexParamVideoDropControl); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-disable-dfr", (OMX_INDEXTYPE)OMX_IndexParamVideoDisableDFR); +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP8ENC_HANDLE *pVp8Enc = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoEnc->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp8Enc != NULL) { + Exynos_OSAL_Free(pVp8Enc); + pVp8Enc = pVideoEnc->hCodecHandle = NULL; + } + +#ifdef USE_ANDROID + Exynos_OSAL_DelVendorExts(hComponent); +#endif + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/enc/vp8/Exynos_OMX_Vp8enc.h b/openmax/component/video/enc/vp8/Exynos_OMX_Vp8enc.h new file mode 100644 index 0000000..58f210e --- /dev/null +++ b/openmax/component/video/enc/vp8/Exynos_OMX_Vp8enc.h @@ -0,0 +1,94 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Vp8enc.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2013.02.14 : Create + */ + +#ifndef EXYNOS_OMX_VP8_ENC_COMPONENT +#define EXYNOS_OMX_VP8_ENC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" + +#include "ExynosVideoApi.h" + +typedef struct _EXYNOS_MFC_VP8ENC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + + ExynosVideoEncOps *pEncOps; + ExynosVideoEncBufferOps *pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps; + ExynosVideoEncParam encParam; + ExynosVideoInstInfo videoInstInfo; + + OMX_U32 nRefForPframes; + + #define MAX_PROFILE_NUM 1 + OMX_VIDEO_VP8PROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_VP8LEVELTYPE maxLevel; +} EXYNOS_MFC_VP8ENC_HANDLE; + +typedef struct _EXYNOS_VP8ENC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_VP8TYPE VP8Component[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + OMX_U32 nPFrames; /* IDR period control */ + OMX_VIDEO_QPRANGE qpRangeI; + OMX_VIDEO_QPRANGE qpRangeP; + + OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE AndroidVp8EncoderType; + + /* SEC MFC Codec specific */ + EXYNOS_MFC_VP8ENC_HANDLE hMFCVp8Handle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_VP8ENC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); + OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/enc/vp8/NOTICE b/openmax/component/video/enc/vp8/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/enc/vp8/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/enc/vp8/library_register.c b/openmax/component/video/enc/vp8/library_register.c new file mode 100644 index 0000000..ccd44f7 --- /dev/null +++ b/openmax/component/video/enc/vp8/library_register.c @@ -0,0 +1,58 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2013.02.14 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VP8_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - video encoder VP8 */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_VP8_ENC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_VP8_ENC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/openmax/component/video/enc/vp8/library_register.h b/openmax/component/video/enc/vp8/library_register.h new file mode 100644 index 0000000..d0a3090 --- /dev/null +++ b/openmax/component/video/enc/vp8/library_register.h @@ -0,0 +1,56 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2013.02.14 : Create + */ + +#ifndef EXYNOS_OMX_VP8_ENC_REG +#define EXYNOS_OMX_VP8_ENC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 1 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* VP8 */ +#define EXYNOS_OMX_COMPONENT_VP8_ENC "OMX.Exynos.VP8.Encoder" +#define EXYNOS_OMX_COMPONENT_VP8_ENC_ROLE "video_encoder.vp8" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/openmax/component/video/enc/vp9/Android.mk b/openmax/component/video/enc/vp9/Android.mk new file mode 100644 index 0000000..c2b51e2 --- /dev/null +++ b/openmax/component/video/enc/vp9/Android.mk @@ -0,0 +1,79 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Vp9enc.c \ + library_register.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libOMX.Exynos.VP9.Encoder +LOCAL_MODULE_RELATIVE_PATH := omx +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := -DUSE_VP9_SUPPORT + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Venc libVendorVideoApi libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + libdl \ + liblog \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libstagefright_foundation \ + libexynosv4l2 \ + libion_exynos \ + libcsc \ + libExynosOMX_Resourcemanager \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/enc \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label -Wno-unused-function + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/component/video/enc/vp9/Exynos_OMX_Vp9enc.c b/openmax/component/video/enc/vp9/Exynos_OMX_Vp9enc.c new file mode 100644 index 0000000..60b8e37 --- /dev/null +++ b/openmax/component/video/enc/vp9/Exynos_OMX_Vp9enc.c @@ -0,0 +1,3530 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Vp9enc.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2015.04.14 : Create + */ + +#include +#include +#include + +#include "Exynos_OMX_Macros.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Venc.h" +#include "Exynos_OMX_VencControl.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Thread.h" +#include "library_register.h" +#include "Exynos_OMX_Vp9enc.h" +#include "Exynos_OSAL_SharedMemory.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OSAL_Queue.h" + +#include "Exynos_OSAL_Platform.h" + +#include "VendorVideoAPI.h" + +/* To use CSC_METHOD_HW in EXYNOS OMX, gralloc should allocate physical memory using FIMC */ +/* It means GRALLOC_USAGE_HW_FIMC1 should be set on Native Window usage */ +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VP9_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +#define VP9_QP_INDEX_RANGE 64 + +static OMX_ERRORTYPE SetProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + + int nProfileCnt = 0; + int nLevelCnt = 0; + + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp9Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Enc->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile0; + pVp9Enc->hMFCVp9Handle.nProfileCnt = nProfileCnt; + + switch (pVp9Enc->hMFCVp9Handle.videoInstInfo.HwVersion) { + case MFC_1501: + case MFC_150: + pVp9Enc->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile2; + pVp9Enc->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile2HDR; + pVp9Enc->hMFCVp9Handle.nProfileCnt = nProfileCnt; + + pVp9Enc->hMFCVp9Handle.maxLevel = OMX_VIDEO_VP9Level52; + break; + case MFC_1410: + case MFC_1400: + case MFC_140: + pVp9Enc->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile2; + pVp9Enc->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile2HDR; + pVp9Enc->hMFCVp9Handle.nProfileCnt = nProfileCnt; + + pVp9Enc->hMFCVp9Handle.maxLevel = OMX_VIDEO_VP9Level51; + break; + case MFC_130: + case MFC_120: + case MFC_1220: + pVp9Enc->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile2; + pVp9Enc->hMFCVp9Handle.profiles[nProfileCnt++] = OMX_VIDEO_VP9Profile2HDR; + pVp9Enc->hMFCVp9Handle.nProfileCnt = nProfileCnt; + + pVp9Enc->hMFCVp9Handle.maxLevel = OMX_VIDEO_VP9Level51; + break; + default: + pVp9Enc->hMFCVp9Handle.maxLevel = OMX_VIDEO_VP9Level41; + break; + } + +EXIT: + return ret; +} + +static OMX_ERRORTYPE GetIndexToProfileLevel( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + + OMX_U32 nMaxIndex = 0; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp9Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef USE_ANDROID + if (pVp9Enc->hMFCVp9Handle.nProfileCnt <= (int)pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pVp9Enc->hMFCVp9Handle.profiles[pProfileLevelType->nProfileIndex]; + pProfileLevelType->eLevel = pVp9Enc->hMFCVp9Handle.maxLevel; +#else + while ((pVp9Enc->hMFCVp9Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pVp9Enc->hMFCVp9Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nMaxIndex = pVp9Enc->hMFCVp9Handle.nProfileCnt * nLevelCnt; + if (nMaxIndex <= pProfileLevelType->nProfileIndex) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pProfileLevelType->eProfile = pVp9Enc->hMFCVp9Handle.profiles[pProfileLevelType->nProfileIndex / nLevelCnt]; + pProfileLevelType->eLevel = 0x1 << (pProfileLevelType->nProfileIndex % nLevelCnt); +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : supported profile(%x), level(%x)", + pExynosComponent, __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + return ret; +} + +static OMX_BOOL CheckProfileLevelSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pProfileLevelType) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + + OMX_BOOL bProfileSupport = OMX_FALSE; + OMX_BOOL bLevelSupport = OMX_FALSE; + + int nLevelCnt = 0; + int i; + + FunctionIn(); + + if ((pExynosComponent == NULL) || + (pProfileLevelType == NULL)) { + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp9Enc == NULL) + goto EXIT; + + while ((pVp9Enc->hMFCVp9Handle.maxLevel >> nLevelCnt++) > 0); + + if ((pVp9Enc->hMFCVp9Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] : there is no any profile/level", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pVp9Enc->hMFCVp9Handle.nProfileCnt; i++) { + if (pVp9Enc->hMFCVp9Handle.profiles[i] == pProfileLevelType->eProfile) { + bProfileSupport = OMX_TRUE; + break; + } + } + + if (bProfileSupport != OMX_TRUE) + goto EXIT; + + while (nLevelCnt >= 0) { + if ((int)pProfileLevelType->eLevel == (0x1 << nLevelCnt)) { + bLevelSupport = OMX_TRUE; + break; + } + + nLevelCnt--; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] : profile(%x)/level(%x) is %ssupported", pExynosComponent, __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +static OMX_U32 OMXVP9ProfileToProfileIDC(OMX_VIDEO_VP9PROFILETYPE eProfile) +{ + OMX_U32 ret; + + switch (eProfile) { + case OMX_VIDEO_VP9Profile0: + ret = 0; + break; + case OMX_VIDEO_VP9Profile1: + ret = 1; + break; + case OMX_VIDEO_VP9Profile2: + case OMX_VIDEO_VP9Profile2HDR: + case OMX_VIDEO_VP9Profile2HDR10Plus: + ret = 2; + break; + case OMX_VIDEO_VP9Profile3: + case OMX_VIDEO_VP9Profile3HDR: + ret = 3; + break; + default: + ret = 0; + break; + } + + return ret; +} + +static OMX_U32 OMXVP9LevelToLevelIDC(OMX_VIDEO_VP9LEVELTYPE eLevel) +{ + OMX_U32 ret; + + /* refer to UM, MFC supports only 0 value */ + switch (eLevel) { + case OMX_VIDEO_VP9Level1: + ret = 10; + break; + case OMX_VIDEO_VP9Level11: + ret = 11; + break; + case OMX_VIDEO_VP9Level2: + ret = 20; + break; + case OMX_VIDEO_VP9Level21: + ret = 21; + break; + case OMX_VIDEO_VP9Level3: + ret = 30; + break; + case OMX_VIDEO_VP9Level31: + ret = 31; + break; + case OMX_VIDEO_VP9Level4: + ret = 40; + break; + case OMX_VIDEO_VP9Level41: + ret = 41; + break; + case OMX_VIDEO_VP9Level5: + ret = 50; + break; + case OMX_VIDEO_VP9Level51: + ret = 51; + break; + case OMX_VIDEO_VP9Level52: + ret = 52; + break; + case OMX_VIDEO_VP9Level6: + ret = 60; + break; + case OMX_VIDEO_VP9Level61: + ret = 61; + break; + case OMX_VIDEO_VP9Level62: + ret = 62; + break; + default: + ret = 0; + break; + } + + return ret; +} + +static void Print_VP9Enc_Param(ExynosVideoEncParam *pEncParam) +{ + ExynosVideoEncCommonParam *pCommonParam = &pEncParam->commonParam; + ExynosVideoEncVp9Param *pVp9Param = &pEncParam->codecParam.vp9; + + /* common parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceWidth : %d", pCommonParam->SourceWidth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SourceHeight : %d", pCommonParam->SourceHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "IDRPeriod : %d", pCommonParam->IDRPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SliceMode : %d", pCommonParam->SliceMode); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RandomIntraMBRefresh : %d", pCommonParam->RandomIntraMBRefresh); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Bitrate : %d", pCommonParam->Bitrate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp : %d", pCommonParam->FrameQp); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameQp_P : %d", pCommonParam->FrameQp_P); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(I) ranege : %d / %d", pCommonParam->QpRange.QpMin_I, pCommonParam->QpRange.QpMax_I); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "QP(P) ranege : %d / %d", pCommonParam->QpRange.QpMin_P, pCommonParam->QpRange.QpMax_P); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DropControl : %d", pCommonParam->bDropControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DisableDFR : %d", pCommonParam->bDisableDFR); + + /* Vp9 specific parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameRate : %d", pVp9Param->FrameRate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Vp9Profile : %d", pVp9Param->Vp9Profile); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Vp9Level : %d", pVp9Param->Vp9Level); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Vp9GoldenFrameSel : %d", pVp9Param->Vp9GoldenFrameSel); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Vp9GFRefreshPeriod : %d", pVp9Param->Vp9GFRefreshPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RefNumberForPFrame : %d", pVp9Param->RefNumberForPFrame); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "MaxPartitionDepth : %d", pVp9Param->MaxPartitionDepth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumTemporalLayer : %d", pVp9Param->TemporalSVC.nTemporalLayerCount); + + /* rate control related parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableFRMRateControl : %d", pCommonParam->EnableFRMRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "EnableMBRateControl : %d", pCommonParam->EnableMBRateControl); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CBRPeriodRf : %d", pCommonParam->CBRPeriodRf); +} + +static void Set_VP9Enc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + EXYNOS_MFC_VP9ENC_HANDLE *pMFCVp9Handle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncVp9Param *pVp9Param = NULL; + + OMX_S32 nWidth, nHeight; + int i; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCVp9Handle = &pVp9Enc->hMFCVp9Handle; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pEncParam = &pMFCVp9Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pVp9Param = &pEncParam->codecParam.vp9; + + pEncParam->eCompressionFormat = VIDEO_CODING_VP9; + + /* uses specified target size instead of size on output port */ + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + nWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + + /* common parameters */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + pCommonParam->SourceWidth = nWidth; + pCommonParam->SourceHeight = nHeight; + } else { + pCommonParam->SourceWidth = nHeight; + pCommonParam->SourceHeight = nWidth; + } + pCommonParam->IDRPeriod = pVp9Enc->nPFrames + 1; + pCommonParam->SliceMode = 0; + pCommonParam->Bitrate = pOutputPort->portDefinition.format.video.nBitrate; + pCommonParam->FrameQp = pVideoEnc->quantization.nQpI; + pCommonParam->FrameQp_P = pVideoEnc->quantization.nQpP; + + pCommonParam->QpRange.QpMin_I = pVp9Enc->qpRangeI.nMinQP; + pCommonParam->QpRange.QpMax_I = pVp9Enc->qpRangeI.nMaxQP; + pCommonParam->QpRange.QpMin_P = pVp9Enc->qpRangeP.nMinQP; + pCommonParam->QpRange.QpMax_P = pVp9Enc->qpRangeP.nMaxQP; + + pCommonParam->PadControlOn = 0; /* 0: Use boundary pixel, 1: Use the below setting value */ + pCommonParam->LumaPadVal = 0; + pCommonParam->CbPadVal = 0; + pCommonParam->CrPadVal = 0; + + if (pVideoEnc->intraRefresh.eRefreshMode == OMX_VIDEO_IntraRefreshCyclic) { + /* Cyclic Mode */ + pCommonParam->RandomIntraMBRefresh = pVideoEnc->intraRefresh.nCirMBs; + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + + /* Perceptual Mode */ + pCommonParam->PerceptualMode = (pVideoEnc->bPVCMode)? VIDEO_TRUE:VIDEO_FALSE; + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + pCommonParam->bDropControl = (pVideoEnc->bDropControl)? VIDEO_TRUE:VIDEO_FALSE; + pCommonParam->bDisableDFR = (pVideoEnc->bDisableDFR)? VIDEO_TRUE:VIDEO_FALSE; + + /* Vp9 specific parameters */ + pVp9Param->Vp9Profile = OMXVP9ProfileToProfileIDC(pVp9Enc->VP9Component[OUTPUT_PORT_INDEX].eProfile); + pVp9Param->Vp9Level = OMXVP9LevelToLevelIDC(pVp9Enc->VP9Component[OUTPUT_PORT_INDEX].eLevel); + pVp9Param->FrameRate = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + if (pVp9Param->FrameRate <= 0) + pVp9Param->FrameRate = 30; /* default : 30fps, zero means that DynamicFramerateChange mode is set */ + + pVp9Param->RefNumberForPFrame = pMFCVp9Handle->nRefForPframes; + + /* there is no interface at OMX IL component */ + pVp9Param->Vp9GoldenFrameSel = 0; + pVp9Param->Vp9GFRefreshPeriod = 30; + pVp9Param->MaxPartitionDepth = 1; + + /* Temporal SVC */ + pVp9Param->TemporalSVC.nTemporalLayerCount = (unsigned int)pVp9Enc->AndroidVp9EncoderType.nTemporalLayerCount; + pVp9Param->TemporalSVC.nTemporalLayerBitrateRatio[0] = (unsigned int)(pOutputPort->portDefinition.format.video.nBitrate * + pVp9Enc->AndroidVp9EncoderType.nTemporalLayerBitrateRatio[0] / 100); + for (i = 1; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { + pVp9Param->TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)(pOutputPort->portDefinition.format.video.nBitrate * + (pVp9Enc->AndroidVp9EncoderType.nTemporalLayerBitrateRatio[i] - + pVp9Enc->AndroidVp9EncoderType.nTemporalLayerBitrateRatio[i - 1]) + / 100); + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eControlRate: 0x%x", pExynosComponent, __FUNCTION__, pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]); + /* rate control related parameters */ + switch (pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]) { + case OMX_Video_ControlRateDisable: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode DBR"); + pCommonParam->EnableFRMRateControl = 0; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 0; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 200; + break; + case OMX_Video_ControlRateConstant: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode CBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 9; + break; + case OMX_Video_ControlRateVariable: + default: /*Android default */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Video Encode VBR"); + pCommonParam->EnableFRMRateControl = 1; /* 0: Disable, 1: Frame level RC */ + pCommonParam->EnableMBRateControl = 1; /* 0: Disable, 1:MB level RC */ + pCommonParam->CBRPeriodRf = 200; + break; + } + +// Print_VP9Enc_Param(pEncParam); +} + +static void Change_VP9Enc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + EXYNOS_MFC_VP9ENC_HANDLE *pMFCVp9Handle = NULL; + OMX_PTR pDynamicConfigCMD = NULL; + OMX_PTR pConfigData = NULL; + OMX_S32 nCmdIndex = 0; + ExynosVideoEncOps *pEncOps = NULL; + int nValue = 0; + + int i; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCVp9Handle = &pVp9Enc->hMFCVp9Handle; + pEncOps = pMFCVp9Handle->pEncOps; + + pDynamicConfigCMD = (OMX_PTR)Exynos_OSAL_Dequeue(&pExynosComponent->dynamicConfigQ); + if (pDynamicConfigCMD == NULL) + goto EXIT; + + nCmdIndex = *(OMX_S32 *)pDynamicConfigCMD; + pConfigData = (OMX_PTR)((OMX_U8 *)pDynamicConfigCMD + sizeof(OMX_S32)); + + switch ((int)nCmdIndex) { + case OMX_IndexConfigVideoIntraVOPRefresh: + { + nValue = VIDEO_FRAME_I; + pEncOps->Set_FrameType(pMFCVp9Handle->hMFCHandle, nValue); + pVideoEnc->IntraRefreshVOP = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] VOP Refresh", pExynosComponent, __FUNCTION__); + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_S32 nPFrames = (*((OMX_U32 *)pConfigData)) - 1; + nValue = nPFrames + 1; + pEncOps->Set_IDRPeriod(pMFCVp9Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] IDR period: %d", pExynosComponent, __FUNCTION__, nValue); + } + break; + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pConfigData; + + if (pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] != OMX_Video_ControlRateDisable) { + /* bitrate : main */ + nValue = pConfigBitrate->nEncodeBitrate; + pEncOps->Set_BitRate(pMFCVp9Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bitrate: %d", pExynosComponent, __FUNCTION__, nValue); + /* bitrate : layer */ + TemporalLayerShareBuffer TemporalSVC; + Exynos_OSAL_Memset(&TemporalSVC, 0, sizeof(TemporalLayerShareBuffer)); + TemporalSVC.nTemporalLayerCount = (unsigned int)pVp9Enc->AndroidVp9EncoderType.nTemporalLayerCount; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "nTemporalLayerCount : %d", TemporalSVC.nTemporalLayerCount); + TemporalSVC.nTemporalLayerBitrateRatio[0] = (unsigned int)(pConfigBitrate->nEncodeBitrate * + pVp9Enc->AndroidVp9EncoderType.nTemporalLayerBitrateRatio[0] / 100); + for (i = 1; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) { + TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)(pConfigBitrate->nEncodeBitrate * + (pVp9Enc->AndroidVp9EncoderType.nTemporalLayerBitrateRatio[i] - + pVp9Enc->AndroidVp9EncoderType.nTemporalLayerBitrateRatio[i - 1]) + / 100); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "nTempBitrateRatio[%d] : %d", i, TemporalSVC.nTemporalLayerBitrateRatio[i]); + } + pEncOps->Set_LayerChange(pMFCVp9Handle->hMFCHandle, TemporalSVC); + } + } + break; + case OMX_IndexConfigVideoFramerate: + { + OMX_CONFIG_FRAMERATETYPE *pConfigFramerate = (OMX_CONFIG_FRAMERATETYPE *)pConfigData; + OMX_U32 nPortIndex = pConfigFramerate->nPortIndex; + + if (nPortIndex == INPUT_PORT_INDEX) { + nValue = (pConfigFramerate->xEncodeFramerate) >> 16; + pEncOps->Set_FrameRate(pMFCVp9Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] framerate: %d", pExynosComponent, __FUNCTION__, nValue); + } + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pConfigData; + ExynosVideoQPRange qpRange; + + Exynos_OSAL_Memset(&qpRange, 0, sizeof(ExynosVideoQPRange)); + + qpRange.QpMin_I = pQpRange->qpRangeI.nMinQP; + qpRange.QpMax_I = pQpRange->qpRangeI.nMaxQP; + qpRange.QpMin_P = pQpRange->qpRangeP.nMinQP; + qpRange.QpMax_P = pQpRange->qpRangeP.nMaxQP; + + pEncOps->Set_QpRange(pMFCVp9Handle->hMFCHandle, qpRange); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qp range: I(%d, %d), P(%d, %d)", + pExynosComponent, __FUNCTION__, + qpRange.QpMin_I, qpRange.QpMax_I, + qpRange.QpMin_P, qpRange.QpMax_P); + } + break; + case OMX_IndexConfigOperatingRate: + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pConfigData; + OMX_U32 xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + + nValue = pConfigRate->nU32 >> 16; + + if (pMFCVp9Handle->videoInstInfo.supportInfo.enc.bOperatingRateSupport == VIDEO_TRUE) { + if (nValue == ((OMX_U32)INT_MAX >> 16)) { + nValue = (OMX_U32)INT_MAX; + } else { + nValue = nValue * 1000; + } + + pEncOps->Set_OperatingRate(pMFCVp9Handle->hMFCHandle, nValue); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] operating rate: 0x%x", pExynosComponent, __FUNCTION__, nValue); + } else { + if (nValue == (((OMX_U32)INT_MAX) >> 16)) { + nValue = 1000; + } else { + nValue = ((xFramerate >> 16) == 0)? 100:(OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + } + + pEncOps->Set_QosRatio(pMFCVp9Handle->hMFCHandle, nValue); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] qos ratio: %d", pExynosComponent, __FUNCTION__, nValue); + } + + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; + case OMX_IndexConfigCommonOutputSize: + { + OMX_FRAMESIZETYPE *pFrameSize = (OMX_FRAMESIZETYPE *)pConfigData; + OMX_CONFIG_RECTTYPE *pTargetFrame = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].cropRectangle[IMG_CROP_OUTPUT_PORT]); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] resolution(%d x %d) is changed to (%d x %d)", pExynosComponent, __FUNCTION__, + pTargetFrame->nWidth, pTargetFrame->nHeight, + pFrameSize->nWidth, pFrameSize->nHeight); + + /* update target size */ + pTargetFrame->nTop = 0; + pTargetFrame->nLeft = 0; + pTargetFrame->nWidth = pFrameSize->nWidth; + pTargetFrame->nHeight = pFrameSize->nHeight; + + pVideoEnc->bEncDRC = OMX_TRUE; + } + break; + default: + break; + } + + Exynos_OSAL_Free(pDynamicConfigCMD); + + Set_VP9Enc_Param(pExynosComponent); + +EXIT: + return; +} + +OMX_ERRORTYPE GetCodecOutputPrivateData( + OMX_PTR pCodecBuffer, + OMX_PTR *pVirtAddr, + OMX_U32 *pDataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pVideoBuffer = NULL; + + if (pCodecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoBuffer = (ExynosVideoBuffer *)pCodecBuffer; + + if (pVirtAddr != NULL) + *pVirtAddr = pVideoBuffer->planes[0].addr; + + if (pDataSize != NULL) + *pDataSize = pVideoBuffer->planes[0].allocSize; + +EXIT: + return ret; +} + +OMX_BOOL CheckFormatHWSupport( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_COLOR_FORMATTYPE eColorFormat) +{ + OMX_BOOL ret = OMX_FALSE; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int i; + + if (pExynosComponent == NULL) + goto EXIT; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) + goto EXIT; + + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp9Enc == NULL) + goto EXIT; + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + eVideoFormat = (ExynosVideoColorFormatType)Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + for (i = 0; i < VIDEO_COLORFORMAT_MAX; i++) { + if (pVp9Enc->hMFCVp9Handle.videoInstInfo.supportFormat[i] == VIDEO_COLORFORMAT_UNKNOWN) + break; + + if (pVp9Enc->hMFCVp9Handle.videoInstInfo.supportFormat[i] == eVideoFormat) { + ret = OMX_TRUE; + break; + } + } + +EXIT: + return ret; +} + +OMX_ERRORTYPE VP9CodecOpen( + EXYNOS_VP9ENC_HANDLE *pVp9Enc, + ExynosVideoInstInfo *pVideoInstInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if ((pVp9Enc == NULL) || + (pVideoInstInfo == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + /* alloc ops structure */ + pEncOps = (ExynosVideoEncOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncOps)); + pInbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + pOutbufOps = (ExynosVideoEncBufferOps *)Exynos_OSAL_Malloc(sizeof(ExynosVideoEncBufferOps)); + + if ((pEncOps == NULL) || + (pInbufOps == NULL) || + (pOutbufOps == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate decoder ops buffer", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVp9Enc->hMFCVp9Handle.pEncOps = pEncOps; + pVp9Enc->hMFCVp9Handle.pInbufOps = pInbufOps; + pVp9Enc->hMFCVp9Handle.pOutbufOps = pOutbufOps; + + /* function pointer mapping */ + pEncOps->nSize = sizeof(ExynosVideoEncOps); + pInbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + pOutbufOps->nSize = sizeof(ExynosVideoEncBufferOps); + + if (Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to get decoder ops", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for encoder ops */ + if ((pEncOps->Init == NULL) || + (pEncOps->Finalize == NULL) || + (pEncOps->Set_FrameTag == NULL) || + (pEncOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* check mandatory functions for buffer ops */ + if ((pInbufOps->Setup == NULL) || (pOutbufOps->Setup == NULL) || + (pInbufOps->Run == NULL) || (pOutbufOps->Run == NULL) || + (pInbufOps->Stop == NULL) || (pOutbufOps->Stop == NULL) || + (pInbufOps->Enqueue == NULL) || (pOutbufOps->Enqueue == NULL) || + (pInbufOps->Dequeue == NULL) || (pOutbufOps->Dequeue == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Mandatory functions must be supplied", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = VIDEO_MEMORY_USERPTR; +#endif + pVp9Enc->hMFCVp9Handle.hMFCHandle = pVp9Enc->hMFCVp9Handle.pEncOps->Init(pVideoInstInfo); + if (pVp9Enc->hMFCVp9Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to init", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + if (ret != OMX_ErrorNone) { + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pVp9Enc->hMFCVp9Handle.pEncOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pVp9Enc->hMFCVp9Handle.pInbufOps = NULL; + } + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pVp9Enc->hMFCVp9Handle.pOutbufOps = NULL; + } + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecClose(EXYNOS_VP9ENC_HANDLE *pVp9Enc) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + + FunctionIn(); + + if (pVp9Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp9Enc->hMFCVp9Handle.hMFCHandle; + pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps; + pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + pOutbufOps = pVp9Enc->hMFCVp9Handle.pOutbufOps; + + if (hMFCHandle != NULL) { + pEncOps->Finalize(hMFCHandle); + hMFCHandle = pVp9Enc->hMFCVp9Handle.hMFCHandle = NULL; + pVp9Enc->hMFCVp9Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp9Enc->hMFCVp9Handle.bConfiguredMFCDst = OMX_FALSE; + } + + /* Unregister function pointers */ + Exynos_Video_Unregister_Encoder(pEncOps, pInbufOps, pOutbufOps); + + if (pOutbufOps != NULL) { + Exynos_OSAL_Free(pOutbufOps); + pOutbufOps = pVp9Enc->hMFCVp9Handle.pOutbufOps = NULL; + } + + if (pInbufOps != NULL) { + Exynos_OSAL_Free(pInbufOps); + pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps = NULL; + } + + if (pEncOps != NULL) { + Exynos_OSAL_Free(pEncOps); + pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps = NULL; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecStart( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp9Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp9Enc->hMFCVp9Handle.hMFCHandle; + pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + pOutbufOps = pVp9Enc->hMFCVp9Handle.pOutbufOps; + + if (nPortIndex == INPUT_PORT_INDEX) + pInbufOps->Run(hMFCHandle); + else if (nPortIndex == OUTPUT_PORT_INDEX) + pOutbufOps->Run(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecStop( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp9Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + hMFCHandle = pVp9Enc->hMFCVp9Handle.hMFCHandle; + pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + pOutbufOps = pVp9Enc->hMFCVp9Handle.pOutbufOps; + + if ((nPortIndex == INPUT_PORT_INDEX) && (pInbufOps != NULL)) + pInbufOps->Stop(hMFCHandle); + else if ((nPortIndex == OUTPUT_PORT_INDEX) && (pOutbufOps != NULL)) + pOutbufOps->Stop(hMFCHandle); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecOutputBufferProcessRun( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp9Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nPortIndex == INPUT_PORT_INDEX) { + if (pVp9Enc->bSourceStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pVp9Enc->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + if (nPortIndex == OUTPUT_PORT_INDEX) { + if (pVp9Enc->bDestinationStart == OMX_FALSE) { + Exynos_OSAL_SignalSet(pVp9Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pVp9Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecEnqueueAllBuffer( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pVp9Enc->hMFCVp9Handle.hMFCHandle; + int i; + + ExynosVideoEncBufferOps *pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pVp9Enc->hMFCVp9Handle.pOutbufOps; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && + (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pVp9Enc->bSourceStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, INPUT_PORT_INDEX); + + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(input) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoEnc->pMFCEncInputBuffer[i]->fd[0], pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, INPUT_PORT_INDEX, pVideoEnc->pMFCEncInputBuffer[i]); + } + + pInbufOps->Clear_Queue(hMFCHandle); + } else if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pVp9Enc->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] CodecBuffer(output) [%d]: FD(0x%x), VA(0x%x)", + pExynosComponent, __FUNCTION__, + i, pVideoEnc->pMFCEncOutputBuffer[i]->fd[0], pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoEnc->pMFCEncOutputBuffer[i]); + } + + pOutbufOps->Clear_Queue(hMFCHandle); + } + +EXIT: + FunctionOut(); + + return ret; +} + +void VP9CodecSetHdrInfo(OMX_COMPONENTTYPE *pOMXComponent) +{ + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_VP9ENC_HANDLE *pMFCVp9Handle = &pVp9Enc->hMFCVp9Handle; + void *hMFCHandle = pMFCVp9Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps; + + OMX_COLOR_FORMATTYPE eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + if (pMFCVp9Handle->videoInstInfo.supportInfo.enc.bColorAspectsSupport == VIDEO_TRUE) { + ExynosVideoColorAspects BSCA; + Exynos_OSAL_Memset(&BSCA, 0, sizeof(BSCA)); + +#ifdef USE_ANDROID + if (pVideoEnc->surfaceFormat == eColorFormat) { + Exynos_OSAL_GetColorAspectsForBitstream(&(pInputPort->ColorAspects), &(pOutputPort->ColorAspects)); + + /* in case of RGBA, re-update suitable values(transfer) */ + if (pVideoEnc->surfaceFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888) { + /* Eventhough frameworks already sent ColorAspects, + * sometimes dataspace has not set to OMX component because of timing. + * So get dataspace from frameworks ColorAspects. + */ + if (pInputPort->ColorAspects.nDataSpace == 0) { + Exynos_OSAL_UpdateDataSpaceFromAspects(&(pInputPort->ColorAspects)); + } + Exynos_OSAL_GetRGBColorTypeForBitStream(&pOutputPort->ColorAspects, pInputPort->ColorAspects.nDataSpace, eColorFormat); + } + } else { + /* in case of RGBA->YUV, color aspects for bitstream is already updated */ + if (pVideoEnc->surfaceFormat != (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888) + Exynos_OSAL_GetColorAspectsForBitstream(&(pInputPort->ColorAspects), &(pOutputPort->ColorAspects)); + } +#endif + + BSCA.eRangeType = (ExynosRangeType)pOutputPort->ColorAspects.nRangeType; + BSCA.ePrimariesType = (ExynosPrimariesType)pOutputPort->ColorAspects.nPrimaryType; + BSCA.eTransferType = (ExynosTransferType)pOutputPort->ColorAspects.nTransferType; + BSCA.eCoeffType = (ExynosMatrixCoeffType)pOutputPort->ColorAspects.nCoeffType; + + pEncOps->Set_ColorAspects(hMFCHandle, &BSCA); + } + + return ; +} + +OMX_ERRORTYPE Vp9CodecUpdateResolution(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_VP9ENC_HANDLE *pMFCVp9Handle = &pVp9Enc->hMFCVp9Handle; + void *hMFCHandle = pMFCVp9Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + ExynosVideoEncOps *pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + ExynosVideoGeometry bufferConf; + + FunctionIn(); + + pVideoEnc->bEncDRCSync = OMX_TRUE; + + /* stream off */ + ret = VP9CodecStop(pOMXComponent, INPUT_PORT_INDEX); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VP9CodecStop() about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_SignalWait(pVideoEnc->hEncDRCSyncEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pVideoEnc->hEncDRCSyncEvent); + + /* get input buffer geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + if (pInbufOps->Get_Geometry) { + if (pInbufOps->Get_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to get geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + /* clear information */ + pInbufOps->Clear_RegisteredBuffer(hMFCHandle); + pInbufOps->Cleanup_Buffer(hMFCHandle); + + /* set input buffer geometry */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + bufferConf.nFrameHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + bufferConf.nStride = ALIGN(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth, 16); + } else { + bufferConf.nFrameWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + bufferConf.nFrameHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + bufferConf.nStride = ALIGN(pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight, 16); + } + + if (pInbufOps->Set_Geometry) { + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, MAX_INPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + /* header with IDR */ + if (pEncOps->Set_HeaderMode(hMFCHandle, VIDEO_FALSE) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set header mode", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + /* stream on */ + VP9CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + /* reset buffer queue */ + VP9CodecEnqueueAllBuffer(pOMXComponent, INPUT_PORT_INDEX); + + /* clear timestamp */ + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + + /* reinitialize a value for reconfiguring CSC */ + pVideoEnc->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecSrcSetup( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_VP9ENC_HANDLE *pMFCVp9Handle = &pVp9Enc->hMFCVp9Handle; + void *hMFCHandle = pMFCVp9Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoEncOps *pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + ExynosVideoEncParam *pEncParam = NULL; + + ExynosVideoGeometry bufferConf; + OMX_U32 inputBufferNumber = 0; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] first frame has only EOS flag. EOS flag will be returned through FBD", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Malloc(sizeof(BYPASS_BUFFER_INFO)); + if (pBufferInfo == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pBufferInfo->nFlags = pSrcInputData->nFlags; + pBufferInfo->timeStamp = pSrcInputData->timeStamp; + ret = Exynos_OSAL_Queue(&pVp9Enc->bypassBufferInfoQ, (void *)pBufferInfo); + + if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_OSAL_SignalSet(pVp9Enc->hDestinationInStartEvent); + Exynos_OSAL_SleepMillisec(0); + } else if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_OSAL_SignalSet(pVp9Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + ret = OMX_ErrorNone; + goto EXIT; + } + + Set_VP9Enc_Param(pExynosComponent); + + pEncParam = &pMFCVp9Handle->encParam; + if (pEncOps->Set_EncParam) { + if(pEncOps->Set_EncParam(pVp9Enc->hMFCVp9Handle.hMFCHandle, pEncParam) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + Print_VP9Enc_Param(pEncParam); + +#ifdef USE_ANDROID + VP9CodecSetHdrInfo(pOMXComponent); +#endif + + if (pMFCVp9Handle->videoInstInfo.supportInfo.enc.bPrioritySupport == VIDEO_TRUE) + pEncOps->Set_Priority(hMFCHandle, pVideoEnc->nPriority); + + if (pEncParam->commonParam.bDisableDFR == VIDEO_TRUE) + pEncOps->Disable_DynamicFrameRate(pMFCVp9Handle->hMFCHandle, VIDEO_TRUE); + + /* input buffer info: only 3 config values needed */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eColorFormat = pEncParam->commonParam.FrameMap; + + { + OMX_S32 nTargetWidth, nTargetHeight; + + /* uses specified target size instead of size on output port */ + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + /* use specified resolution */ + nTargetWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nTargetHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nTargetWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nTargetHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = nTargetWidth; + bufferConf.nFrameHeight = nTargetHeight; + bufferConf.nStride = ALIGN(nTargetWidth, 16); + } else { + bufferConf.nFrameWidth = nTargetHeight; + bufferConf.nFrameHeight = nTargetWidth; + bufferConf.nStride = ALIGN(nTargetHeight, 16); + } + } + + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + pInbufOps->Set_Shareable(hMFCHandle); + inputBufferNumber = MAX_INPUTBUFFER_NUM_DYNAMIC; + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + /* should be done before prepare input buffer */ + if (pInbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* set input buffer geometry */ + if (pInbufOps->Set_Geometry) { + if (pInbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about input", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, inputBufferNumber) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup input buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pInputPort->bufferProcessType & BUFFER_SHARE) && + (pInputPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + /* data buffer */ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + pVp9Enc->hMFCVp9Handle.bConfiguredMFCSrc = OMX_TRUE; + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecDstSetup(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_MFC_VP9ENC_HANDLE *pMFCVp9Handle = &pVp9Enc->hMFCVp9Handle; + void *hMFCHandle = pMFCVp9Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pOutbufOps = pVp9Enc->hMFCVp9Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + unsigned int nDataLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + int i, nOutBufSize = 0, nOutputBufferCnt = 0; + + FunctionIn(); + + nOutBufSize = pOutputPort->portDefinition.nBufferSize; + if ((pOutputPort->bufferProcessType & BUFFER_COPY) || + (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nOutBufSize = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * + pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nOutBufSize = Exynos_OSAL_GetOutBufferSize(pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.nBufferSize); +#endif + + } + + /* set geometry for output (dst) */ + if (pOutbufOps->Set_Geometry) { + /* only 2 config values needed */ + bufferConf.eCompressionFormat = VIDEO_CODING_VP9; + bufferConf.nSizeImage = nOutBufSize; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pOutputPort); + + if (pOutbufOps->Set_Geometry(pVp9Enc->hMFCVp9Handle.hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to set geometry about output", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pOutputPort->bufferProcessType & BUFFER_COPY) + nOutputBufferCnt = MFC_OUTPUT_BUFFER_NUM_MAX; + else + nOutputBufferCnt = pOutputPort->portDefinition.nBufferCountActual; + + if (pOutbufOps->Setup(pVp9Enc->hMFCVp9Handle.hMFCHandle, nOutputBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to setup output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + nAllocLen[0] = nOutBufSize; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, MFC_OUTPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Allocate_CodecBuffers for output", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + /* Enqueue output buffer */ + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr, + (unsigned long *)pVideoEnc->pMFCEncOutputBuffer[i]->fd, + pVideoEnc->pMFCEncOutputBuffer[i]->bufferSize, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + NULL); + } + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /* Register output buffer */ + /*************/ + /* TBD */ + /*************/ + } + + pVp9Enc->hMFCVp9Handle.bConfiguredMFCDst = OMX_TRUE; + + if (VP9CodecStart(pOMXComponent, OUTPUT_PORT_INDEX) != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to run output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nParamIndex %x", pExynosComponent, __FUNCTION__, (int)nParamIndex); + switch ((int)nParamIndex) { + case OMX_IndexParamVideoVp9: + { + OMX_VIDEO_PARAM_VP9TYPE *pDstVP9Component = (OMX_VIDEO_PARAM_VP9TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP9TYPE *pSrcVP9Component = NULL; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstVP9Component, sizeof(OMX_VIDEO_PARAM_VP9TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstVP9Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVP9Component = &pVp9Enc->VP9Component[pDstVP9Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstVP9Component) + nOffset, + ((char *)pSrcVP9Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_VP9TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE *)pComponentParameterStructure; + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_VP9_ENC_ROLE); + } + break; + case OMX_IndexParamVideoProfileLevelQuerySupported: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + ret = GetIndexToProfileLevel(pExynosComponent, pDstProfileLevel); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pDstProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE*)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP9TYPE *pSrcVP9Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVP9Component = &pVp9Enc->VP9Component[pDstProfileLevel->nPortIndex]; + pDstProfileLevel->eProfile = pSrcVP9Component->eProfile; + pDstProfileLevel->eLevel = pSrcVP9Component->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcErrorCorrectionType = &pVp9Enc->errorCorrectionType[OUTPUT_PORT_INDEX]; + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pVp9Enc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pVp9Enc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pVp9Enc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pVp9Enc->qpRangeP.nMaxQP; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamVideoAndroidVp8Encoder: + { + + OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *pDstVp9EncoderType = (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *pSrcVp9EncoderType = &pVp9Enc->AndroidVp9EncoderType; + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pDstVp9EncoderType, sizeof(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDstVp9EncoderType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcVp9EncoderType->nKeyFrameInterval = pVp9Enc->nPFrames + 1; + pSrcVp9EncoderType->nMinQuantizer = pVp9Enc->qpRangeI.nMinQP; + pSrcVp9EncoderType->nMaxQuantizer = pVp9Enc->qpRangeI.nMaxQP; + + Exynos_OSAL_Memcpy(((char *)pDstVp9EncoderType) + nOffset, + ((char *)pSrcVp9EncoderType) + nOffset, + sizeof(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE) - nOffset); + } + break; +#endif + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pEnablePVC->nU32 = pVideoEnc->bPVCMode; + } + break; + case OMX_IndexParamNumberRefPframes: + { + OMX_PARAM_U32TYPE *pNumberRefPframes = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pNumberRefPframes, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pNumberRefPframes->nU32 = pVp9Enc->hMFCVp9Handle.nRefForPframes; + } + break; + default: + ret = Exynos_OMX_VideoEncodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexParamVideoVp9: + { + OMX_VIDEO_PARAM_VP9TYPE *pDstVP9Component = NULL; + OMX_VIDEO_PARAM_VP9TYPE *pSrcVP9Component = (OMX_VIDEO_PARAM_VP9TYPE *)pComponentParameterStructure; + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcVP9Component, sizeof(OMX_VIDEO_PARAM_VP9TYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcVP9Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstVP9Component = &pVp9Enc->VP9Component[pSrcVP9Component->nPortIndex]; + + Exynos_OSAL_Memcpy(((char *)pDstVP9Component) + nOffset, + ((char *)pSrcVP9Component) + nOffset, + sizeof(OMX_VIDEO_PARAM_VP9TYPE) - nOffset); + } + break; + case OMX_IndexParamStandardComponentRole: + { + OMX_PARAM_COMPONENTROLETYPE *pComponentRole = (OMX_PARAM_COMPONENTROLETYPE*)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pComponentRole, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->currentState != OMX_StateLoaded) && + (pExynosComponent->currentState != OMX_StateWaitForResources)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (!Exynos_OSAL_Strcmp((char*)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_VP9_ENC_ROLE)) { + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingVP9; + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP9TYPE *pDstVP9Component = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstVP9Component = &pVp9Enc->VP9Component[pSrcProfileLevel->nPortIndex]; + + if (OMX_FALSE == CheckProfileLevelSupport(pExynosComponent, pSrcProfileLevel)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pDstVP9Component->eProfile = pSrcProfileLevel->eProfile; + pDstVP9Component->eLevel = pSrcProfileLevel->eLevel; + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstErrorCorrectionType = &pVp9Enc->errorCorrectionType[OUTPUT_PORT_INDEX]; + pDstErrorCorrectionType->bEnableHEC = pSrcErrorCorrectionType->bEnableHEC; + pDstErrorCorrectionType->bEnableResync = pSrcErrorCorrectionType->bEnableResync; + pDstErrorCorrectionType->nResynchMarkerSpacing = pSrcErrorCorrectionType->nResynchMarkerSpacing; + pDstErrorCorrectionType->bEnableDataPartitioning = pSrcErrorCorrectionType->bEnableDataPartitioning; + pDstErrorCorrectionType->bEnableRVLC = pSrcErrorCorrectionType->bEnableRVLC; + } + break; + case OMX_IndexParamVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d])", __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Enc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pVp9Enc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pVp9Enc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pVp9Enc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + } + break; +#ifdef USE_ANDROID + case OMX_IndexParamVideoAndroidVp8Encoder: + { + OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *pSrcVp9EncoderType = (OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE *pDstVp9EncoderType = &pVp9Enc->AndroidVp9EncoderType; + + + /* except nSize, nVersion and nPortIndex */ + int nOffset = sizeof(OMX_U32) + sizeof(OMX_VERSIONTYPE) + sizeof(OMX_U32); + + ret = Exynos_OMX_Check_SizeVersion(pSrcVp9EncoderType, sizeof(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcVp9EncoderType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pVp9Enc->hMFCVp9Handle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) && + (pSrcVp9EncoderType->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: Temporal SVC is not supported", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((pSrcVp9EncoderType->nMinQuantizer > pSrcVp9EncoderType->nMaxQuantizer) || + (pSrcVp9EncoderType->nMaxQuantizer >= VP9_QP_INDEX_RANGE)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: QP value is invalid(min:%d, max:%d)", __FUNCTION__, + pSrcVp9EncoderType->nMinQuantizer, pSrcVp9EncoderType->nMaxQuantizer); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVp9Enc->nPFrames = pSrcVp9EncoderType->nKeyFrameInterval - 1; + + pVp9Enc->qpRangeI.nMinQP = pSrcVp9EncoderType->nMinQuantizer; + pVp9Enc->qpRangeI.nMaxQP = pSrcVp9EncoderType->nMaxQuantizer; + + Exynos_OSAL_Memcpy(((char *)pDstVp9EncoderType) + nOffset, + ((char *)pSrcVp9EncoderType) + nOffset, + sizeof(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE) - nOffset); + } + break; +#endif + case OMX_IndexParamVideoEnablePVC: + { + OMX_PARAM_U32TYPE *pEnablePVC = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pEnablePVC, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVideoEnc->bPVCMode = (pEnablePVC->nU32)? OMX_TRUE:OMX_FALSE; + } + break; + case OMX_IndexParamNumberRefPframes: + { + OMX_PARAM_U32TYPE *pNumberRefPframes = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pNumberRefPframes, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + pVp9Enc->hMFCVp9Handle.nRefForPframes = pNumberRefPframes->nU32; + } + break; + default: + ret = Exynos_OMX_VideoEncodeSetParameter(hComponent, nIndex, pComponentParameterStructure); + break; + } +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_GetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pQpRange->qpRangeI.nMinQP = pVp9Enc->qpRangeI.nMinQP; + pQpRange->qpRangeI.nMaxQP = pVp9Enc->qpRangeI.nMaxQP; + pQpRange->qpRangeP.nMinQP = pVp9Enc->qpRangeP.nMinQP; + pQpRange->qpRangeP.nMaxQP = pVp9Enc->qpRangeP.nMaxQP; + } + break; + default: + ret = Exynos_OMX_VideoEncodeGetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_SetConfig( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_U32 nPFrames = (*((OMX_U32 *)pComponentConfigStructure)) - 1; + + pVp9Enc->nPFrames = nPFrames; + + ret = OMX_ErrorNone; + } + break; + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE *pQpRange = (OMX_VIDEO_QPRANGETYPE *)pComponentConfigStructure; + OMX_U32 nPortIndex = pQpRange->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pQpRange, sizeof(OMX_VIDEO_QPRANGETYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pQpRange->qpRangeI.nMinQP > pQpRange->qpRangeI.nMaxQP) || + (pQpRange->qpRangeP.nMinQP > pQpRange->qpRangeP.nMaxQP)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] QP value is invalid(I[min:%d, max:%d], P[min:%d, max:%d])", + pExynosComponent, __FUNCTION__, + pQpRange->qpRangeI.nMinQP, pQpRange->qpRangeI.nMaxQP, + pQpRange->qpRangeP.nMinQP, pQpRange->qpRangeP.nMaxQP); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pVp9Enc->hMFCVp9Handle.videoInstInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_FALSE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] only I-frame's QP range is applied", pExynosComponent, __FUNCTION__); + + pVp9Enc->qpRangeI.nMinQP = pQpRange->qpRangeI.nMinQP; + pVp9Enc->qpRangeI.nMaxQP = pQpRange->qpRangeI.nMaxQP; + pVp9Enc->qpRangeP.nMinQP = pQpRange->qpRangeP.nMinQP; + pVp9Enc->qpRangeP.nMaxQP = pQpRange->qpRangeP.nMaxQP; + } + break; + default: + ret = Exynos_OMX_VideoEncodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + OMX_PTR pDynamicConfigCMD = NULL; + pDynamicConfigCMD = Exynos_OMX_MakeDynamicConfig(nIndex, pComponentConfigStructure); + Exynos_OSAL_Queue(&pExynosComponent->dynamicConfigQ, (void *)pDynamicConfigCMD); + } + + if (ret == (OMX_ERRORTYPE)OMX_ErrorNoneExpiration) + ret = OMX_ErrorNone; + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_GetExtensionIndex( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE *pIndexType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (cParameterName == NULL) || + (pIndexType == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_PVC) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamVideoEnablePVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_REF_NUM_PFRAMES) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamNumberRefPframes; + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = Exynos_OMX_VideoEncodeGetExtensionIndex(hComponent, cParameterName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_ComponentRoleEnum( + OMX_HANDLETYPE hComponent, + OMX_U8 *cRole, + OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if ((hComponent == NULL) || + (cRole == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + Exynos_OSAL_Strcpy((char *)cRole, EXYNOS_OMX_COMPONENT_VP9_ENC_ROLE); + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Init */ +OMX_ERRORTYPE Exynos_VP9Enc_Init(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + OMX_COLOR_FORMATTYPE eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; + + ExynosVideoInstInfo *pVideoInstInfo = &(pVp9Enc->hMFCVp9Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + + FunctionIn(); + + pVp9Enc->hMFCVp9Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp9Enc->hMFCVp9Handle.bConfiguredMFCDst = OMX_FALSE; + pVideoEnc->bFirstInput = OMX_TRUE; + pVideoEnc->bFirstOutput = OMX_FALSE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + if (pInputPort->eMetaDataType != METADATA_TYPE_DISABLED) { + /* metadata buffer */ + pInputPort->bufferProcessType = BUFFER_SHARE; + +#ifdef USE_ANDROID + if ((pInputPort->eMetaDataType == METADATA_TYPE_DATA) && + (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque)) { + pInputPort->eMetaDataType = METADATA_TYPE_GRAPHIC; /* AndoridOpaque means GrallocSource */ + pInputPort->bufferProcessType = BUFFER_COPY; /* will determine a process type after getting a hal format at handle */ + } +#else + if (pInputPort->eMetaDataType == METADATA_TYPE_UBM_BUFFER) { + pInputPort->bufferProcessType = BUFFER_COPY; + } +#endif + } else { + /* data buffer */ + pInputPort->bufferProcessType = BUFFER_COPY; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] CodecOpen W:%d H:%d Bitrate:%d FPS:%d", pExynosComponent, __FUNCTION__, + pInputPort->portDefinition.format.video.nFrameWidth, + pInputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.format.video.nBitrate, + pInputPort->portDefinition.format.video.xFramerate); + pVideoInstInfo->nSize = sizeof(ExynosVideoInstInfo); + pVideoInstInfo->nWidth = pInputPort->portDefinition.format.video.nFrameWidth; + pVideoInstInfo->nHeight = pInputPort->portDefinition.format.video.nFrameHeight; + pVideoInstInfo->nBitrate = pInputPort->portDefinition.format.video.nBitrate; + pVideoInstInfo->xFramerate = pInputPort->portDefinition.format.video.xFramerate; + + /* VP9 Codec Open */ + ret = VP9CodecOpen(pVp9Enc, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + Exynos_SetPlaneToPort(pInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + Exynos_SetPlaneToPort(pOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + + Exynos_OSAL_SemaphoreCreate(&pInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_OSAL_SemaphoreCreate(&pOutputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pOutputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + pVp9Enc->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pVp9Enc->hSourceStartEvent); + pVp9Enc->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pVp9Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalCreate(&pVp9Enc->hDestinationOutStartEvent); + + Exynos_OSAL_Memset(pExynosComponent->bTimestampSlotUsed, 0, sizeof(OMX_BOOL) * MAX_TIMESTAMP); + INIT_ARRAY_TO_VAL(pExynosComponent->timeStamp, DEFAULT_TIMESTAMP_VAL, MAX_TIMESTAMP); + Exynos_OSAL_Memset(pExynosComponent->nFlags, 0, sizeof(OMX_U32) * MAX_FLAGS); + pVp9Enc->hMFCVp9Handle.indexTimestamp = 0; + pVp9Enc->hMFCVp9Handle.outputIndexTimestamp = 0; + + pExynosComponent->getAllDelayBuffer = OMX_FALSE; + + Exynos_OSAL_QueueCreate(&pVp9Enc->bypassBufferInfoQ, QUEUE_ELEMENTS); + +#ifdef USE_CSC_HW + csc_method = CSC_METHOD_HW; +#endif + + pVideoEnc->csc_handle = csc_init(csc_method); + if (pVideoEnc->csc_handle == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVideoEnc->csc_set_format = OMX_FALSE; + +EXIT: + FunctionOut(); + + return ret; +} + +/* MFC Terminate */ +OMX_ERRORTYPE Exynos_VP9Enc_Terminate(OMX_COMPONENTTYPE *pOMXComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent != NULL) { + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + if (pVideoEnc != NULL) { + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + + if (pVideoEnc->csc_handle != NULL) { + csc_deinit(pVideoEnc->csc_handle); + pVideoEnc->csc_handle = NULL; + } + + if (pVp9Enc != NULL) { + Exynos_OSAL_QueueTerminate(&pVp9Enc->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pVp9Enc->hDestinationInStartEvent); + pVp9Enc->hDestinationInStartEvent = NULL; + Exynos_OSAL_SignalTerminate(pVp9Enc->hDestinationOutStartEvent); + pVp9Enc->hDestinationOutStartEvent = NULL; + pVp9Enc->bDestinationStart = OMX_FALSE; + + Exynos_OSAL_SignalTerminate(pVp9Enc->hSourceStartEvent); + pVp9Enc->hSourceStartEvent = NULL; + pVp9Enc->bSourceStart = OMX_FALSE; + } + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pExynosOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosOutputPort->codecSemID); + pExynosOutputPort->codecSemID = NULL; + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_OSAL_QueueTerminate(&pExynosInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pExynosInputPort->codecSemID); + pExynosInputPort->codecSemID = NULL; + + if (pVp9Enc != NULL) { + VP9CodecClose(pVp9Enc); + } + } + } + + Exynos_ResetAllPortConfig(pOMXComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_SrcIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pVp9Enc->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_COLOR_FORMATTYPE inputColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncOps *pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_BUFFERHEADERTYPE tempBufferHeader; + void *pPrivate = NULL; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int i, nPlaneCnt, nConfigCnt; + + FunctionIn(); + +#ifdef USE_ANDROID + { + int fps = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + + if (pVideoEnc->pPerfHandle != NULL) + Exynos_OSAL_Performance(pVideoEnc->pPerfHandle, pVp9Enc->hMFCVp9Handle.indexTimestamp, fps); + } +#endif + + if (pVp9Enc->hMFCVp9Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = VP9CodecSrcSetup(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VP9CodecSrcSetup(0x%x)", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + } + + if (pVp9Enc->hMFCVp9Handle.bConfiguredMFCDst == OMX_FALSE) { + ret = VP9CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VP9CodecDstSetup(0x%x)", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + } + + nConfigCnt = Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ); + if (nConfigCnt > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] has config message(%d)", pExynosComponent, __FUNCTION__, nConfigCnt); + while (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + Change_VP9Enc_Param(pExynosComponent); + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] all config messages were handled", pExynosComponent, __FUNCTION__); + } + + /* DRC on Executing state through OMX_IndexConfigCommonOutputSize */ + if (pVideoEnc->bEncDRC == OMX_TRUE) { + ret = Vp9CodecUpdateResolution(pOMXComponent); + pVideoEnc->bEncDRC = OMX_FALSE; + goto EXIT; + } + + if ((pSrcInputData->dataLen > 0) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + pExynosComponent->timeStamp[pVp9Enc->hMFCVp9Handle.indexTimestamp] = pSrcInputData->timeStamp; + pExynosComponent->bTimestampSlotUsed[pVp9Enc->hMFCVp9Handle.indexTimestamp] = OMX_TRUE; + pExynosComponent->nFlags[pVp9Enc->hMFCVp9Handle.indexTimestamp] = pSrcInputData->nFlags; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p), nFlags: 0x%x, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pSrcInputData->bufferHeader, pSrcInputData->nFlags, + pSrcInputData->timeStamp, (double)(pSrcInputData->timeStamp / 1E6), + pVp9Enc->hMFCVp9Handle.indexTimestamp); + pEncOps->Set_FrameTag(hMFCHandle, pVp9Enc->hMFCVp9Handle.indexTimestamp); + pVp9Enc->hMFCVp9Handle.indexTimestamp++; + pVp9Enc->hMFCVp9Handle.indexTimestamp %= MAX_TIMESTAMP; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + { + OMX_S32 nTargetWidth, nTargetHeight; + + if (pOutputPort->bUseImgCrop[IMG_CROP_OUTPUT_PORT] == OMX_TRUE) { + nTargetWidth = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nWidth; + nTargetHeight = pOutputPort->cropRectangle[IMG_CROP_OUTPUT_PORT].nHeight; + } else { + nTargetWidth = pOutputPort->portDefinition.format.video.nFrameWidth; + nTargetHeight = pOutputPort->portDefinition.format.video.nFrameHeight; + } + /* rotation */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + nTargetWidth, nTargetHeight, + nDataLen, nAllocLen); + } else { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + nTargetHeight, nTargetWidth, + nDataLen, nAllocLen); + } + } + + if (pInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + if (pSrcInputData->dataLen == 0) { + for (i = 0; i < nPlaneCnt; i++) + nDataLen[i] = 0; + } else { + /* when having valid input */ + if (pSrcInputData->buffer.addr[2] != NULL) { + ExynosVideoMeta *pVideoMeta = (ExynosVideoMeta *)pSrcInputData->buffer.addr[2]; + + if ((pVideoMeta->eType & VIDEO_INFO_TYPE_CHECK_PIXEL_FORMAT) && + ((pVideoEnc->surfaceFormat >= OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC) && + (pVideoEnc->surfaceFormat <= OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L80))) { + int nOMXFormat = OMX_COLOR_FormatUnused; + int nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + + nOMXFormat = Exynos_OSAL_HAL2OMXColorFormat(pVideoMeta->nPixelFormat); + if (nOMXFormat != OMX_COLOR_FormatUnused) { + nVideoFormat = Exynos_OSAL_OMX2VideoFormat(nOMXFormat, pInputPort->ePlaneType); + + if (nVideoFormat != VIDEO_COLORFORMAT_UNKNOWN) { + if (pEncOps->Set_ActualFormat(hMFCHandle, nVideoFormat) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] set change format is failed", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] video format is changed: %d", pExynosComponent, __FUNCTION__, nVideoFormat); + } + } + } + } + } + + if ((pVp9Enc->hMFCVp9Handle.videoInstInfo.supportInfo.enc.bDropControlSupport == VIDEO_TRUE) && + (pVideoEnc->bDropControl == OMX_TRUE)) { + pEncOps->Set_DropControl(hMFCHandle, VIDEO_TRUE); + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->buffer.addr, + (unsigned long *)pSrcInputData->buffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about input (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + + VP9CodecStart(pOMXComponent, INPUT_PORT_INDEX); + + if (pVp9Enc->bSourceStart == OMX_FALSE) { + pVp9Enc->bSourceStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp9Enc->hSourceStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + + if ((pVp9Enc->bDestinationStart == OMX_FALSE) && + (pVp9Enc->hMFCVp9Handle.bConfiguredMFCDst == OMX_TRUE)) { + pVp9Enc->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp9Enc->hDestinationInStartEvent); + Exynos_OSAL_SignalSet(pVp9Enc->hDestinationOutStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_SrcOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pVp9Enc->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else { + if (pVideoEnc->bEncDRCSync == OMX_TRUE) { + Exynos_OSAL_SignalSet(pVideoEnc->hEncDRCSyncEvent); + pVideoEnc->bEncDRCSync = OMX_FALSE; + } + pVideoBuffer = NULL; + } + + pSrcOutputData->dataLen = 0; + pSrcOutputData->usedDataLen = 0; + pSrcOutputData->remainDataLen = 0; + pSrcOutputData->nFlags = 0; + pSrcOutputData->timeStamp = 0; + pSrcOutputData->allocSize = 0; + pSrcOutputData->bufferHeader = NULL; + + if (pVideoBuffer == NULL) { + pSrcOutputData->buffer.addr[0] = NULL; + pSrcOutputData->pPrivate = NULL; + } else { + int plane = 0, nPlaneCnt; + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pSrcOutputData->buffer.addr[plane] = pVideoBuffer->planes[plane].addr; + pSrcOutputData->buffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pSrcOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->buffer.addr[0] == + pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]) { + pVideoEnc->pMFCEncInputBuffer[i]->dataSize = 0; + pSrcOutputData->pPrivate = pVideoEnc->pMFCEncInputBuffer[i]; + break; + } + } + + if (i >= MFC_INPUT_BUFFER_NUM_MAX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pInputPort->bufferProcessType == BUFFER_SHARE) { + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input / buffer header(%p)", + pExynosComponent, __FUNCTION__, pSrcOutputData->bufferHeader); + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pInputPort->hBufferCount, pSrcOutputData->bufferHeader, INPUT_PORT_INDEX); +#endif + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_DstIn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + void *hMFCHandle = pVp9Enc->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncBufferOps *pOutbufOps = pVp9Enc->hMFCVp9Handle.pOutbufOps; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + unsigned int nAllocLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + unsigned int nDataLen[VIDEO_BUFFER_MAX_PLANES] = {0, 0, 0}; + + FunctionIn(); + + if (pDstInputData->buffer.addr[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to find output buffer", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + nAllocLen[0] = pOutputPort->portDefinition.nBufferSize; + if ((pOutputPort->bufferProcessType & BUFFER_COPY) || + (pOutputPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + /* OMX buffer is not used directly : CODEC buffer or MetaData */ + nAllocLen[0] = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + nAllocLen[0] = Exynos_OSAL_GetOutBufferSize(pOutputPort->portDefinition.format.video.nFrameWidth, + pOutputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.nBufferSize); +#endif + + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p)", + pExynosComponent, __FUNCTION__, pDstInputData->bufferHeader); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->buffer.addr, + (unsigned long *)&pDstInputData->buffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + pDstInputData->bufferHeader); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to ExtensionEnqueue about output (0x%x)", + pExynosComponent, __FUNCTION__, codecReturn); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + + VP9CodecStart(pOMXComponent, OUTPUT_PORT_INDEX); + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_DstOut( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + void *hMFCHandle = pVp9Enc->hMFCVp9Handle.hMFCHandle; + + ExynosVideoEncOps *pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps; + ExynosVideoEncBufferOps *pOutbufOps = pVp9Enc->hMFCVp9Handle.pOutbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_S32 indexTimestamp = 0; + + FunctionIn(); + + if (pVp9Enc->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + codecReturn = pOutbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer); + if (codecReturn == VIDEO_ERROR_NONE) { + pVideoBuffer = &videoBuffer; + } else if (codecReturn == VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] HW is not available(EIO)", pExynosComponent, __FUNCTION__); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + pDstOutputData->buffer.addr[0] = pVideoBuffer->planes[0].addr; + pDstOutputData->buffer.fd[0] = pVideoBuffer->planes[0].fd; + + pDstOutputData->allocSize = pVideoBuffer->planes[0].allocSize; + pDstOutputData->dataLen = pVideoBuffer->planes[0].dataSize; + pDstOutputData->remainDataLen = pVideoBuffer->planes[0].dataSize; + pDstOutputData->usedDataLen = 0; + + pDstOutputData->pPrivate = pVideoBuffer; + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->buffer.addr[0] == + pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoEnc->pMFCEncOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Can not find a codec buffer", pExynosComponent, __FUNCTION__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + indexTimestamp = pEncOps->Get_FrameTag(pVp9Enc->hMFCVp9Handle.hMFCHandle); + + if (pVideoEnc->bFirstOutput == OMX_FALSE) { + /* Because of Codec2 requirement, Driver doesn't send only CSD buffer in VP8, VP9 encoders. */ + if (indexTimestamp == INDEX_HEADER_DATA) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] codec specific data is generated", pExynosComponent, __FUNCTION__); + + pDstOutputData->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; + pDstOutputData->timeStamp = 0; + } else { + pDstOutputData->timeStamp = pExynosComponent->timeStamp[pVp9Enc->hMFCVp9Handle.outputIndexTimestamp]; + } + + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + pVideoEnc->bFirstOutput = OMX_TRUE; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] out indexTimestamp: %d(0x%x)", pExynosComponent, __FUNCTION__, indexTimestamp, indexTimestamp); + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + if (indexTimestamp == INDEX_AFTER_DRC) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid frame, buffer will be discard and reused", pExynosComponent, __FUNCTION__); + pDstOutputData->timeStamp = 0x00; + pDstOutputData->nFlags = 0x00; + ret = (OMX_ERRORTYPE)OMX_ErrorNoneReuseBuffer; + goto EXIT; + } + + if (indexTimestamp == INDEX_HEADER_DATA) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] codec specific data is generated", pExynosComponent, __FUNCTION__); + indexTimestamp = pVp9Enc->hMFCVp9Handle.outputIndexTimestamp; + pDstOutputData->timeStamp = pExynosComponent->nFlags[indexTimestamp]; + pDstOutputData->nFlags = OMX_BUFFERFLAG_CODECCONFIG | OMX_BUFFERFLAG_ENDOFFRAME; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, frameType: %d, dataLen: %d, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pVideoBuffer->frameType, pDstOutputData->dataLen, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + ret = OMX_ErrorNone; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Tag(%x) is invalid. changes to use outputIndexTimestamp(%d)", + pExynosComponent, __FUNCTION__, + indexTimestamp, pVp9Enc->hMFCVp9Handle.outputIndexTimestamp); + indexTimestamp = pVp9Enc->hMFCVp9Handle.outputIndexTimestamp; + } else { + pVp9Enc->hMFCVp9Handle.outputIndexTimestamp = indexTimestamp; + } + + /* In case of Video buffer batch mode, use timestamp from MFC device driver */ + if (pVideoBuffer->timestamp != 0) + pDstOutputData->timeStamp = pVideoBuffer->timestamp; + else + pDstOutputData->timeStamp = pExynosComponent->timeStamp[indexTimestamp]; + + pExynosComponent->bTimestampSlotUsed[indexTimestamp] = OMX_FALSE; + pDstOutputData->nFlags = pExynosComponent->nFlags[indexTimestamp]; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + } + + if (pVideoBuffer->frameType == VIDEO_FRAME_I) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output / buffer header(%p), nFlags: 0x%x, frameType: %d, dataLen: %d, timestamp %lld us (%.2f secs), Tag: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->bufferHeader, pDstOutputData->nFlags, + pVideoBuffer->frameType, pDstOutputData->dataLen, + pDstOutputData->timeStamp, (double)(pDstOutputData->timeStamp / 1E6), + indexTimestamp); + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] got end of stream", pExynosComponent, __FUNCTION__); + + if (pExynosComponent->bBehaviorEOS == OMX_FALSE) + pDstOutputData->remainDataLen = 0; + else + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_srcInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || + (!CHECK_PORT_POPULATED(pInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = Exynos_VP9Enc_SrcIn(pOMXComponent, pSrcInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_srcOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pSrcOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pInputPort)) || + (!CHECK_PORT_POPULATED(pInputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if ((pVp9Enc->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pInputPort))) { + Exynos_OSAL_SignalWait(pVp9Enc->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get SourceStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp9Enc->hSourceStartEvent); + } + + ret = Exynos_VP9Enc_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_dstInputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstInputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pVp9Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pVp9Enc->hDestinationInStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationInStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp9Enc->hDestinationInStartEvent); + } + + if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + if (Exynos_OSAL_GetElemNum(&pVp9Enc->bypassBufferInfoQ) > 0) { + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pVp9Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + pDstInputData->bufferHeader->nFlags = pBufferInfo->nFlags; + pDstInputData->bufferHeader->nTimeStamp = pBufferInfo->timeStamp; + + Exynos_OMX_OutputBufferReturn(pOMXComponent, pDstInputData->bufferHeader); + Exynos_OSAL_Free(pBufferInfo); + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + if (pVp9Enc->hMFCVp9Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_VP9Enc_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_VP9Enc_dstOutputBufferProcess( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATA *pDstOutputData) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + FunctionIn(); + + if ((!CHECK_PORT_ENABLED(pOutputPort)) || + (!CHECK_PORT_POPULATED(pOutputPort))) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + goto EXIT; + } + + if ((pVp9Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pVp9Enc->hDestinationOutStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] get DestinationOutStartEvent", pExynosComponent, __FUNCTION__); + Exynos_OSAL_SignalReset(pVp9Enc->hDestinationOutStartEvent); + } + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + if (Exynos_OSAL_GetElemNum(&pVp9Enc->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bypassBufferInfoQ has EOS buffer", pExynosComponent, __FUNCTION__); + + if (dstOutputUseBuffer->dataValid == OMX_FALSE) { + pOMXBuffer = Exynos_OutputBufferGetQueue_Direct(pExynosComponent); + if (pOMXBuffer == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } else { + pOMXBuffer = dstOutputUseBuffer->bufferHeader; + } + + pBufferInfo = Exynos_OSAL_Dequeue(&pVp9Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pOMXBuffer->nFlags = pBufferInfo->nFlags; + pOMXBuffer->nTimeStamp = pBufferInfo->timeStamp; + Exynos_OMX_OutputBufferReturn(pOMXComponent, pOMXBuffer); + Exynos_OSAL_Free(pBufferInfo); + + dstOutputUseBuffer->dataValid = OMX_FALSE; + + ret = OMX_ErrorNone; + goto EXIT; + } + } + + ret = Exynos_VP9Enc_DstOut(pOMXComponent, pDstOutputData); + if (((ret != OMX_ErrorNone) && (ret != OMX_ErrorNoneReuseBuffer)) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] send event(OMX_EventError)", + pExynosComponent, __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + +EXIT: + FunctionOut(); + + return ret; +} + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit( + OMX_HANDLETYPE hComponent, + OMX_STRING componentName) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + int i = 0; + + Exynos_OSAL_Get_Log_Property(); // For debuging + FunctionIn(); + + if ((hComponent == NULL) || + (componentName == NULL)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP9_ENC, componentName) != 0) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported component name(%s)", __FUNCTION__, componentName); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to VideoDecodeComponentInit (0x%x)", componentName, __FUNCTION__, ret); + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pExynosComponent->codecType = HW_VIDEO_ENC_CODEC; + + pExynosComponent->componentName = (OMX_STRING)Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_NAME_SIZE); + if (pExynosComponent->componentName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pExynosComponent->componentName, 0, MAX_OMX_COMPONENT_NAME_SIZE); + + pVp9Enc = Exynos_OSAL_Malloc(sizeof(EXYNOS_VP9ENC_HANDLE)); + if (pVp9Enc == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc (0x%x) Line:%d", pExynosComponent, __FUNCTION__, ret, __LINE__); + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVp9Enc, 0, sizeof(EXYNOS_VP9ENC_HANDLE)); + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVideoEnc->hCodecHandle = (OMX_HANDLETYPE)pVp9Enc; + pVp9Enc->qpRangeI.nMinQP = 2; /* index = 2, value = 9 */ + pVp9Enc->qpRangeI.nMaxQP = 63; /* index = 63, value = 255 */ + pVp9Enc->qpRangeP.nMinQP = 2; /* index = 2, value = 9 */ + pVp9Enc->qpRangeP.nMaxQP = 63; /* index = 63, value = 255 */ + + pVideoEnc->quantization.nQpI = 90; + pVideoEnc->quantization.nQpP = 100; + pVideoEnc->quantization.nQpB = 100; + + Exynos_OSAL_Strcpy(pExynosComponent->componentName, EXYNOS_OMX_COMPONENT_VP9_ENC); + + /* Set componentVersion */ + pExynosComponent->componentVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->componentVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->componentVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->componentVersion.s.nStep = STEP_NUMBER; + /* Set specVersion */ + pExynosComponent->specVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; + pExynosComponent->specVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; + pExynosComponent->specVersion.s.nRevision = REVISION_NUMBER; + pExynosComponent->specVersion.s.nStep = STEP_NUMBER; + + /* Input port */ + pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "raw/video"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + + /* Output port */ + pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosPort->portDefinition.format.video.nFrameWidth = DEFAULT_FRAME_WIDTH; + pExynosPort->portDefinition.format.video.nFrameHeight = DEFAULT_FRAME_HEIGHT; + pExynosPort->portDefinition.format.video.nStride = 0; + pExynosPort->portDefinition.nBufferSize = DEFAULT_VIDEO_OUTPUT_BUFFER_SIZE; + pExynosPort->portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingVP9; + Exynos_OSAL_Memset(pExynosPort->portDefinition.format.video.cMIMEType, 0, MAX_OMX_MIMETYPE_SIZE); + Exynos_OSAL_Strcpy(pExynosPort->portDefinition.format.video.cMIMEType, "video/avc"); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatUnused; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_SINGLE; + + for(i = 0; i < ALL_PORT_NUM; i++) { + INIT_SET_SIZE_VERSION(&pVp9Enc->VP9Component[i], OMX_VIDEO_PARAM_VP9TYPE); + pVp9Enc->VP9Component[i].nPortIndex = i; + pVp9Enc->VP9Component[i].eProfile = OMX_VIDEO_VP9Profile0; + pVp9Enc->VP9Component[i].eLevel = OMX_VIDEO_VP9Level41; + } + pVp9Enc->nPFrames = -1; + + Exynos_OSAL_Memset(&pVp9Enc->AndroidVp9EncoderType, 0, sizeof(OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE)); + INIT_SET_SIZE_VERSION(&pVp9Enc->AndroidVp9EncoderType, OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE); + pVp9Enc->AndroidVp9EncoderType.nKeyFrameInterval = pVp9Enc->nPFrames + 1; + pVp9Enc->AndroidVp9EncoderType.eTemporalPattern = OMX_VIDEO_VPXTemporalLayerPatternNone; + pVp9Enc->AndroidVp9EncoderType.nTemporalLayerCount = 1; + for (i = 0; i < OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS; i++) + pVp9Enc->AndroidVp9EncoderType.nTemporalLayerBitrateRatio[i] = 100; + + pVp9Enc->AndroidVp9EncoderType.nMinQuantizer = pVp9Enc->qpRangeI.nMinQP; + pVp9Enc->AndroidVp9EncoderType.nMaxQuantizer = pVp9Enc->qpRangeI.nMaxQP; + + pOMXComponent->GetParameter = &Exynos_VP9Enc_GetParameter; + pOMXComponent->SetParameter = &Exynos_VP9Enc_SetParameter; + pOMXComponent->GetConfig = &Exynos_VP9Enc_GetConfig; + pOMXComponent->SetConfig = &Exynos_VP9Enc_SetConfig; + pOMXComponent->GetExtensionIndex = &Exynos_VP9Enc_GetExtensionIndex; + pOMXComponent->ComponentRoleEnum = &Exynos_VP9Enc_ComponentRoleEnum; + pOMXComponent->ComponentDeInit = &Exynos_OMX_ComponentDeinit; + + pExynosComponent->exynos_codec_componentInit = &Exynos_VP9Enc_Init; + pExynosComponent->exynos_codec_componentTerminate = &Exynos_VP9Enc_Terminate; + + pVideoEnc->exynos_codec_srcInputProcess = &Exynos_VP9Enc_srcInputBufferProcess; + pVideoEnc->exynos_codec_srcOutputProcess = &Exynos_VP9Enc_srcOutputBufferProcess; + pVideoEnc->exynos_codec_dstInputProcess = &Exynos_VP9Enc_dstInputBufferProcess; + pVideoEnc->exynos_codec_dstOutputProcess = &Exynos_VP9Enc_dstOutputBufferProcess; + + pVideoEnc->exynos_codec_start = &VP9CodecStart; + pVideoEnc->exynos_codec_stop = &VP9CodecStop; + pVideoEnc->exynos_codec_bufferProcessRun = &VP9CodecOutputBufferProcessRun; + pVideoEnc->exynos_codec_enqueueAllBuffer = &VP9CodecEnqueueAllBuffer; + + pVideoEnc->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pVideoEnc->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoEnc->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to SharedMemory_Open", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pVp9Enc); + pVp9Enc = pVideoEnc->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + pVp9Enc->hMFCVp9Handle.videoInstInfo.eCodecType = VIDEO_CODING_VP9; + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) + pVp9Enc->hMFCVp9Handle.videoInstInfo.eSecurityType = VIDEO_SECURE; + else + pVp9Enc->hMFCVp9Handle.videoInstInfo.eSecurityType = VIDEO_NORMAL; + + pVp9Enc->hMFCVp9Handle.nRefForPframes = 1; + + if (Exynos_Video_GetInstInfo(&(pVp9Enc->hMFCVp9Handle.videoInstInfo), VIDEO_FALSE /* enc */) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Exynos_Video_GetInstInfo is failed", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pVp9Enc); + pVp9Enc = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for enc : temporal-svc(%d)/qp-range(%d)/pvc(%d)/CA(%d)", + pExynosComponent, __FUNCTION__, + (pVp9Enc->hMFCVp9Handle.videoInstInfo.supportInfo.enc.bTemporalSvcSupport), + (pVp9Enc->hMFCVp9Handle.videoInstInfo.supportInfo.enc.bQpRangePBSupport), + (pVp9Enc->hMFCVp9Handle.videoInstInfo.supportInfo.enc.bPVCSupport), + (pVp9Enc->hMFCVp9Handle.videoInstInfo.supportInfo.enc.bColorAspectsSupport)); + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + +#ifdef USE_ANDROID + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-qp-range", (OMX_INDEXTYPE)OMX_IndexConfigVideoQPRange); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-ref-pframes", (OMX_INDEXTYPE)OMX_IndexParamNumberRefPframes); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-drop-control", (OMX_INDEXTYPE)OMX_IndexParamVideoDropControl); + Exynos_OSAL_AddVendorExt(hComponent, "sec-ext-enc-disable-dfr", (OMX_INDEXTYPE)OMX_IndexParamVideoDisableDFR); +#endif + + pExynosComponent->currentState = OMX_StateLoaded; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_VP9ENC_HANDLE *pVp9Enc = NULL; + + FunctionIn(); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (((pExynosComponent->currentState != OMX_StateInvalid) && + (pExynosComponent->currentState != OMX_StateLoaded)) || + ((pExynosComponent->currentState == OMX_StateLoaded) && + (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle))) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] in curState(0x%x), OMX_FreeHandle() is called. change to OMX_StateInvalid", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + Exynos_OMX_Component_AbnormalTermination(hComponent); + } + + Exynos_OSAL_SharedMemory_Close(pVideoEnc->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp9Enc != NULL) { + Exynos_OSAL_Free(pVp9Enc); + pVp9Enc = pVideoEnc->hCodecHandle = NULL; + } + +#ifdef USE_ANDROID + Exynos_OSAL_DelVendorExts(hComponent); +#endif + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to VideoDecodeComponentDeinit", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/component/video/enc/vp9/Exynos_OMX_Vp9enc.h b/openmax/component/video/enc/vp9/Exynos_OMX_Vp9enc.h new file mode 100644 index 0000000..b713fee --- /dev/null +++ b/openmax/component/video/enc/vp9/Exynos_OMX_Vp9enc.h @@ -0,0 +1,94 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Vp9enc.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2015.04.14 : Create + */ + +#ifndef EXYNOS_OMX_VP9_ENC_COMPONENT +#define EXYNOS_OMX_VP9_ENC_COMPONENT + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "OMX_Video.h" + +#include "ExynosVideoApi.h" + +typedef struct _EXYNOS_MFC_VP9ENC_HANDLE +{ + OMX_HANDLETYPE hMFCHandle; + + OMX_U32 indexTimestamp; + OMX_U32 outputIndexTimestamp; + OMX_BOOL bConfiguredMFCSrc; + OMX_BOOL bConfiguredMFCDst; + + ExynosVideoEncOps *pEncOps; + ExynosVideoEncBufferOps *pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps; + ExynosVideoEncParam encParam; + ExynosVideoInstInfo videoInstInfo; + + OMX_U32 nRefForPframes; + + #define MAX_PROFILE_NUM 4 + OMX_VIDEO_VP9PROFILETYPE profiles[MAX_PROFILE_NUM]; + OMX_S32 nProfileCnt; + OMX_VIDEO_VP9LEVELTYPE maxLevel; +} EXYNOS_MFC_VP9ENC_HANDLE; + +typedef struct _EXYNOS_VP9ENC_HANDLE +{ + /* OMX Codec specific */ + OMX_VIDEO_PARAM_VP9TYPE VP9Component[ALL_PORT_NUM]; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType[ALL_PORT_NUM]; + OMX_U32 nPFrames; /* IDR period control */ + OMX_VIDEO_QPRANGE qpRangeI; + OMX_VIDEO_QPRANGE qpRangeP; + + OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE AndroidVp9EncoderType; + + /* SEC MFC Codec specific */ + EXYNOS_MFC_VP9ENC_HANDLE hMFCVp9Handle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationInStartEvent; + OMX_HANDLETYPE hDestinationOutStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; +} EXYNOS_VP9ENC_HANDLE; + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF OMX_ERRORTYPE Exynos_OMX_ComponentInit(OMX_HANDLETYPE hComponent, OMX_STRING componentName); + OMX_ERRORTYPE Exynos_OMX_ComponentDeinit(OMX_HANDLETYPE hComponent); + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/openmax/component/video/enc/vp9/NOTICE b/openmax/component/video/enc/vp9/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/component/video/enc/vp9/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/component/video/enc/vp9/library_register.c b/openmax/component/video/enc/vp9/library_register.c new file mode 100644 index 0000000..d74b842 --- /dev/null +++ b/openmax/component/video/enc/vp9/library_register.c @@ -0,0 +1,58 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2015.04.14 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "library_register.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VP9_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent) +{ + FunctionIn(); + + if (ppExynosComponent == NULL) + goto EXIT; + + /* component 1 - video encoder VP9 */ + Exynos_OSAL_Strcpy(ppExynosComponent[0]->componentName, EXYNOS_OMX_COMPONENT_VP9_ENC); + Exynos_OSAL_Strcpy(ppExynosComponent[0]->roles[0], EXYNOS_OMX_COMPONENT_VP9_ENC_ROLE); + ppExynosComponent[0]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/openmax/component/video/enc/vp9/library_register.h b/openmax/component/video/enc/vp9/library_register.h new file mode 100644 index 0000000..bcb1b21 --- /dev/null +++ b/openmax/component/video/enc/vp9/library_register.h @@ -0,0 +1,56 @@ +/* + * + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file library_register.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2015.04.14 : Create + */ + +#ifndef EXYNOS_OMX_VP9_ENC_REG +#define EXYNOS_OMX_VP9_ENC_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Component.h" +#include "Exynos_OMX_Component_Register.h" + + +#define OSCL_EXPORT_REF __attribute__((visibility("default"))) +#define MAX_COMPONENT_NUM 1 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* VP9 */ +#define EXYNOS_OMX_COMPONENT_VP9_ENC "OMX.Exynos.VP9.Encoder" +#define EXYNOS_OMX_COMPONENT_VP9_ENC_ROLE "video_encoder.vp9" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **ppExynosComponent); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/openmax/core/Android.mk b/openmax/core/Android.mk new file mode 100644 index 0000000..7c97fdf --- /dev/null +++ b/openmax/core/Android.mk @@ -0,0 +1,92 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OMX_Component_Register.c \ + Exynos_OMX_Core.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libExynosOMX_Core +LOCAL_PROPRIETARY_MODULE := true + +LOCAL_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_OSAL libExynosOMX_Basecomponent +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils liblog \ + libExynosOMX_Resourcemanager + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_TOP)/component/common + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_DISABLE_RAPID_COMPONENT_LOAD), true) +LOCAL_CFLAGS += -DUSE_DISABLE_RAPID_COMPONENT_LOAD +endif + +ifeq ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_ALP_AUDIO), true) + ifeq ($(BOARD_USE_SEIREN_AUDIO), true) + LOCAL_CFLAGS += -DUSE_SEIREN_AUDIO_COMPONENT_LOAD + else + LOCAL_CFLAGS += -DUSE_ALP_AUDIO_COMPONENT_LOAD + endif +endif + +ifeq ($(EXYNOS_OMX_SUPPORT_TUNNELING), true) +LOCAL_CFLAGS += -DTUNNELING_SUPPORT +endif + +ifeq ($(EXYNOS_OMX_SUPPORT_EGL_IMAGE), true) +LOCAL_CFLAGS += -DEGL_IMAGE_SUPPORT +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +ifneq ($(BOARD_USE_HEVCENC_SUPPORT), true) +LOCAL_CFLAGS += -DDISABLE_HEVC_ENC_CODEC +LOCAL_CFLAGS += -DDISABLE_CODEC_COMP +endif + +ifneq ($(BOARD_USE_VP9DEC_SUPPORT), true) +LOCAL_CFLAGS += -DDISABLE_VP9_DEC_CODEC +LOCAL_CFLAGS += -DDISABLE_CODEC_COMP +endif + +ifneq ($(BOARD_USE_VP9ENC_SUPPORT), true) +LOCAL_CFLAGS += -DDISABLE_VP9_ENC_CODEC +LOCAL_CFLAGS += -DDISABLE_CODEC_COMP +endif + +ifneq ($(BOARD_USE_WFDENC_SUPPORT), true) +LOCAL_CFLAGS += -DDISABLE_WFD_ENC_CODEC +LOCAL_CFLAGS += -DDISABLE_CODEC_COMP +endif + +ifeq ($(BOARD_USE_NON_DRM_CODEC_ONLY), true) +LOCAL_CFLAGS += -DDISABLE_SECURE_CODEC +LOCAL_CFLAGS += -DDISABLE_CODEC_COMP +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_SHARED_LIBRARY) diff --git a/openmax/core/Exynos_OMX_Component_Register.c b/openmax/core/Exynos_OMX_Component_Register.c new file mode 100644 index 0000000..bdd1b7d --- /dev/null +++ b/openmax/core/Exynos_OMX_Component_Register.c @@ -0,0 +1,833 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Component_Register.c + * @brief Exynos OpenMAX IL Component Register + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "OMX_Component.h" +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Library.h" +#include "Exynos_OMX_Component_Register.h" +#include "Exynos_OMX_Macros.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_COMP_REGS" +#include "Exynos_OSAL_Log.h" + +static EXYNOS_OMX_COMPONENT_REGLIST gTableComponents[] = { +#ifndef USE_CUSTOM_COMPONENT_SUPPORT + /* Video Decoder */ + { + { "OMX.Exynos.AVC.Decoder", + { + {"video_decoder.avc"}, + }, + 1, + }, + "libOMX.Exynos.AVC.Decoder.so" + }, + { + { "OMX.Exynos.AVC.Decoder.secure", + { + {"video_decoder.avc"}, + }, + 1, + }, + "libOMX.Exynos.AVC.Decoder.so" + }, + { + { "OMX.Exynos.HEVC.Decoder", + { + {"video_decoder.hevc"}, + }, + 1, + }, + "libOMX.Exynos.HEVC.Decoder.so" + }, + { + { "OMX.Exynos.HEVC.Decoder.secure", + { + {"video_decoder.hevc"}, + }, + 1, + }, + "libOMX.Exynos.HEVC.Decoder.so" + }, + { + { "OMX.Exynos.MPEG2.Decoder", + { + {"video_decoder.mpeg2"}, + }, + 1, + }, + "libOMX.Exynos.MPEG2.Decoder.so" + }, + { + { "OMX.Exynos.MPEG4.Decoder", + { + {"video_decoder.mpeg4"}, + }, + 1, + }, + "libOMX.Exynos.MPEG4.Decoder.so" + }, + { + { "OMX.Exynos.MPEG4.Decoder.secure", + { + {"video_decoder.mpeg4"}, + }, + 1, + }, + "libOMX.Exynos.MPEG4.Decoder.so" + }, + { + { "OMX.Exynos.H263.Decoder", + { + {"video_decoder.h263"}, + }, + 1, + }, + "libOMX.Exynos.MPEG4.Decoder.so" + }, + { + { "OMX.Exynos.WMV.Decoder", + { + {"video_decoder.vc1"}, + }, + 1, + }, + "libOMX.Exynos.WMV.Decoder.so" + }, + { + { "OMX.Exynos.VP8.Decoder", + { + {"video_decoder.vp8"}, + }, + 1, + }, + "libOMX.Exynos.VP8.Decoder.so" + }, + { + { "OMX.Exynos.VP9.Decoder", + { + {"video_decoder.vp9"}, + }, + 1, + }, + "libOMX.Exynos.VP9.Decoder.so" + }, + { + { "OMX.Exynos.VP9.Decoder.secure", + { + {"video_decoder.vp9"}, + }, + 1, + }, + "libOMX.Exynos.VP9.Decoder.so" + }, +#else + { + { "OMX.Exynos.avc.dec", + { + {"video_decoder.avc"}, + }, + 1, + }, + "libOMX.Exynos.AVC.Decoder.so" + }, + { + { "OMX.Exynos.avc.dec.secure", + { + {"video_decoder.avc"}, + }, + 1, + }, + "libOMX.Exynos.AVC.Decoder.so" + }, + { + { "OMX.Exynos.hevc.dec", + { + {"video_decoder.hevc"}, + }, + 1, + }, + "libOMX.Exynos.HEVC.Decoder.so" + }, + { + { "OMX.Exynos.hevc.dec.secure", + { + {"video_decoder.hevc"}, + }, + 1, + }, + "libOMX.Exynos.HEVC.Decoder.so" + }, + { + { "OMX.Exynos.mpeg2.dec", + { + {"video_decoder.mpeg2"}, + }, + 1, + }, + "libOMX.Exynos.MPEG2.Decoder.so" + }, + { + { "OMX.Exynos.mpeg4.dec", + { + {"video_decoder.mpeg4"}, + }, + 1, + }, + "libOMX.Exynos.MPEG4.Decoder.so" + }, + { + { "OMX.Exynos.mpeg4.dec.secure", + { + {"video_decoder.mpeg4"}, + }, + 1, + }, + "libOMX.Exynos.MPEG4.Decoder.so" + }, + { + { "OMX.Exynos.h263.dec", + { + {"video_decoder.h263"}, + }, + 1, + }, + "libOMX.Exynos.MPEG4.Decoder.so" + }, + { + { "OMX.Exynos.vc1.dec", + { + {"video_decoder.vc1"}, + }, + 1, + }, + "libOMX.Exynos.WMV.Decoder.so" + }, + { + { "OMX.Exynos.vp8.dec", + { + {"video_decoder.vp8"}, + }, + 1, + }, + "libOMX.Exynos.VP8.Decoder.so" + }, + { + { "OMX.Exynos.vp9.dec", + { + {"video_decoder.vp9"}, + }, + 1, + }, + "libOMX.Exynos.VP9.Decoder.so" + }, + { + { "OMX.Exynos.vp9.dec.secure", + { + {"video_decoder.vp9"}, + }, + 1, + }, + "libOMX.Exynos.VP9.Decoder.so" + }, +#endif + + /* Video Encoder */ + { + { "OMX.Exynos.AVC.Encoder", + { + {"video_encoder.avc"}, + }, + 1, + }, + "libOMX.Exynos.AVC.Encoder.so" + }, + { + { "OMX.Exynos.AVC.Encoder.secure", + { + {"video_encoder.avc-wfd"}, + }, + 1, + }, + "libOMX.Exynos.AVC.Encoder.so" + }, + { + { "OMX.Exynos.HEVC.Encoder", + { + {"video_encoder.hevc"}, + }, + 1, + }, + "libOMX.Exynos.HEVC.Encoder.so" + }, + { + { "OMX.Exynos.HEVC.Encoder.secure", + { + {"video_encoder.hevc-wfd"}, + }, + 1, + }, + "libOMX.Exynos.HEVC.Encoder.so" + }, + { + { "OMX.Exynos.MPEG4.Encoder", + { + {"video_encoder.mpeg4"}, + }, + 1, + }, + "libOMX.Exynos.MPEG4.Encoder.so" + }, + { + { "OMX.Exynos.H263.Encoder", + { + {"video_encoder.h263"}, + }, + 1, + }, + "libOMX.Exynos.MPEG4.Encoder.so" + }, + { + { "OMX.Exynos.VP8.Encoder", + { + {"video_encoder.vp8"}, + }, + 1, + }, + "libOMX.Exynos.VP8.Encoder.so" + }, + { + { "OMX.Exynos.VP9.Encoder", + { + {"video_encoder.vp9"}, + }, + 1, + }, + "libOMX.Exynos.VP9.Encoder.so" + }, + { + { "OMX.Exynos.AVC.WFD.Encoder", + { + {"video_encoder.avc-wfd"}, + }, + 1, + }, + "libOMX.Exynos.AVC.WFD.Encoder.so" + }, + { + { "OMX.Exynos.AVC.WFD.Encoder.secure", + { + {"video_encoder.avc-wfd"}, + }, + 1, + }, + "libOMX.Exynos.AVC.WFD.Encoder.so" + }, + { + { "OMX.Exynos.HEVC.WFD.Encoder", + { + {"video_encoder.hevc-wfd"}, + }, + 1, + }, + "libOMX.Exynos.HEVC.WFD.Encoder.so" + }, + { + { "OMX.Exynos.HEVC.WFD.Encoder.secure", + { + {"video_encoder.hevc-wfd"}, + }, + 1, + }, + "libOMX.Exynos.HEVC.WFD.Encoder.so" + }, + + /* Audio Decoder */ +#ifdef USE_SEIREN_AUDIO_COMPONENT_LOAD + /* Audio */ + /* MP3 Decoder */ + { + { "OMX.Exynos.MP3.Decoder", + { + {"audio_decoder.mp3"}, + }, + 1, + }, + "libOMX.Exynos.MP3.Decoder.so" + }, + + /* MP1 Decoder */ + { + { "OMX.Exynos.MP1.Decoder", + { + {"audio_decoder.mp1"}, + }, + 1, + }, + "libOMX.Exynos.MP1.Decoder.so" + }, + + /* MP2 Decoder */ + { + { "OMX.Exynos.MP2.Decoder", + { + {"audio_decoder.mp2"}, + }, + 1, + }, + "libOMX.Exynos.MP2.Decoder.so" + }, + + /* AAC Decoder */ + { + { "OMX.Exynos.AAC.Decoder", + { + {"audio_decoder.aac"}, + }, + 1, + }, + "libOMX.Exynos.AAC.Decoder.so" + }, + + /* FLAC Decoder */ + { + { "OMX.Exynos.FLAC.Decoder", + { + {"audio_decoder.flac"}, + }, + 1, + }, + "libOMX.Exynos.FLAC.Decoder.so" + }, +#endif +#ifdef USE_ALP_AUDIO_COMPONENT_LOAD + /* MP3 Decoder */ + { + { "OMX.Exynos.MP3.Decoder", + { + {"audio_decoder.mp3"}, + }, + 1, + }, + "libOMX.Exynos.MP3.Decoder.so" + }, + + /* WMA Decoder */ + { + { "OMX.Exynos.WMA.Decoder", + { + {"audio_decoder.wma"}, + }, + 1, + }, + "libOMX.Exynos.WMA.Decoder.so" + }, +#endif +}; + +#ifdef DISABLE_CODEC_COMP +static char *gDisableComponents[] = { +#ifdef DISABLE_HEVC_ENC_CODEC + "HEVC.Encoder", +#endif +#ifdef DISABLE_VP9_DEC_CODEC + "VP9.Decoder", + "vp9.dec", +#endif +#ifdef DISABLE_VP9_ENC_CODEC + "VP9.Encoder", +#endif +#ifdef DISABLE_WFD_ENC_CODEC + "WFD.Encoder", +#endif +#ifdef DISABLE_SECURE_CODEC + ".secure", +#endif +}; +#endif + +static void registComponent( + char *sLibName, + EXYNOS_OMX_COMPONENT_REGLIST *pComponentList, + int *pNumComponents) +{ + const char *libPath = NULL; + int nComponents = 0; + unsigned int i; + + FunctionIn(); + + if ((sLibName == NULL) || + (pComponentList == NULL) || + (pNumComponents == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + return; + } + + nComponents = (*pNumComponents); + libPath = Exynos_OSAL_GetLibPath(); + + for (i = 0; i < sizeof(gTableComponents)/sizeof(EXYNOS_OMX_COMPONENT_REGLIST); i++) { + if (Exynos_OSAL_Strcmp(sLibName, gTableComponents[i].libName) == 0) { +#ifdef DISABLE_CODEC_COMP + OMX_BOOL skip = OMX_FALSE; + unsigned int j; + + for (j = 0; j < sizeof(gDisableComponents)/sizeof(gDisableComponents[0]); j++) { + if (Exynos_OSAL_Strstr((const char *)gTableComponents[i].component.componentName, gDisableComponents[j]) != NULL) { + skip = OMX_TRUE; + break; + } + } + + if (skip == OMX_TRUE) + continue; +#endif + Exynos_OSAL_Memcpy(&(pComponentList[nComponents]), &(gTableComponents[i]), sizeof(gTableComponents[i])); + Exynos_OSAL_Memset(pComponentList[nComponents].libName, 0, MAX_OMX_COMPONENT_LIBNAME_SIZE); + Exynos_OSAL_Strcpy(pComponentList[nComponents].libName, (OMX_PTR)libPath); + Exynos_OSAL_Strcat(pComponentList[nComponents].libName, sLibName); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "%s: %s", pComponentList[nComponents].libName, gTableComponents[i].component.componentName); + nComponents++; + } + } + + (*pNumComponents) = nComponents; + +EXIT: + FunctionOut(); + + return; +} + +OMX_ERRORTYPE Exynos_OMX_Component_Register(EXYNOS_OMX_COMPONENT_REGLIST **compList, OMX_U32 *compNum) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + int componentNum = 0, totalCompNum = 0; + const char *libPath = NULL; + char *libName = NULL; + const char *errorMsg = NULL; + DIR *dir = NULL; + struct dirent *d = NULL; + + int i, j; + + int (*Exynos_OMX_COMPONENT_Library_Register)(ExynosRegisterComponentType **exynosComponents); + ExynosRegisterComponentType **exynosComponentsTemp = NULL; + EXYNOS_OMX_COMPONENT_REGLIST *componentList = NULL; + + FunctionIn(); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s lib is loaded", (IS_64BIT_OS? "64bit":"32bit")); + libPath = Exynos_OSAL_GetLibPath(); + dir = opendir(libPath); + if (dir == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to opendir(%s)", __FUNCTION__, libPath); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + componentList = (EXYNOS_OMX_COMPONENT_REGLIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_COMPONENT_REGLIST) * MAX_OMX_COMPONENT_NUM); + if (componentList == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(componentList, 0, sizeof(EXYNOS_OMX_COMPONENT_REGLIST) * MAX_OMX_COMPONENT_NUM); + + libName = Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_LIBNAME_SIZE); + if (libName == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + while ((d = readdir(dir)) != NULL) { + OMX_HANDLETYPE soHandle = NULL; + + if (Exynos_OSAL_CheckLibName(d->d_name) == 0) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "Loading the library: %s", d->d_name); + +#ifndef USE_DISABLE_RAPID_COMPONENT_LOAD + registComponent(d->d_name, componentList, &totalCompNum); +#else + Exynos_OSAL_Memset(libName, 0, MAX_OMX_COMPONENT_LIBNAME_SIZE); + Exynos_OSAL_Strcpy(libName, (OMX_PTR)libPath); + Exynos_OSAL_Strcat(libName, d->d_name); + + if ((soHandle = Exynos_OSAL_dlopen(libName, RTLD_NOW)) != NULL) { + Exynos_OSAL_dlerror(); /* clear error*/ + if ((Exynos_OMX_COMPONENT_Library_Register = Exynos_OSAL_dlsym(soHandle, "Exynos_OMX_COMPONENT_Library_Register")) != NULL) { + componentNum = (*Exynos_OMX_COMPONENT_Library_Register)(NULL); + exynosComponentsTemp = (ExynosRegisterComponentType **)Exynos_OSAL_Malloc(sizeof(ExynosRegisterComponentType *) * componentNum); + if (exynosComponentsTemp == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + for (i = 0; i < componentNum; i++) { + exynosComponentsTemp[i] = Exynos_OSAL_Malloc(sizeof(ExynosRegisterComponentType)); + if (exynosComponentsTemp[i] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__); + for (j = 0; j < i; j++) { + Exynos_OSAL_Free(exynosComponentsTemp[j]); + exynosComponentsTemp[j] = NULL; + } + + Exynos_OSAL_Free(exynosComponentsTemp); + exynosComponentsTemp = NULL; + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Memset(exynosComponentsTemp[i], 0, sizeof(ExynosRegisterComponentType)); + } + + (*Exynos_OMX_COMPONENT_Library_Register)(exynosComponentsTemp); + + for (i = 0; i < componentNum; i++) { +#ifdef DISABLE_CODEC_COMP + OMX_BOOL skip = OMX_FALSE; + int j; + + for (j = 0; j < sizeof(gDisableComponents)/sizeof(gDisableComponents[0]); j++) { + if (Exynos_OSAL_Strstr(exynosComponentsTemp[i]->componentName, gDisableComponents[j]) != NULL) { + skip = OMX_TRUE; + break; + } + } + + if (skip == OMX_TRUE) + continue; +#endif + Exynos_OSAL_Strcpy(componentList[totalCompNum].component.componentName, exynosComponentsTemp[i]->componentName); + for (j = 0; j < (int)exynosComponentsTemp[i]->totalRoleNum; j++) + Exynos_OSAL_Strcpy(componentList[totalCompNum].component.roles[j], exynosComponentsTemp[i]->roles[j]); + componentList[totalCompNum].component.totalRoleNum = exynosComponentsTemp[i]->totalRoleNum; + + Exynos_OSAL_Strcpy(componentList[totalCompNum].libName, libName); + + totalCompNum++; + } + + for (i = 0; i < componentNum; i++) { + Exynos_OSAL_Free(exynosComponentsTemp[i]); + exynosComponentsTemp[i] = NULL; + } + + Exynos_OSAL_Free(exynosComponentsTemp); + exynosComponentsTemp = NULL; + } else { + if ((errorMsg = Exynos_OSAL_dlerror()) != NULL) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "dlsym failed: %s", errorMsg); + } + + Exynos_OSAL_dlclose(soHandle); + soHandle = NULL; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "dlopen failed: %s", Exynos_OSAL_dlerror()); + } +#endif + } else { + /* not a component name line. skip */ + continue; + } + } + + *compList = componentList; + *compNum = totalCompNum; + +EXIT: + if ((ret != OMX_ErrorNone) && + (componentList != NULL)) { + Exynos_OSAL_Free(componentList); + componentList = NULL; + } + + if (dir != NULL) { + closedir(dir); + dir = NULL; + } + + if (libName != NULL) { + Exynos_OSAL_Free(libName); + libName = NULL; + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_Component_Unregister(EXYNOS_OMX_COMPONENT_REGLIST *componentList) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + Exynos_OSAL_Free(componentList); + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentAPICheck(OMX_COMPONENTTYPE *component) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if ((NULL == component->GetComponentVersion) || + (NULL == component->SendCommand) || + (NULL == component->GetParameter) || + (NULL == component->SetParameter) || + (NULL == component->GetConfig) || + (NULL == component->SetConfig) || + (NULL == component->GetExtensionIndex) || + (NULL == component->GetState) || +#ifdef TUNNELING_SUPPORT + (NULL == component->ComponentTunnelRequest) || +#endif + (NULL == component->UseBuffer) || + (NULL == component->AllocateBuffer) || + (NULL == component->FreeBuffer) || + (NULL == component->EmptyThisBuffer) || + (NULL == component->FillThisBuffer) || + (NULL == component->SetCallbacks) || + (NULL == component->ComponentDeInit) || +#ifdef EGL_IMAGE_SUPPORT + (NULL == component->UseEGLImage) || +#endif + (NULL == component->ComponentRoleEnum)) + ret = OMX_ErrorInvalidComponent; + else + ret = OMX_ErrorNone; + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentLoad(EXYNOS_OMX_COMPONENT *exynos_component) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_HANDLETYPE libHandle = NULL; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + + FunctionIn(); + + OMX_ERRORTYPE (*Exynos_OMX_ComponentInit)(OMX_HANDLETYPE hComponent, OMX_STRING componentName); + + libHandle = Exynos_OSAL_dlopen((OMX_STRING)exynos_component->libName, RTLD_NOW); + if (libHandle == NULL) { + ret = OMX_ErrorInvalidComponentName; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_dlopen(%s)", __FUNCTION__, exynos_component->libName); + goto EXIT; + } + + Exynos_OMX_ComponentInit = Exynos_OSAL_dlsym(libHandle, "Exynos_OMX_ComponentInit"); + if (Exynos_OMX_ComponentInit == NULL) { + Exynos_OSAL_dlclose(libHandle); + ret = OMX_ErrorInvalidComponent; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_dlsym(Exynos_OMX_ComponentInit)", __FUNCTION__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_COMPONENTTYPE)); + if (pOMXComponent == NULL) { + Exynos_OSAL_dlclose(libHandle); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__); + goto EXIT; + } + INIT_SET_SIZE_VERSION(pOMXComponent, OMX_COMPONENTTYPE); + + ret = (*Exynos_OMX_ComponentInit)((OMX_HANDLETYPE)pOMXComponent, (OMX_STRING)exynos_component->componentName); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Free(pOMXComponent); + Exynos_OSAL_dlclose(libHandle); + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OMX_ComponentInit() (ret:0x%x)", __FUNCTION__, ret); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } else { + if (Exynos_OMX_ComponentAPICheck(pOMXComponent) != OMX_ErrorNone) { + if (NULL != pOMXComponent->ComponentDeInit) + pOMXComponent->ComponentDeInit(pOMXComponent); + + Exynos_OSAL_Free(pOMXComponent); + Exynos_OSAL_dlclose(libHandle); + ret = OMX_ErrorInvalidComponent; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OMX_ComponentAPICheck()", __FUNCTION__); + goto EXIT; + } + + exynos_component->libHandle = libHandle; + exynos_component->pOMXComponent = pOMXComponent; + ret = OMX_ErrorNone; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OMX_ComponentUnload(EXYNOS_OMX_COMPONENT *exynos_component) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + + FunctionIn(); + + if (!exynos_component) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = exynos_component->pOMXComponent; + if (pOMXComponent != NULL) { + pOMXComponent->ComponentDeInit(pOMXComponent); + Exynos_OSAL_Free(pOMXComponent); + exynos_component->pOMXComponent = NULL; + } + + if (exynos_component->libHandle != NULL) { + Exynos_OSAL_dlclose(exynos_component->libHandle); + exynos_component->libHandle = NULL; + } + +EXIT: + FunctionOut(); + + return ret; +} + diff --git a/openmax/core/Exynos_OMX_Component_Register.h b/openmax/core/Exynos_OMX_Component_Register.h new file mode 100644 index 0000000..1860978 --- /dev/null +++ b/openmax/core/Exynos_OMX_Component_Register.h @@ -0,0 +1,75 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Component_Register.h + * @brief Exynos OpenMAX IL Component Register + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_COMPONENT_REG +#define EXYNOS_OMX_COMPONENT_REG + +#include "Exynos_OMX_Def.h" +#include "OMX_Types.h" +#include "OMX_Core.h" +#include "OMX_Component.h" + + +typedef struct _ExynosRegisterComponentType +{ + OMX_U8 componentName[MAX_OMX_COMPONENT_NAME_SIZE]; + OMX_U8 roles[MAX_OMX_COMPONENT_ROLE_NUM][MAX_OMX_COMPONENT_ROLE_SIZE]; + OMX_U32 totalRoleNum; +} ExynosRegisterComponentType; + +typedef struct _EXYNOS_OMX_COMPONENT_REGLIST +{ + ExynosRegisterComponentType component; + OMX_U8 libName[MAX_OMX_COMPONENT_LIBNAME_SIZE]; +} EXYNOS_OMX_COMPONENT_REGLIST; + +struct EXYNOS_OMX_COMPONENT; +typedef struct _EXYNOS_OMX_COMPONENT +{ + OMX_U8 componentName[MAX_OMX_COMPONENT_NAME_SIZE]; + OMX_U8 libName[MAX_OMX_COMPONENT_LIBNAME_SIZE]; + OMX_HANDLETYPE libHandle; + OMX_COMPONENTTYPE *pOMXComponent; + struct _EXYNOS_OMX_COMPONENT *nextOMXComp; +} EXYNOS_OMX_COMPONENT; + + +#ifdef __cplusplus +extern "C" { +#endif + + +OMX_ERRORTYPE Exynos_OMX_Component_Register(EXYNOS_OMX_COMPONENT_REGLIST **compList, OMX_U32 *compNum); +OMX_ERRORTYPE Exynos_OMX_Component_Unregister(EXYNOS_OMX_COMPONENT_REGLIST *componentList); +OMX_ERRORTYPE Exynos_OMX_ComponentLoad(EXYNOS_OMX_COMPONENT *exynos_component); +OMX_ERRORTYPE Exynos_OMX_ComponentUnload(EXYNOS_OMX_COMPONENT *exynos_component); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/core/Exynos_OMX_Core.c b/openmax/core/Exynos_OMX_Core.c new file mode 100644 index 0000000..77bc5e7 --- /dev/null +++ b/openmax/core/Exynos_OMX_Core.c @@ -0,0 +1,488 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Core.c + * @brief Exynos OpenMAX IL Core + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * HyeYeon Chung (hyeon.chung@samsung.com) + * Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OMX_Core.h" +#include "Exynos_OMX_Component_Register.h" +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OMX_Resourcemanager.h" +#include "Exynos_OSAL_Event.h" +#include "Exynos_OMX_Basecomponent.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_OMX_CORE" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +static int gInitialized = 0; +static OMX_U32 gComponentNum = 0; + +static EXYNOS_OMX_COMPONENT_REGLIST *gComponentList = NULL; +static EXYNOS_OMX_COMPONENT *gLoadComponentList = NULL; +static OMX_HANDLETYPE ghLoadComponentListMutex = NULL; + +static int gRefCount = 0; +static pthread_mutex_t gMutex; + + +OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_Init(void) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + pthread_mutex_lock(&gMutex); + + if (gInitialized == 0) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] core is not initialized", __FUNCTION__); + if (Exynos_OMX_Component_Register(&gComponentList, &gComponentNum)) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OMX_Component_Register()", __FUNCTION__); + goto EXIT; + } + + ret = Exynos_OMX_ResourceManager_Init(); + if (OMX_ErrorNone != ret) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OMX_ResourceManager_Init()", __FUNCTION__); + goto EXIT; + } + + ret = Exynos_OSAL_MutexCreate(&ghLoadComponentListMutex); + if (OMX_ErrorNone != ret) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_MutexCreate()", __FUNCTION__); + goto EXIT; + } + + gInitialized = 1; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] core is initialized", __FUNCTION__); + } + + gRefCount++; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] current refCount(%d)", __FUNCTION__, gRefCount); + +EXIT: + pthread_mutex_unlock(&gMutex); + + FunctionOut(); + + return ret; +} + +OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_Deinit(void) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + pthread_mutex_lock(&gMutex); + + + gRefCount--; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] current refCount(%d)", __FUNCTION__, gRefCount); + + if (gRefCount > 0) + goto EXIT; + + Exynos_OSAL_MutexTerminate(ghLoadComponentListMutex); + ghLoadComponentListMutex = NULL; + + Exynos_OMX_ResourceManager_Deinit(); + + if (OMX_ErrorNone != Exynos_OMX_Component_Unregister(gComponentList)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OMX_Component_Unregister()", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + gComponentList = NULL; + gComponentNum = 0; + gInitialized = 0; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] core is deinitialized", __FUNCTION__); + +EXIT: + + pthread_mutex_unlock(&gMutex); + FunctionOut(); + + return ret; +} + +OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_ComponentNameEnum( + OMX_OUT OMX_STRING cComponentName, + OMX_IN OMX_U32 nNameLength, + OMX_IN OMX_U32 nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if (nIndex >= gComponentNum) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + snprintf(cComponentName, nNameLength, "%s", gComponentList[nIndex].component.componentName); + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_GetHandle( + OMX_OUT OMX_HANDLETYPE *pHandle, + OMX_IN OMX_STRING cComponentName, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_CALLBACKTYPE *pCallBacks) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_COMPONENT *loadComponent; + EXYNOS_OMX_COMPONENT *currentComponent; + unsigned int i = 0; + + FunctionIn(); + + if (gInitialized != 1) { + ret = OMX_ErrorNotReady; + goto EXIT; + } + + if ((pHandle == NULL) || (cComponentName == NULL) || (pCallBacks == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] ComponentName : %s", __FUNCTION__, cComponentName); + + for (i = 0; i < gComponentNum; i++) { + if (Exynos_OSAL_Strcmp(cComponentName, gComponentList[i].component.componentName) == 0) { + loadComponent = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_COMPONENT)); + if (loadComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Memset(loadComponent, 0, sizeof(EXYNOS_OMX_COMPONENT)); + + Exynos_OSAL_Strcpy(loadComponent->libName, gComponentList[i].libName); + Exynos_OSAL_Strcpy(loadComponent->componentName, gComponentList[i].component.componentName); + ret = Exynos_OMX_ComponentLoad(loadComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Free(loadComponent); + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OMX_ComponentLoad()", __FUNCTION__); + goto EXIT; + } + + ret = loadComponent->pOMXComponent->SetCallbacks(loadComponent->pOMXComponent, pCallBacks, pAppData); + if (ret != OMX_ErrorNone) { + Exynos_OMX_ComponentUnload(loadComponent); + Exynos_OSAL_Free(loadComponent); + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to SetCallbacks()", __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_MutexLock(ghLoadComponentListMutex); + ret = Exynos_OMX_Get_Resource(loadComponent->pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OMX_ComponentUnload(loadComponent); + Exynos_OSAL_Free(loadComponent); + Exynos_OSAL_MutexUnlock(ghLoadComponentListMutex); + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OMX_Get_Resource()", __FUNCTION__); + goto EXIT; + } + + if (gLoadComponentList == NULL) { + gLoadComponentList = loadComponent; + } else { + currentComponent = gLoadComponentList; + while (currentComponent->nextOMXComp != NULL) { + currentComponent = currentComponent->nextOMXComp; + } + currentComponent->nextOMXComp = loadComponent; + } + Exynos_OSAL_MutexUnlock(ghLoadComponentListMutex); + + *pHandle = loadComponent->pOMXComponent; + ret = OMX_ErrorNone; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] %s is created", __FUNCTION__, cComponentName); + goto EXIT; + } + } + + ret = OMX_ErrorComponentNotFound; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_COMPONENT *currentComponent = NULL; + EXYNOS_OMX_COMPONENT *deleteComponent = NULL; + + FunctionIn(); + + if ((gInitialized != 1) || + (gLoadComponentList == NULL)) { + ret = OMX_ErrorNotReady; + goto EXIT; + } + + if (!hComponent) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_MutexLock(ghLoadComponentListMutex); + Exynos_OMX_Release_Resource(hComponent); + + if (gLoadComponentList->pOMXComponent == hComponent) { + deleteComponent = gLoadComponentList; + gLoadComponentList = gLoadComponentList->nextOMXComp; + } else { + currentComponent = gLoadComponentList; + + while ((currentComponent != NULL) && + (currentComponent->nextOMXComp != NULL)) { + if (currentComponent->nextOMXComp->pOMXComponent == hComponent) { + deleteComponent = currentComponent->nextOMXComp; + currentComponent->nextOMXComp = deleteComponent->nextOMXComp; + break; + } + currentComponent = currentComponent->nextOMXComp; + } + + if (deleteComponent == NULL) { + ret = OMX_ErrorComponentNotFound; + Exynos_OSAL_MutexUnlock(ghLoadComponentListMutex); + goto EXIT; + } + } + Exynos_OSAL_MutexUnlock(ghLoadComponentListMutex); + + Exynos_OMX_ComponentUnload(deleteComponent); + Exynos_OSAL_Free(deleteComponent); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_SetupTunnel( + OMX_IN OMX_HANDLETYPE hOutput, + OMX_IN OMX_U32 nPortOutput, + OMX_IN OMX_HANDLETYPE hInput, + OMX_IN OMX_U32 nPortInput) +{ + OMX_ERRORTYPE ret = OMX_ErrorNotImplemented; + + OMX_PTR srcComponent = hOutput; + OMX_U32 srcPort = nPortOutput; + + OMX_PTR dstComponent = hInput; + OMX_U32 dstPort = nPortInput; + +EXIT: + return ret; +} + +OMX_API OMX_ERRORTYPE Exynos_OMX_GetContentPipe( + OMX_OUT OMX_HANDLETYPE *hPipe, + OMX_IN OMX_STRING szURI) +{ + OMX_ERRORTYPE ret = OMX_ErrorNotImplemented; + + OMX_PTR pipe = hPipe; + OMX_STRING name = szURI; +EXIT: + return ret; +} + +OMX_API OMX_ERRORTYPE Exynos_OMX_GetComponentsOfRole( + OMX_IN OMX_STRING role, + OMX_INOUT OMX_U32 *pNumComps, + OMX_INOUT OMX_U8 **compNames) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + int max_role_num = 0; + int i = 0, j = 0; + + FunctionIn(); + + if (gInitialized != 1) { + ret = OMX_ErrorNotReady; + goto EXIT; + } + + *pNumComps = 0; + + for (i = 0; i < MAX_OMX_COMPONENT_NUM; i++) { + max_role_num = gComponentList[i].component.totalRoleNum; + + for (j = 0; j < max_role_num; j++) { + if (Exynos_OSAL_Strcmp(gComponentList[i].component.roles[j], role) == 0) { + if (compNames != NULL) { + Exynos_OSAL_Strcpy((OMX_STRING)compNames[*pNumComps], gComponentList[i].component.componentName); + } + *pNumComps = (*pNumComps + 1); + } + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_API OMX_ERRORTYPE Exynos_OMX_GetRolesOfComponent ( + OMX_IN OMX_STRING compName, + OMX_INOUT OMX_U32 *pNumRoles, + OMX_OUT OMX_U8 **roles) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_BOOL detectComp = OMX_FALSE; + int compNum = 0, totalRoleNum = 0; + int i = 0; + + FunctionIn(); + + if (gInitialized != 1) { + ret = OMX_ErrorNotReady; + goto EXIT; + } + + for (i = 0; i < MAX_OMX_COMPONENT_NUM; i++) { + if (gComponentList != NULL) { + if (Exynos_OSAL_Strcmp(gComponentList[i].component.componentName, compName) == 0) { + *pNumRoles = totalRoleNum = gComponentList[i].component.totalRoleNum; + compNum = i; + detectComp = OMX_TRUE; + break; + } + } else { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + if (detectComp == OMX_FALSE) { + *pNumRoles = 0; + ret = OMX_ErrorComponentNotFound; + goto EXIT; + } + + if (roles != NULL) { + for (i = 0; i < totalRoleNum; i++) { + Exynos_OSAL_Strcpy(roles[i], gComponentList[compNum].component.roles[i]); + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void) +{ + return Exynos_OMX_Init(); +} + +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void) +{ + return Exynos_OMX_Deinit(); +} + +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum( + OMX_OUT OMX_STRING cComponentName, + OMX_IN OMX_U32 nNameLength, + OMX_IN OMX_U32 nIndex) +{ + return Exynos_OMX_ComponentNameEnum(cComponentName, nNameLength, nIndex); +} + +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle( + OMX_OUT OMX_HANDLETYPE *pHandle, + OMX_IN OMX_STRING cComponentName, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_CALLBACKTYPE *pCallBacks) +{ + return Exynos_OMX_GetHandle(pHandle, cComponentName, pAppData, pCallBacks); +} + +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( + OMX_IN OMX_HANDLETYPE hComponent) +{ + return Exynos_OMX_FreeHandle(hComponent); +} + +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel( + OMX_IN OMX_HANDLETYPE hOutput, + OMX_IN OMX_U32 nPortOutput, + OMX_IN OMX_HANDLETYPE hInput, + OMX_IN OMX_U32 nPortInput) +{ + return Exynos_OMX_SetupTunnel(hOutput, nPortOutput, hInput, nPortInput); +} + +OMX_API OMX_ERRORTYPE OMX_GetContentPipe( + OMX_OUT OMX_HANDLETYPE *hPipe, + OMX_IN OMX_STRING szURI) +{ + return Exynos_OMX_GetContentPipe(hPipe, szURI); +} + +OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole( + OMX_IN OMX_STRING role, + OMX_INOUT OMX_U32 *pNumComps, + OMX_INOUT OMX_U8 **compNames) +{ + return Exynos_OMX_GetComponentsOfRole(role, pNumComps, compNames); +} + +OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent( + OMX_IN OMX_STRING compName, + OMX_INOUT OMX_U32 *pNumRoles, + OMX_OUT OMX_U8 **roles) +{ + return Exynos_OMX_GetRolesOfComponent(compName, pNumRoles, roles); +} diff --git a/openmax/core/Exynos_OMX_Core.h b/openmax/core/Exynos_OMX_Core.h new file mode 100644 index 0000000..4ccebf4 --- /dev/null +++ b/openmax/core/Exynos_OMX_Core.h @@ -0,0 +1,77 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Core.h + * @brief Exynos OpenMAX IL Core + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * HyeYeon Chung (hyeon.chung@samsung.com) + * Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_CORE +#define EXYNOS_OMX_CORE + +#include "Exynos_OMX_Def.h" +#include "OMX_Types.h" +#include "OMX_Core.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +EXYNOS_EXPORT_REF OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_Init(void); +EXYNOS_EXPORT_REF OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_Deinit(void); +EXYNOS_EXPORT_REF OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_ComponentNameEnum( + OMX_OUT OMX_STRING cComponentName, + OMX_IN OMX_U32 nNameLength, + OMX_IN OMX_U32 nIndex); +EXYNOS_EXPORT_REF OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_GetHandle( + OMX_OUT OMX_HANDLETYPE *pHandle, + OMX_IN OMX_STRING cComponentName, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_CALLBACKTYPE *pCallBacks); +EXYNOS_EXPORT_REF OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_FreeHandle( + OMX_IN OMX_HANDLETYPE hComponent); +EXYNOS_EXPORT_REF OMX_API OMX_ERRORTYPE OMX_APIENTRY Exynos_OMX_SetupTunnel( + OMX_IN OMX_HANDLETYPE hOutput, + OMX_IN OMX_U32 nPortOutput, + OMX_IN OMX_HANDLETYPE hInput, + OMX_IN OMX_U32 nPortInput); +EXYNOS_EXPORT_REF OMX_API OMX_ERRORTYPE Exynos_OMX_GetContentPipe( + OMX_OUT OMX_HANDLETYPE *hPipe, + OMX_IN OMX_STRING szURI); +EXYNOS_EXPORT_REF OMX_API OMX_ERRORTYPE Exynos_OMX_GetComponentsOfRole( + OMX_IN OMX_STRING role, + OMX_INOUT OMX_U32 *pNumComps, + OMX_INOUT OMX_U8 **compNames); +EXYNOS_EXPORT_REF OMX_API OMX_ERRORTYPE Exynos_OMX_GetRolesOfComponent( + OMX_IN OMX_STRING compName, + OMX_INOUT OMX_U32 *pNumRoles, + OMX_OUT OMX_U8 **roles); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/openmax/core/NOTICE b/openmax/core/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/core/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/openmax/include/exynos/Exynos_OMX_Def.h b/openmax/include/exynos/Exynos_OMX_Def.h new file mode 100644 index 0000000..2c2913f --- /dev/null +++ b/openmax/include/exynos/Exynos_OMX_Def.h @@ -0,0 +1,1298 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Def.h + * @brief Exynos_OMX specific define + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_DEF +#define EXYNOS_OMX_DEF + +//#define PERFORMANCE_DEBUG + +#include "OMX_Types.h" +#include "OMX_IVCommon.h" +#include "OMX_Video.h" +#include "OMX_VideoExt.h" +#include "OMX_IndexExt.h" +#include "OMX_Component.h" + +#define VERSIONMAJOR_NUMBER 1 +#define VERSIONMINOR_NUMBER 1 +#define REVISION_NUMBER 2 +#define STEP_NUMBER 0 + +#ifdef MAX_COMPONENT_NUM +#define RESOURCE_VIDEO_DEC MAX_COMPONENT_NUM +#define RESOURCE_VIDEO_ENC MAX_COMPONENT_NUM +#else +#define RESOURCE_VIDEO_DEC 16 +#define RESOURCE_VIDEO_ENC 16 +#endif +#define RESOURCE_AUDIO_DEC 10 + +#define MAX_OMX_COMPONENT_NUM 40 +#define MAX_OMX_COMPONENT_ROLE_NUM 10 +#define MAX_OMX_COMPONENT_NAME_SIZE OMX_MAX_STRINGNAME_SIZE +#define MAX_OMX_COMPONENT_ROLE_SIZE OMX_MAX_STRINGNAME_SIZE +#define MAX_OMX_COMPONENT_LIBNAME_SIZE OMX_MAX_STRINGNAME_SIZE * 2 +#define MAX_OMX_MIMETYPE_SIZE OMX_MAX_STRINGNAME_SIZE + +#define MAX_BUFFER_REF 40 +#define MAX_TIMESTAMP MAX_BUFFER_REF +#define MAX_FLAGS MAX_BUFFER_REF + +#define MAX_BUFFER_PLANE 3 + +#define INDEX_AFTER_EOS 0xE05 +#define INDEX_AFTER_DRC 0xD5C +#define INDEX_HEADER_DATA 0xC5D + +#define DEFAULT_TIMESTAMP_VAL (-1010101010) +#define RESET_TIMESTAMP_VAL (-1001001001) + +// The largest metadata buffer size advertised +// when metadata buffer mode is used +#define MAX_METADATA_BUFFER_SIZE (64) + +#define MAX_VENDOR_EXT_NUM (32) + +#define PREFIX_COMPONENT_NAME "OMX.Exynos." +#define IS_CUSTOM_COMPONENT(name) (((char)(name[((int)sizeof(PREFIX_COMPONENT_NAME))-1]) >= 0x61)? OMX_TRUE:OMX_FALSE) + +#define IS_64BIT_OS (((sizeof(int) != sizeof(void *))? OMX_TRUE:OMX_FALSE)) + +/* for image converter(MSRND) */ +#define OMX_BUFFERFLAG_CONVERTEDIMAGE 0x00000100 + +typedef enum _EXYNOS_CODEC_TYPE +{ + SW_CODEC, + HW_VIDEO_DEC_CODEC, + HW_VIDEO_ENC_CODEC, + HW_VIDEO_DEC_SECURE_CODEC, + HW_VIDEO_ENC_SECURE_CODEC, + HW_AUDIO_DEC_CODEC, + HW_AUDIO_ENC_CODEC +} EXYNOS_CODEC_TYPE; + +#define PLANE_MAX_NUM 3 +typedef enum _PLANE_TYPE { + PLANE_MULTIPLE = 0x00, + PLANE_SINGLE = 0x11, + PLANE_SINGLE_USER = 0x12, +} PLANE_TYPE; + +typedef enum _EXYNOS_OMX_INDEXTYPE +{ +#define EXYNOS_INDEX_CONFIG_VIDEO_INTRAPERIOD "OMX.SEC.index.VideoIntraPeriod" + OMX_IndexConfigVideoIntraPeriod = 0x7F000002, +#ifdef USE_S3D_SUPPORT +#define EXYNOS_INDEX_PARAM_GET_S3D "OMX.SEC.index.S3DMode" + OMX_IndexVendorS3DMode = 0x7F000003, +#endif +#define EXYNOS_INDEX_PARAM_NEED_CONTIG_MEMORY "OMX.SEC.index.NeedContigMemory" /* for HDCP */ + OMX_IndexVendorNeedContigMemory = 0x7F000004, +#define EXYNOS_INDEX_CONFIG_GET_BUFFER_FD "OMX.SEC.index.GetBufferFD" /* for HDCP */ + OMX_IndexVendorGetBufferFD = 0x7F000005, +#define EXYNOS_INDEX_PARAM_SET_DTS_MODE "OMX.SEC.index.SetDTSMode" /* for decoding DTS contents */ + OMX_IndexVendorSetDTSMode = 0x7F000006, +#define EXYNOS_INDEX_PARAM_ENABLE_THUMBNAIL "OMX.SEC.index.enableThumbnailMode" + OMX_IndexParamEnableThumbnailMode = 0x7F000007, +#define EXYNOS_INDEX_PARAM_VIDEO_QPRANGE_TYPE "OMX.SEC.indexParam.VideoQPRange" + OMX_IndexParamVideoQPRange = 0x7F000008, +#define EXYNOS_INDEX_CONFIG_VIDEO_QPRANGE_TYPE "OMX.SEC.indexConfig.VideoQPRange" + OMX_IndexConfigVideoQPRange = 0x7F000009, +#define EXYNOS_INDEX_CONFIG_VIDEO_TEMPORALSVC "OMX.SEC.index.TemporalSVC" + OMX_IndexConfigVideoTemporalSVC = 0x7F000010, +#define EXYNOS_INDEX_PARAM_VIDEO_AVC_ENABLE_TEMPORALSVC "OMX.SEC.index.AVC.enableTemporalSVC" + OMX_IndexParamVideoAVCEnableTemporalSVC = 0x7F000011, +#define EXYNOS_INDEX_PARAM_ENABLE_BLUR_FILTER "OMX.SEC.indexParam.enableBlurFilter" + OMX_IndexParamEnableBlurFilter = 0x7F000014, +#define EXYNOS_INDEX_CONFIG_BLUR_INFO "OMX.SEC.indexConfig.BlurInfo" + OMX_IndexConfigBlurInfo = 0x7F000015, +#define EXYNOS_INDEX_PARAM_VIDEO_HEVC_ENABLE_TEMPORALSVC "OMX.SEC.index.Hevc.enableTemporalSVC" + OMX_IndexParamVideoHevcEnableTemporalSVC = 0x7F000016, +#define EXYNOS_INDEX_CONFIG_VIDEO_ROIINFO "OMX.SEC.index.RoiInfo" + OMX_IndexConfigVideoRoiInfo = 0x7F000017, +#define EXYNOS_INDEX_PARAM_VIDEO_ENABLE_ROIINFO "OMX.SEC.index.enableRoiInfo" + OMX_IndexParamVideoEnableRoiInfo = 0x7F000018, +#define EXYNOS_INDEX_PARAM_ROATION_INFO "OMX.SEC.indexParam.RotationInfo" + OMX_IndexParamRotationInfo = 0x7F000019, +#define EXYNOS_INDEX_PARAM_ENABLE_PVC "OMX.SEC.indexParam.enablePVC" + OMX_IndexParamVideoEnablePVC = 0x7F000020, +#define EXYNOS_INDEX_CONFIG_BLACK_BAR_CROP_INFO "OMX.SEC.index.BlackBarCrop" + OMX_IndexConfigBlackBarCrop = 0x7F000021, +#define EXYNOS_INDEX_CONFIG_SEARCH_BLACK_BAR "OMX.SEC.index.SearchBlackBar" + OMX_IndexConfigSearchBlackBar = 0x7F000022, +#define EXYNOS_CUSTOM_INDEX_PARAM_REORDER_MODE "OMX.SEC.CUSTOM.index.ReorderMode" + OMX_IndexExynosParamReorderMode = 0x7F000023, +#define EXYNOS_INDEX_CONFIG_IFRAME_RATIO "OMX.SEC.index.IFrameRatio" + OMX_IndexConfigIFrameRatio = 0x7F000024, +#define EXYNOS_INDEX_PARAM_REF_NUM_PFRAMES "OMX.SEC.index.NumberRefPframes" + OMX_IndexParamNumberRefPframes = 0x7F000025, +#define EXYNOS_INDEX_PARAM_VIDEO_ENABLE_GPB "OMX.SEC.index.enableGPB" + OMX_IndexParamVideoEnableGPB = 0x7F000026, +#define EXYNOS_INDEX_PARAM_VIDEO_DROP_CONTROL "OMX.SEC.index.enableDropControl" + OMX_IndexParamVideoDropControl = 0x7F000027, +#define EXYNOS_INDEX_PARAM_VIDEO_COMP_COLOR_FORMAT "OMX.SEC.index.setCompressedColorFormat" + OMX_IndexParamVideoCompressedColorFormat = 0x7F000028, +#define EXYNOS_INDEX_PARAM_VIDEO_DISABLE_DFR "OMX.SEC.index.disableDFR" + OMX_IndexParamVideoDisableDFR = 0x7F000029, +#define EXYNOS_INDEX_PARAM_VIDEO_CHROMA_QP "OMX.SEC.index.chromaQP" + OMX_IndexParamVideoChromaQP = 0x7F000030, +#define EXYNOS_INDEX_PARAM_VIDEO_DISABLE_HBENCODING "OMX.SEC.index.disableHBEncoding" + OMX_IndexParamVideoDisableHBEncoding = 0x7F000031, + +//////////////////////////////////////////////////////////////////////////////////////////////// +// for extension codec spec +//////////////////////////////////////////////////////////////////////////////////////////////// + OMX_IndexExtensionStartUnused = 0x7F020000, +#ifdef USE_KHRONOS_OMX_HEADER +#define EXYNOS_INDEX_PARAM_VIDEO_HEVC_TYPE "OMX.SEC.index.VideoHevcType" + OMX_IndexParamVideoHevc = 0x7F020000, +#define EXYNOS_INDEX_PARAM_VIDEO_VP9_TYPE "OMX.SEC.index.VideoVp9Type" + OMX_IndexParamVideoVp9 = 0x7F020001, +#endif +#ifndef USE_KHRONOS_OMX_1_2 +#define EXYNOS_INDEX_PARAM_VIDEO_VC1_TYPE "OMX.SEC.index.VideoVc1Type" + OMX_IndexParamVideoVC1 = 0x7F021000, +#endif + + +//////////////////////////////////////////////////////////////////////////////////////////////// +// for android platform +//////////////////////////////////////////////////////////////////////////////////////////////// + OMX_IndexAndroidStartUnused = 0x7F030000, + /* query using get_extension_index */ +#define EXYNOS_INDEX_PARAM_USE_ANB "OMX.google.android.index.useAndroidNativeBuffer" /* no more used */ + OMX_IndexParamUseAndroidNativeBuffer = 0x7F030001, +#define EXYNOS_INDEX_PARAM_USE_ANB2 "OMX.google.android.index.useAndroidNativeBuffer2" /* no more used */ + OMX_IndexParamUseAndroidNativeBuffer2 = 0x7F030002, +#define EXYNOS_INDEX_PARAM_GET_ANB "OMX.google.android.index.getAndroidNativeBufferUsage" + OMX_IndexParamGetAndroidNativeBuffer = 0x7F030003, +#define EXYNOS_INDEX_PARAM_ENABLE_ANB "OMX.google.android.index.enableAndroidNativeBuffers" + OMX_IndexParamEnableAndroidBuffers = 0x7F030004, +#define EXYNOS_INDEX_PARAM_STORE_METADATA_BUFFER "OMX.google.android.index.storeMetaDataInBuffers" + OMX_IndexParamStoreMetaDataBuffer = 0x7F030005, +#define EXYNOS_INDEX_PARAM_PREPEND_SPSPPS_TO_IDR "OMX.google.android.index.prependSPSPPSToIDRFrames" + OMX_IndexParamPrependSPSPPSToIDR = 0x7F030006, +#define EXYNOS_INDEX_PARAM_ALLOCATE_NATIVE_HANDLE "OMX.google.android.index.allocateNativeHandle" + OMX_IndexParamAllocateNativeHandle = 0x7F030007, +#define EXYNOS_INDEX_PARAM_DESCRIBE_COLOR_FORMAT "OMX.google.android.index.describeColorFormat" + OMX_IndexParamDescribeColorFormat = 0x7F030008, +#define EXYNOS_INDEX_CONFIG_VIDEO_HDR_STATIC_INFO "OMX.google.android.index.describeHDRStaticInfo" + OMX_IndexConfigVideoHdrStaticInfo = 0x7F030009, +#define EXYNOS_INDEX_CONFIG_VIDEO_COLOR_ASPECTS_INFO "OMX.google.android.index.describeColorAspects" + OMX_IndexConfigVideoColorAspects = 0x7F030010, +#define EXYNOS_INDEX_CONFIG_VIDEO_HDR10_PLUS_INFO "OMX.google.android.index.describeHDR10PlusInfo" + OMX_IndexConfigVideoHdr10PlusInfo = 0x7F030011, +#define EXYNOS_INDEX_PARAM_SET_ANB_CONSUMER_USAGE "OMX.google.android.index.AndroidNativeBufferConsumerUsage" + OMX_IndexParamAndroidNatvieBufferConsumerUsage = 0x7F030012, + +#ifdef USE_KHRONOS_OMX_HEADER + /* not query, just uses index */ +#define EXYNOS_INDEX_CONFIG_ANDROID_VENDOR_EXT "OMX.google.android.index.androidVendorExtension" + OMX_IndexConfigAndroidVendorExtension = 0x7F031001, + + +#define EXYNOS_INDEX_PARAM_VIDEO_ANDROID_VP8_ENCODER "OMX.SEC.index.VideoAndroidVP8Encoder" + OMX_IndexParamVideoAndroidVp8Encoder = 0x7F032001, +#define EXYNOS_INDEX_PARAM_SLICE_SEGMENTS "OMX.SEC.index.SliceSegments" /* not supported yet */ + OMX_IndexParamSliceSegments = 0x7F032002, +#define EXYNOS_INDEX_CONFIG_ANDROID_INTRA_REFRESH "OMX.SEC.index.AndroidIntraRefresh" /* not supported yet */ + OMX_IndexConfigAndroidIntraRefresh = 0x7F032003, +#define EXYNOS_INDEX_PARAM_ANDROID_VIDEO_TEMPORAL "OMX.SEC.index.param.TemporalLayering" + OMX_IndexParamAndroidVideoTemporalLayering = 0x7F032004, +#define EXYNOS_INDEX_CONFIG_ANDROID_VIDEO_TEMPORAL "OMX.SEC.index.config.TemporalLayering" + OMX_IndexConfigAndroidVideoTemporalLayering = 0x7F032005, +#define EXYNOS_INDEX_PARAM_MAX_FRAME_DURATION "OMX.SEC.index.maxDurationForBitratecontrol" /* not supported yet */ + OMX_IndexParamMaxFrameDurationForBitrateControl = 0x7F032006, +#define EXYNOS_INDEX_PARAM_VIDEO_ANDROID_VP9_ENCODER "OMX.SEC.index.VideoAndroidVp9Encoder" /* not supported yet */ + OMX_IndexParamVideoAndroidVp9Encoder = 0x7F032007, + + +#define EXYNOS_INDEX_CONFIG_OPERATING_RATE "OMX.SEC.index.OperatingRate" + OMX_IndexConfigOperatingRate = 0x7F033001, +#define EXYNOS_INDEX_PARAM_CONSUMER_USAGE_BITS "OMX.SEC.index.ConsumerUsageBits" + OMX_IndexParamConsumerUsageBits = 0x7F033002, +#define EXYNOS_INDEX_CONFIG_PRIORTIY "OMX.SEC.index.Priority" + OMX_IndexConfigPriority = 0x7F033003, +#endif // USE_KHRONOS_OMX_HEADER + + +//////////////////////////////////////////////////////////////////////////////////////////////// +// for linux platform +//////////////////////////////////////////////////////////////////////////////////////////////// + OMX_IndexLinuxStartUnused = 0x7F040000, +#define EXYNOS_CUSTOM_INDEX_PARAM_IMAGE_CROP "OMX.SEC.CUSTOM.index.ImageCrop" + OMX_IndexExynosParamImageCrop = 0x7F040002, +//////////////////////////////////////////////////////////////////////////////////////////////// +// for custom component +//////////////////////////////////////////////////////////////////////////////////////////////// + OMX_IndexCustomStartUnused = 0x7F050000, +#define EXYNOS_CUSTOM_INDEX_CONFIG_PTS_MODE "OMX.SEC.CUSTOM.index.PTSMode" + OMX_IndexExynosConfigPTSMode = 0x7F050001, +#define EXYNOS_CUSTOM_INDEX_CONFIG_DISPLAY_DELAY "OMX.SEC.CUSTOM.index.DisplayDelay" + OMX_IndexExynosConfigDisplayDelay = 0x7F050002, +#define EXYNOS_CUSTOM_INDEX_PARAM_CORRUPTEDHEADER "OMX.SEC.CUSTOM.index.CorruptedHeader" + OMX_IndexExynosParamCorruptedHeader = 0x7F050003, +#define EXYNOS_CUSTOM_INDEX_PARAM_DISPLAY_DELAY "OMX.SEC.CUSTOM.index.DisplayDelay2" /* Compatibility with OMX.SEC.CUSTOM.index.DisplayDelay */ + OMX_IndexExynosParamDisplayDelay = 0x7F050004, +#define EXYNOS_CUSTOM_INDEX_PARAM_USE_BUFFERCOPY "OMX.SEC.CUSTOM.index.BufferCopy" + OMX_IndexExynosParamBufferCopy = 0x7F050005, +#define EXYNOS_CUSTOM_INDEX_PARAM_USE_IMG_CONV "OMX.SEC.CUSTOM.index.ImageConvert" + OMX_IndexExynosParamImageConvert = 0x7F050006, +#define EXYNOS_CUSTOM_INDEX_PARAM_USE_IMG_CONV_MODE "OMX.SEC.CUSTOM.index.ImageConvertMode" + OMX_IndexExynosParamImageConvertMode = 0x7F050007, + + +//////////////////////////////////////////////////////////////////////////////////////////////// +// for Skype HD +//////////////////////////////////////////////////////////////////////////////////////////////// + OMX_IndexSkypeStartUnused = 0x7F060000, +#define OMX_MS_SKYPE_PARAM_DRIVERVER "OMX.microsoft.skype.index.driverversion" + OMX_IndexSkypeParamDriverVersion = 0x7F060001, +#if 0 +#define OMX_MS_SKYPE_PARAM_DECODERSETTING "OMX.microsoft.skype.index.decodersetting" + OMX_IndexSkypeParamDecoderSetting = 0x7F060002, +#define OMX_MS_SKYPE_PARAM_DECODERCAP "OMX.microsoft.skype.index.decodercapability" + OMX_IndexSkypeParamDecoderCapability = 0x7F060003, +#define OMX_MS_SKYPE_PARAM_ENCODERSETTING "OMX.microsoft.skype.index.encodersetting" + OMX_IndexSkypeParamEncoderSetting = 0x7F060004, +#define OMX_MS_SKYPE_PARAM_ENCODERCAP "OMX.microsoft.skype.index.encodercapability" + OMX_IndexSkypeParamEncoderCapability = 0x7F060005, +#endif +#define OMX_MS_SKYPE_CONFIG_MARKLTRFRAME "OMX.microsoft.skype.index.markltrframe" + OMX_IndexSkypeConfigMarkLTRFrame = 0x7F060006, +#define OMX_MS_SKYPE_CONFIG_USELTRFRAME "OMX.microsoft.skype.index.useltrframe" + OMX_IndexSkypeConfigUseLTRFrame = 0x7F060007, +#define OMX_MS_SKYPE_CONFIG_QP "OMX.microsoft.skype.index.qp" + OMX_IndexSkypeConfigQP = 0x7F060008, +#if 0 +#define OMX_MS_SKYPE_CONFIG_TEMPORALLAYERCOUNT "OMX.microsoft.skype.index.temporallayercount" + OMX_IndexSkypeConfigTemporalLayerCount = 0x7F060009, +#endif +#define OMX_MS_SKYPE_CONFIG_BASELAYERPID "OMX.microsoft.skype.index.basepid" + OMX_IndexSkypeConfigBasePid = 0x7F06000a, + + /* common */ + OMX_IndexSkypeParamLowLatency = 0x7F060010, + + /* encoder */ + OMX_IndexSkypeParamEncoderMaxTemporalLayerCount = 0x7F061000, + OMX_IndexSkypeParamEncoderMaxLTR = 0x7F061001, + OMX_IndexSkypeParamEncoderLTR = 0x7F061002, + OMX_IndexSkypeParamEncoderPreprocess = 0x7F061003, + OMX_IndexSkypeParamEncoderSar = 0x7F061004, + OMX_IndexSkypeParamEncoderInputControl = 0x7F061005, + OMX_IndexSkypeConfigEncoderLTR = 0x7F061006, + OMX_IndexSkypeConfigEncoderInputTrigger = 0x7F061007, + OMX_IndexSkypeParamVideoBitrate = 0x7F061008, + + OMX_IndexExynosEndUnused = 0x7F05FFFF, +} EXYNOS_OMX_INDEXTYPE; + +typedef enum _EXYNOS_OMX_ERRORTYPE +{ + OMX_ErrorNoEOF = (OMX_S32) 0x90000001, + OMX_ErrorInputDataDecodeYet = (OMX_S32) 0x90000002, + OMX_ErrorInputDataEncodeYet = (OMX_S32) 0x90000003, + OMX_ErrorCodecInit = (OMX_S32) 0x90000004, + OMX_ErrorCodecDecode = (OMX_S32) 0x90000005, + OMX_ErrorCodecEncode = (OMX_S32) 0x90000006, + OMX_ErrorCodecFlush = (OMX_S32) 0x90000007, + OMX_ErrorOutputBufferUseYet = (OMX_S32) 0x90000008, + OMX_ErrorCorruptedFrame = (OMX_S32) 0x90000009, + OMX_ErrorNeedNextHeaderInfo = (OMX_S32) 0x90000010, + OMX_ErrorNoneSrcSetupFinish = (OMX_S32) 0x90000011, + OMX_ErrorCorruptedHeader = (OMX_S32) OMX_ErrorStreamCorrupt, /* 0x90000012, */ + OMX_ErrorNoneExpiration = (OMX_S32) 0x90000013, + OMX_ErrorNoneReuseBuffer = (OMX_S32) 0x90000014, +} EXYNOS_OMX_ERRORTYPE; + +typedef enum _EXYNOS_OMX_COMMANDTYPE +{ + EXYNOS_OMX_CommandComponentDeInit = 0x7F000001, + EXYNOS_OMX_CommandEmptyBuffer, + EXYNOS_OMX_CommandFillBuffer, + EXYNOS_OMX_CommandFakeBuffer, + Exynos_OMX_CommandSendEvent, +} EXYNOS_OMX_COMMANDTYPE; + +typedef enum _EXYNOS_OMX_TRANS_STATETYPE { + EXYNOS_OMX_TransStateInvalid, + EXYNOS_OMX_TransStateLoadedToIdle, + EXYNOS_OMX_TransStateIdleToExecuting, + EXYNOS_OMX_TransStateExecutingToIdle, + EXYNOS_OMX_TransStateIdleToLoaded, + EXYNOS_OMX_TransStateMax = 0X7FFFFFFF +} EXYNOS_OMX_TRANS_STATETYPE; + +typedef enum _EXYNOS_OMX_PORT_STATETYPE { + EXYNOS_OMX_PortStateInvalid, + EXYNOS_OMX_PortStateFlushing, + EXYNOS_OMX_PortStateFlushingForDisable, + EXYNOS_OMX_PortStateDisabling, + EXYNOS_OMX_PortStateEnabling, + EXYNOS_OMX_PortStateIdle, + EXYNOS_OMX_PortStateLoaded, + EXYNOS_OMX_PortStateMax = 0X7FFFFFFF +} EXYNOS_OMX_PORT_STATETYPE; + +typedef enum _EXYNOS_OMX_COLOR_FORMATTYPE { + OMX_SEC_COLOR_FormatNV12TPhysicalAddress = 0x7F000001, /* unused */ + OMX_SEC_COLOR_FormatNV12LPhysicalAddress = 0x7F000002, /* unused */ + OMX_SEC_COLOR_FormatNV12LVirtualAddress = 0x7F000003, /* unused */ + + OMX_SEC_COLOR_FormatNV21LPhysicalAddress = 0x7F000010, /* unused */ + OMX_SEC_COLOR_FormatNV21Linear = 0x7F000011, + OMX_SEC_COLOR_FormatYVU420Planar = 0x7F000012, + OMX_SEC_COLOR_Format32bitABGR8888 = 0x7F000013, /* unused */ + OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace = 0x7F000014, /* unused */ + OMX_SEC_COLOR_Format10bitYUV420SemiPlanar = 0x7F000015, /* unused */ + OMX_SEC_COLOR_FormatS10bitYUV420SemiPlanar = 0x7F000016, /* S10B : Y/CbCr */ + OMX_SEC_COLOR_Format10bitYVU420SemiPlanar = 0x7F000017, /* unused */ + OMX_SEC_COLOR_FormatS10bitYVU420SemiPlanar = 0x7F000018, /* S10B : Y/CrCb */ + OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC = 0x7F000019, /* SBWC : Y/CbCr */ + OMX_SEC_COLOR_FormatYVU420SemiPlanarSBWC = 0x7F000020, /* SBWC : Y/CrCb */ + OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC = 0x7F000021, /* SBWC 10B : Y/CbCr */ + OMX_SEC_COLOR_Format10bitYVU420SemiPlanarSBWC = 0x7F000022, /* SBWC 10B : Y/CrCb */ + OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC_L50 = 0x7F000023, /* SBWC L50 : Y/CbCr */ + OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC_L75 = 0x7F000024, /* SBWC L75 : Y/CbCr */ + OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L40 = 0x7F000025, /* SBWC 10B L40 : Y/CbCr */ + OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L60 = 0x7F000026, /* SBWC 10B L60 : Y/CbCr */ + OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L80 = 0x7F000027, /* SBWC 10B L80 : Y/CbCr */ + + /* to copy a encoded data for drm component using gsc or fimc */ + OMX_SEC_COLOR_FormatEncodedData = OMX_COLOR_FormatYCbYCr, +#ifdef USE_KHRONOS_OMX_HEADER + OMX_COLOR_FormatAndroidOpaque = 0x7F000789, + OMX_COLOR_Format32BitRGBA8888 = 0x7F00A000, + OMX_SEC_COLOR_FormatNV12Tiled = 0x7FC00002, /* unused */ + OMX_COLOR_FormatYUV420Flexible = 0x7F420888, + + // 10-bit or 12-bit YUV format, LSB-justified (0's on higher bits) + OMX_COLOR_FormatYUV420Planar16 = 0x7F42016B, /* P010 */ +#endif +}EXYNOS_OMX_COLOR_FORMATTYPE; + +typedef enum _EXYNOS_OMX_SUPPORTFORMAT_TYPE +{ + supportFormat_0 = 0x00, + supportFormat_1, + supportFormat_2, + supportFormat_3, + supportFormat_4, + supportFormat_5, + supportFormat_6, + supportFormat_7, +} EXYNOS_OMX_SUPPORTFORMAT_TYPE; + +typedef enum _EXYNOS_OMX_BUFFERPROCESS_TYPE +{ + BUFFER_DEFAULT = 0x00, + BUFFER_COPY = 0x01, + BUFFER_SHARE = 0x02, + BUFFER_COPY_FORCE = 0x10, +} EXYNOS_OMX_BUFFERPROCESS_TYPE; + +#ifdef USE_S3D_SUPPORT +typedef enum _EXYNOS_OMX_FPARGMT_TYPE +{ + OMX_SEC_FPARGMT_INVALID = -1, + OMX_SEC_FPARGMT_CHECKERBRD_INTERL = 0x00, + OMX_SEC_FPARGMT_COLUMN_INTERL = 0x01, + OMX_SEC_FPARGMT_ROW_INTERL = 0x02, + OMX_SEC_FPARGMT_SIDE_BY_SIDE = 0x03, + OMX_SEC_FPARGMT_TOP_BOTTOM = 0x04, + OMX_SEC_FPARGMT_TEMPORAL_INTERL = 0x05, + OMX_SEC_FPARGMT_NONE = 0x0A +} EXYNOS_OMX_FPARGMT_TYPE; +#endif + +typedef enum _EXYNOS_OMX_EVENTTYPE +{ + OMX_EventVendorStart = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ +#ifdef USE_KHRONOS_OMX_HEADER + OMX_EventDataSpaceChanged, +#endif +#ifdef USE_S3D_SUPPORT + OMX_EventS3DInformation, +#endif +} EXYNOS_OMX_EVENTTYPE; + +typedef enum __EVENT_COMMAD_TYPE { + EVENT_CMD_STATE_TO_LOAD_STATE, + EVENT_CMD_STATE_TO_IDLE_STATE, + EVENT_CMD_ENABLE_INPUT_PORT, + EVENT_CMD_ENABLE_OUTPUT_PORT, + EVENT_CMD_DISABLE_INPUT_PORT, + EVENT_CMD_DISABLE_OUTPUT_PORT, +} EVENT_COMMAD_TYPE; + +typedef enum _EXYNOS_METADATA_TYPE { + METADATA_TYPE_DISABLED = 0x0000, /* 1. data buffer(ex: yuv, rgb) */ + METADATA_TYPE_DATA = 0x0001, /* 2. uses meta struct(type, [fd|handle|id]) */ + METADATA_TYPE_HANDLE = 0x0002, /* 3. naitve handle(fd) */ + + METADATA_TYPE_BUFFER_LOCK = 0x0100, /* need to lock to get va */ + METADATA_TYPE_BUFFER_ID = 0x1000, /* need to get fd from id */ + + METADATA_TYPE_GRAPHIC = (METADATA_TYPE_DATA | METADATA_TYPE_BUFFER_LOCK), /* 4. uses meta struct(type, handle) */ + METADATA_TYPE_GRAPHIC_HANDLE = (METADATA_TYPE_HANDLE | METADATA_TYPE_BUFFER_LOCK), /* 5. graphic buffer handle(fd) */ + METADATA_TYPE_UBM_BUFFER = (METADATA_TYPE_DATA | METADATA_TYPE_BUFFER_LOCK | METADATA_TYPE_BUFFER_ID), /* 6. uses meta struct(type, id) */ +} EXYNOS_METADATA_TYPE; + +typedef enum _EXYNOS_OMX_VIDEO_CONTROLRATETYPE { + OMX_Video_ControlRateVendorStart = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_Video_ControlRateConstantVTCall = 0x7F000001, +} EXYNOS_OMX_VIDEO_CONTROLRATETYPE; + +typedef struct _EXYNOS_OMX_PRIORITYMGMTTYPE +{ + OMX_U32 nGroupPriority; /* the value 0 represents the highest priority */ + /* for a group of components */ + OMX_U32 nGroupID; +} EXYNOS_OMX_PRIORITYMGMTTYPE; + +typedef struct _EXYNOS_OMX_VIDEO_PROFILELEVEL +{ + OMX_S32 profile; + OMX_S32 level; +} EXYNOS_OMX_VIDEO_PROFILELEVEL; + +typedef struct _EXYNOS_OMX_LOCK_RANGE +{ + OMX_U32 nWidth; + OMX_U32 nHeight; + OMX_COLOR_FORMATTYPE eColorFormat; +} EXYNOS_OMX_LOCK_RANGE; + +typedef struct _EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bNeedContigMem; +} EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE; + +typedef struct _EXYNOS_OMX_VIDEO_CONFIG_BUFFERINFO { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_PTR OMX_IN pVirAddr; + OMX_S32 OMX_OUT fd; +} EXYNOS_OMX_VIDEO_CONFIG_BUFFERINFO; + +typedef struct _EXYNOS_OMX_VIDEO_PARAM_DTSMODE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bDTSMode; +} EXYNOS_OMX_VIDEO_PARAM_DTSMODE; + +typedef struct _EXYNOS_OMX_VIDEO_THUMBNAILMODE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnable; +} EXYNOS_OMX_VIDEO_THUMBNAILMODE; + +typedef struct _OMX_VIDEO_QPRANGE { + OMX_U32 nMinQP; + OMX_U32 nMaxQP; +} OMX_VIDEO_QPRANGE; + +typedef struct _OMX_VIDEO_QPRANGETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_QPRANGE qpRangeI; + OMX_VIDEO_QPRANGE qpRangeP; + OMX_VIDEO_QPRANGE qpRangeB; /* H.264, HEVC, MPEG4 */ +} OMX_VIDEO_QPRANGETYPE; + +typedef struct __OMX_VIDEO_PARAM_CHROMA_QP_OFFSET { /* H.264, HEVC */ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nCr; + OMX_S32 nCb; +} OMX_VIDEO_PARAM_CHROMA_QP_OFFSET; + +/* Temporal SVC */ +/* Maximum number of temporal layers */ +#define OMX_VIDEO_MAX_TEMPORAL_LAYERS 7 +#define OMX_VIDEO_MAX_TEMPORAL_LAYERS_WITH_LTR 3 +#define OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS 7 +#define OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS_FOR_B (OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS - 1) +#define OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS 7 +#define OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS_FOR_B (OMX_VIDEO_MAX_HEVC_TEMPORAL_LAYERS - 1) + +typedef enum _EXYNOS_OMX_HIERARCHICAL_CODING_TYPE +{ + EXYNOS_OMX_Hierarchical_P = 0x00, + EXYNOS_OMX_Hierarchical_B, +} EXYNOS_OMX_HIERARCHICAL_CODING_TYPE; + +typedef struct _EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnableTemporalSVC; +} EXYNOS_OMX_VIDEO_PARAM_ENABLE_TEMPORALSVC; + +typedef struct _EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nKeyFrameInterval; + OMX_U32 nTemporalLayerCount; + OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_MAX_TEMPORAL_LAYERS]; + OMX_U32 nMinQuantizer; + OMX_U32 nMaxQuantizer; +} EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC; + +typedef enum _EXYNOS_OMX_BLUR_MODE +{ + BLUR_MODE_NONE = 0x00, + BLUR_MODE_DOWNUP = 0x01, + BLUR_MODE_COEFFICIENT = 0x02, +} EXYNOS_OMX_BLUR_MODE; + +typedef enum _EXYNOS_OMX_BLUR_RESOL +{ + BLUR_RESOL_240 = 426 * 240, /* 426 x 240 */ + BLUR_RESOL_480 = 854 * 480, /* 854 x 480 */ + BLUR_RESOL_720 = 1280 * 720, /* 1280 x 720 */ + BLUR_RESOL_960 = 1920 * 960, /* 1920 x 960 */ + BLUR_RESOL_1080 = 1920 * 1080, /* 1920 x 1080 */ +} EXYNOS_OMX_BLUR_RESOL; + +typedef struct _EXYNOS_OMX_VIDEO_PARAM_ENABLE_BLURFILTER { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bUseBlurFilter; +} EXYNOS_OMX_VIDEO_PARAM_ENABLE_BLURFILTER; + +typedef struct _EXYNOS_OMX_VIDEO_CONFIG_BLURINFO { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + EXYNOS_OMX_BLUR_MODE eBlurMode; + EXYNOS_OMX_BLUR_RESOL eTargetResol; +} EXYNOS_OMX_VIDEO_CONFIG_BLURINFO; +/* ROI Information */ + +typedef struct _EXYNOS_OMX_VIDEO_CONFIG_ROIINFO { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nUpperQpOffset; + OMX_S32 nLowerQpOffset; + OMX_BOOL bUseRoiInfo; + OMX_S32 nRoiMBInfoSize; + OMX_PTR pRoiMBInfo; +} EXYNOS_OMX_VIDEO_CONFIG_ROIINFO; + +typedef struct _EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnableRoiInfo; +} EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO; + +typedef enum _EXYNOS_OMX_ROTATION_TYPE +{ + ROTATE_0 = 0, + ROTATE_90 = 90, + ROTATE_180 = 180, + ROTATE_270 = 270, +} EXYNOS_OMX_ROTATION_TYPE; + +typedef struct _EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + EXYNOS_OMX_ROTATION_TYPE eRotationType; +} EXYNOS_OMX_VIDEO_PARAM_ROTATION_INFO; + +typedef struct _EXYNOS_OMX_VIDEO_PARAM_REORDERMODE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bReorderMode; +} EXYNOS_OMX_VIDEO_PARAM_REORDERMODE; + +typedef enum _EXYNOS_OMX_IMG_CROP_PORT +{ + IMG_CROP_INPUT_PORT = 0x00, //OMX_IndexConfigCommonInputCrop + IMG_CROP_OUTPUT_PORT, //OMX_IndexConfigCommonOutputCrop + IMG_CROP_PORT_MAX, +} EXYNOS_OMX_IMG_CROP_PORT; + +/* EXYNOS_OMX_IMG_INFO */ +/* nStride + * ------------------------------------ + * | nImageWidth | padding | + * | | xxxxxxx | + * | (top.left)---------| xxxxxxx | + * | | width | xxxxxxx | + * nImageHeight | | cccccc | xxxxxxx | + * | height | cccccc | xxxxxxx | nSliceHeight + * | | cccccc | xxxxxxx | + * | ---------| xxxxxxx | + * --|--------------------| xxxxxxx | + * | xxxxxxxxxxxxxxxxxxxxxxxxxxxx | + * ---------------------------------- + */ +typedef struct __EXYNOS_OMX_IMG_INFO { + OMX_S32 nStride; + OMX_S32 nSliceHeight; + OMX_S32 nImageWidth; + OMX_S32 nImageHeight; + + /* crop */ + OMX_S32 nLeft; + OMX_S32 nTop; + OMX_S32 nWidth; + OMX_S32 nHeight; +} EXYNOS_OMX_IMG_INFO; + +typedef OMX_CONFIG_BOOLEANTYPE EXYNOS_OMX_VIDEO_PARAM_IMAGE_CROP; + +// codec specific +typedef enum _EXYNOS_OMX_VIDEO_CODINGTYPE { +#ifdef USE_KHRONOS_OMX_HEADER + OMX_VIDEO_CodingVP9 = OMX_VIDEO_CodingVP8 + 1, /**< Google VP9 */ + OMX_VIDEO_CodingHEVC, /**< ITU H.265/HEVC */ +#endif + OMX_VIDEO_VendorCodingMAX = 0x7FFFFFFF, +} EXYNOS_OMX_VIDEO_CODINGTYPE; + +/* for AVC */ +#ifdef USE_KHRONOS_OMX_HEADER +typedef enum _EXYNOS_OMX_VIDEO_AVCPROFILETYPE { + OMX_VIDEO_AVCProfileConstrainedBaseline = 0x10000, + OMX_VIDEO_AVCProfileConstrainedHigh = 0x80000, +} OMX_VIDEO_AVCPROFILEEXTTYPE; + +typedef enum _EXYNOS_OMX_VIDEO_AVCLEVELTYPE { + OMX_VIDEO_AVCLevel52 = 0x10000, /**< Level 5.2 */ +} EXYNOS_OMX_VIDEO_AVCLEVELTYPE; +#endif +// AVC end + +/* for Mpeg4 */ +#ifdef USE_KHRONOS_OMX_HEADER +typedef enum _EXYNOS_OMX_VIDEO_MPEG4LEVELTYPE { + OMX_VIDEO_MPEG4Level3b = 0x18, /**< Level 3a */ + OMX_VIDEO_MPEG4Level6 = 0x100, /**< Level 6 */ +} EXYNOS_OMX_VIDEO_MPEG4LEVELTYPE; +#endif +// Mpeg4 end + +/* for Mpeg2 */ +#ifdef USE_KHRONOS_OMX_HEADER +typedef enum _EXYNOS_OMX_VIDEO_MPEG2LEVELTYPE { + OMX_VIDEO_MPEG2LevelHP = OMX_VIDEO_MPEG2LevelHL + 1, /**< HighP Level */ +} EXYNOS_OMX_VIDEO_MPEG2LEVELTYPE; +#endif +// Mpeg2 end + +/* for HEVC */ +#ifdef USE_KHRONOS_OMX_HEADER +typedef enum _OMX_VIDEO_HEVCPROFILETYPE { + OMX_VIDEO_HEVCProfileUnknown = 0x0, + OMX_VIDEO_HEVCProfileMain = 0x1, /**< Main profile */ + OMX_VIDEO_HEVCProfileMain10 = 0x2, /**< Main 10 profile */ + OMX_VIDEO_HEVCProfileMainStillPicture = 0x4, /**< Main Still Picture */ + // Main10 profile with HDR SEI support. + OMX_VIDEO_HEVCProfileMain10HDR10 = 0x1000, /**< Main10 profile with HDR SEI support */ + OMX_VIDEO_HEVCProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_HEVCProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_HEVCProfileMax = 0x7FFFFFFF +} OMX_VIDEO_HEVCPROFILETYPE; + +/** HEVC Level enum type */ +typedef enum _OMX_VIDEO_HEVCLEVELTYPE { + OMX_VIDEO_HEVCLevelUnknown = 0x00000000, + OMX_VIDEO_HEVCMainTierLevel1 = 0x00000001, /**< Level 1 */ + OMX_VIDEO_HEVCHighTierLevel1 = 0x00000002, + OMX_VIDEO_HEVCMainTierLevel2 = 0x00000004, /**< Level 2 */ + OMX_VIDEO_HEVCHighTierLevel2 = 0x00000008, + OMX_VIDEO_HEVCMainTierLevel21 = 0x00000010, /**< Level 2.1 */ + OMX_VIDEO_HEVCHighTierLevel21 = 0x00000020, + OMX_VIDEO_HEVCMainTierLevel3 = 0x00000040, /**< Level 3 */ + OMX_VIDEO_HEVCHighTierLevel3 = 0x00000080, + OMX_VIDEO_HEVCMainTierLevel31 = 0x00000100, /**< Level 3.1 */ + OMX_VIDEO_HEVCHighTierLevel31 = 0x00000200, + OMX_VIDEO_HEVCMainTierLevel4 = 0x00000400, /**< Level 4 */ + OMX_VIDEO_HEVCHighTierLevel4 = 0x00000800, + OMX_VIDEO_HEVCMainTierLevel41 = 0x00001000, /**< Level 4.1 */ + OMX_VIDEO_HEVCHighTierLevel41 = 0x00002000, + OMX_VIDEO_HEVCMainTierLevel5 = 0x00004000, /**< Level 5 */ + OMX_VIDEO_HEVCHighTierLevel5 = 0x00008000, + OMX_VIDEO_HEVCMainTierLevel51 = 0x00010000, /**< Level 5.1 */ + OMX_VIDEO_HEVCHighTierLevel51 = 0x00020000, + OMX_VIDEO_HEVCMainTierLevel52 = 0x00040000, /**< Level 5.2 */ + OMX_VIDEO_HEVCHighTierLevel52 = 0x00080000, + OMX_VIDEO_HEVCMainTierLevel6 = 0x00100000, /**< Level 6 */ + OMX_VIDEO_HEVCHighTierLevel6 = 0x00200000, + OMX_VIDEO_HEVCMainTierLevel61 = 0x00400000, /**< Level 6.1 */ + OMX_VIDEO_HEVCHighTierLevel61 = 0x00800000, + OMX_VIDEO_HEVCMainTierLevel62 = 0x01000000, /**< Level 6.2 */ + OMX_VIDEO_HEVCHighTierLevel62 = 0x02000000, + OMX_VIDEO_HEVCLevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_HEVCLevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_HEVCHighMAX = 0x7FFFFFFF +} OMX_VIDEO_HEVCLEVELTYPE; + +/** Structure for controlling HEVC video encoding and decoding */ +typedef struct _OMX_VIDEO_PARAM_HEVCTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_HEVCPROFILETYPE eProfile; + OMX_VIDEO_HEVCLEVELTYPE eLevel; + OMX_U32 nKeyFrameInterval; // distance between consecutive I-frames (including one + // of the I frames). 0 means interval is unspecified and + // can be freely chosen by the codec. 1 means a stream of + // only I frames. +} OMX_VIDEO_PARAM_HEVCTYPE; +#endif // hevc end + +/* for VP9 */ +#ifdef USE_KHRONOS_OMX_HEADER +typedef enum _OMX_VIDEO_VP9PROFILETYPE { + OMX_VIDEO_VP9Profile0 = 0x0, + OMX_VIDEO_VP9Profile1 = 0x1, + OMX_VIDEO_VP9Profile2 = 0x2, + OMX_VIDEO_VP9Profile3 = 0x4, + // HDR profiles also support passing HDR metadata + OMX_VIDEO_VP9Profile2HDR = 0x1000, + OMX_VIDEO_VP9Profile3HDR = 0x2000, + OMX_VIDEO_VP9Profile2HDR10Plus = 0x4000, + OMX_VIDEO_VP9Profile3HDR10Plus = 0x8000, + OMX_VIDEO_VP9ProfileUnknown = 0x6EFFFFFF, + OMX_VIDEO_VP9ProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_VP9ProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_VP9ProfileMax = 0x7FFFFFFF +} OMX_VIDEO_VP9PROFILETYPE; + + /* VP9 levels */ +typedef enum _OMX_VIDEO_VP9LEVELTYPE { + OMX_VIDEO_VP9Level1 = 0x0, + OMX_VIDEO_VP9Level11 = 0x1, + OMX_VIDEO_VP9Level2 = 0x2, + OMX_VIDEO_VP9Level21 = 0x4, + OMX_VIDEO_VP9Level3 = 0x8, + OMX_VIDEO_VP9Level31 = 0x10, + OMX_VIDEO_VP9Level4 = 0x20, + OMX_VIDEO_VP9Level41 = 0x40, + OMX_VIDEO_VP9Level5 = 0x80, + OMX_VIDEO_VP9Level51 = 0x100, + OMX_VIDEO_VP9Level52 = 0x200, + OMX_VIDEO_VP9Level6 = 0x400, + OMX_VIDEO_VP9Level61 = 0x800, + OMX_VIDEO_VP9Level62 = 0x1000, + OMX_VIDEO_VP9LevelUnknown = 0x6EFFFFFF, + OMX_VIDEO_VP9LevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_VP9LevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_VP9LevelMax = 0x7FFFFFFF +} OMX_VIDEO_VP9LEVELTYPE; + +typedef struct _OMX_VIDEO_PARAM_VP9TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_VP9PROFILETYPE eProfile; + OMX_VIDEO_VP9LEVELTYPE eLevel; + OMX_BOOL bErrorResilientMode; +} OMX_VIDEO_PARAM_VP9TYPE; +#endif // vp9 end +#ifndef USE_KHRONOS_OMX_1_2 +/* WMV codec */ +/** WMV Profile enum type */ +typedef enum _OMX_VIDEO_WMVPROFILETYPE { + OMX_VIDEO_WMVProfileSimple = 0, + OMX_VIDEO_WMVProfileMain, + OMX_VIDEO_WMVProfileAdvanced, + OMX_VIDEO_WMVProfileUnknown = 0x6EFFFFFF, + OMX_VIDEO_WMVProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_WMVProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ +} OMX_VIDEO_WMVPROFILETYPE; + +/** WMV Level enum type */ +typedef enum _OMX_VIDEO_WMVLEVELTYPE { + OMX_VIDEO_WMVLevelLow = 0, + OMX_VIDEO_WMVLevelMedium, + OMX_VIDEO_WMVLevelHigh, + OMX_VIDEO_WMVLevelL0, + OMX_VIDEO_WMVLevelL1, + OMX_VIDEO_WMVLevelL2, + OMX_VIDEO_WMVLevelL3, + OMX_VIDEO_WMVLevelL4, + OMX_VIDEO_WMVLevelUnknown = 0x6EFFFFFF, + OMX_VIDEO_WMVLevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_WMVLevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ +} OMX_VIDEO_WMVLEVELTYPE; + +/* VC1 codec */ +/** VC1 Profile enum type */ +typedef enum _OMX_VIDEO_VC1PROFILETYPE { + OMX_VIDEO_VC1ProfileUnused = 0, + OMX_VIDEO_VC1ProfileSimple, + OMX_VIDEO_VC1ProfileMain, + OMX_VIDEO_VC1ProfileAdvanced, + OMX_VIDEO_VC1ProfileUnknown = 0x6EFFFFFF, + OMX_VIDEO_VC1ProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_VC1ProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_VC1ProfileMax +} OMX_VIDEO_VC1PROFILETYPE; + +/** VC1 Level enum type */ +typedef enum _OMX_VIDEO_VC1LEVELTYPE { + OMX_VIDEO_VC1LevelUnused = 0, + OMX_VIDEO_VC1LevelLow, + OMX_VIDEO_VC1LevelMedium, + OMX_VIDEO_VC1LevelHigh, + OMX_VIDEO_VC1Level0, + OMX_VIDEO_VC1Level1, + OMX_VIDEO_VC1Level2, + OMX_VIDEO_VC1Level3, + OMX_VIDEO_VC1Level4, + OMX_VIDEO_VC1LevelUnknown = 0x6EFFFFFF, + OMX_VIDEO_VC1LevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_VC1LevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_VC1LevelMax +} OMX_VIDEO_VC1LEVELTYPE; + +/** Structure for controlling VC1 video encoding and decoding */ +typedef struct _OMX_VIDEO_PARAM_VC1TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_VC1PROFILETYPE eProfile; + OMX_VIDEO_VC1LEVELTYPE eLevel; +} OMX_VIDEO_PARAM_VC1TYPE; +#endif // USE_KHRONOS_OMX_1_2 +// codec specific end + + + +// for android +typedef struct _EXYNOS_OMX_VIDEO_PRIMARIES { + OMX_U16 x; + OMX_U16 y; +} EXYNOS_OMX_VIDEO_PRIMARIES; + +typedef struct _EXYNOS_OMX_VIDEO_HDRSTATICINFO { + OMX_U32 nMaxPicAverageLight; + OMX_U32 nMaxContentLight; + OMX_U32 nMaxDisplayLuminance; + OMX_U32 nMinDisplayLuminance; + + EXYNOS_OMX_VIDEO_PRIMARIES red; + EXYNOS_OMX_VIDEO_PRIMARIES green; + EXYNOS_OMX_VIDEO_PRIMARIES blue; + EXYNOS_OMX_VIDEO_PRIMARIES white; +} EXYNOS_OMX_VIDEO_HDRSTATICINFO; + +typedef struct _EXYNOS_OMX_VIDEO_COLORASPECTS { + OMX_U32 nRangeType; + OMX_U32 nPrimaryType; + OMX_U32 nTransferType; + OMX_U32 nCoeffType; + OMX_U32 nDataSpace; +} EXYNOS_OMX_VIDEO_COLORASPECTS; + +#define MAX_HDR10PLUS_SIZE 1024 +typedef struct _EXYNOS_OMX_VIDEO_HDR10PLUS_INFO { + OMX_BOOL bOccupied; + OMX_U32 nTag; + OMX_PTR pHDR10PlusInfo; +} EXYNOS_OMX_VIDEO_HDR10PLUS_INFO; + +#ifdef USE_KHRONOS_OMX_HEADER +/** + * Structure for configuring video compression intra refresh period + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nRefreshPeriod : Intra refreh period in frames. Value 0 means disable intra refresh +*/ +typedef struct _OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nRefreshPeriod; +} OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE; + +/** Maximum number of VP8 temporal layers */ +#define OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS 3 + +/** VP8 temporal layer patterns */ +typedef enum _OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE { + OMX_VIDEO_VPXTemporalLayerPatternNone = 0, + OMX_VIDEO_VPXTemporalLayerPatternWebRTC = 1, + OMX_VIDEO_VPXTemporalLayerPatternMax = 0x7FFFFFFF +} OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE; + +/** + * Android specific VP8/VP9 encoder params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nKeyFrameInterval : Key frame interval in frames + * eTemporalPattern : Type of temporal layer pattern + * nTemporalLayerCount : Number of temporal coding layers + * nTemporalLayerBitrateRatio : Bitrate ratio allocation between temporal + * streams in percentage + * nMinQuantizer : Minimum (best quality) quantizer + * nMaxQuantizer : Maximum (worst quality) quantizer + */ +typedef struct _OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nKeyFrameInterval; // distance between consecutive key_frames (including one + // of the key_frames). 0 means interval is unspecified and + // can be freely chosen by the codec. 1 means a stream of + // only key_frames. + OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE eTemporalPattern; + OMX_U32 nTemporalLayerCount; + OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS]; + OMX_U32 nMinQuantizer; + OMX_U32 nMaxQuantizer; +} OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE; + +/** Structure to define if dependent slice segments should be used */ +typedef struct _OMX_VIDEO_SLICESEGMENTSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bDepedentSegments; + OMX_BOOL bEnableLoopFilterAcrossSlices; +} OMX_VIDEO_SLICESEGMENTSTYPE; + +#define OMX_MAX_STRINGVALUE_SIZE OMX_MAX_STRINGNAME_SIZE +#define OMX_MAX_ANDROID_VENDOR_PARAMCOUNT 32 + +typedef enum _OMX_ANDROID_VENDOR_VALUETYPE { + OMX_AndroidVendorValueInt32 = 0, /*<< int32_t value */ + OMX_AndroidVendorValueInt64, /*<< int64_t value */ + OMX_AndroidVendorValueString, /*<< string value */ + OMX_AndroidVendorValueEndUnused, +} OMX_ANDROID_VENDOR_VALUETYPE; + +/** + * Structure describing a single value of an Android vendor extension. + * + * STRUCTURE MEMBERS: + * cKey : parameter value name. + * eValueType : parameter value type + * bSet : if false, the parameter is not set (for OMX_GetConfig) or is unset (OMX_SetConfig) + * if true, the parameter is set to the corresponding value below + * nInt64 : int64 value + * cString : string value + */ +typedef struct _OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE { + OMX_U8 cKey[OMX_MAX_STRINGNAME_SIZE]; + OMX_ANDROID_VENDOR_VALUETYPE eValueType; + OMX_BOOL bSet; + union { + OMX_S32 nInt32; + OMX_S64 nInt64; + OMX_U8 cString[OMX_MAX_STRINGVALUE_SIZE]; + }; +} OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE; + +/** + * OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE is the structure for an Android vendor extension + * supported by the component. This structure enumerates the various extension parameters and their + * values. + * + * Android vendor extensions have a name and one or more parameter values - each with a string key - + * that are set together. The values are exposed to Android applications via a string key that is + * the concatenation of 'vendor', the extension name and the parameter key, each separated by dot + * (.), with any trailing '.value' suffix(es) removed (though optionally allowed). + * + * Extension names and parameter keys are subject to the following rules: + * - Each SHALL contain a set of lowercase alphanumeric (underscore allowed) tags separated by + * dot (.) or dash (-). + * - The first character of the first tag, and any tag following a dot SHALL not start with a + * digit. + * - Tags 'value', 'vendor', 'omx' and 'android' (even if trailed and/or followed by any number + * of underscores) are prohibited in the extension name. + * - Tags 'vendor', 'omx' and 'android' (even if trailed and/or followed by any number + * of underscores) are prohibited in parameter keys. + * - The tag 'value' (even if trailed and/or followed by any number + * of underscores) is prohibited in parameter keys with the following exception: + * the parameter key may be exactly 'value' + * - The parameter key for extensions with a single parameter value SHALL be 'value' + * - No two extensions SHALL have the same name + * - No extension's name SHALL start with another extension's NAME followed by a dot (.) + * - No two parameters of an extension SHALL have the same key + * + * This config can be used with both OMX_GetConfig and OMX_SetConfig. In the OMX_GetConfig + * case, the caller specifies nIndex and nParamSizeUsed. The component fills in cName, + * eDir and nParamCount. Additionally, if nParamSizeUsed is not less than nParamCount, the + * component fills out the parameter values (nParam) with the current values for each parameter + * of the vendor extension. + * + * The value of nIndex goes from 0 to N-1, where N is the number of Android vendor extensions + * supported by the component. The component does not need to report N as the caller can determine + * N by enumerating all extensions supported by the component. The component may not support any + * extensions. If there are no more extensions, OMX_GetParameter returns OMX_ErrorNoMore. The + * component supplies extensions in the order it wants clients to set them. + * + * The component SHALL return OMX_ErrorNone for all cases where nIndex is less than N (specifically + * even in the case of where nParamCount is greater than nParamSizeUsed). + * + * In the OMX_SetConfig case the field nIndex is ignored. If the component supports an Android + * vendor extension with the name in cName, it SHALL configure the parameter values for that + * extension according to the parameters in nParam. nParamCount is the number of valid parameters + * in the nParam array, and nParamSizeUsed is the size of the nParam array. (nParamSizeUsed + * SHALL be at least nParamCount) Parameters that are part of a vendor extension but are not + * in the nParam array are assumed to be unset (this is different from not changed). + * All parameter values SHALL have distinct keys in nParam (the component can assume that this + * is the case. Otherwise, the actual value for the parameters that are multiply defined can + * be any of the set values.) + * + * Return values in case of OMX_SetConfig: + * OMX_ErrorUnsupportedIndex: the component does not support the extension specified by cName + * OMX_ErrorUnsupportedSetting: the component does not support some or any of the parameters + * (names) specified in nParam + * OMX_ErrorBadParameter: the parameter is invalid (e.g. nParamCount is greater than + * nParamSizeUsed, or some parameter value has invalid type) + * + * STRUCTURE MEMBERS: + * nSize : size of the structure in bytes + * nVersion : OMX specification version information + * cName : name of vendor extension + * nParamCount : the number of parameter values that are part of this vendor extension + * nParamSizeUsed : the size of nParam + * (must be at least 1 and at most OMX_MAX_ANDROID_VENDOR_PARAMCOUNT) + * param : the parameter values + */ +typedef struct _OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nIndex; + OMX_U8 cName[OMX_MAX_STRINGNAME_SIZE]; + OMX_DIRTYPE eDir; + OMX_U32 nParamCount; + OMX_U32 nParamSizeUsed; + OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE param[1]; +} OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE; + +/** Maximum number of temporal layers supported by AVC/HEVC */ +#define OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS 8 + +/** temporal layer patterns */ +typedef enum OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE { + OMX_VIDEO_AndroidTemporalLayeringPatternNone = 0, + // pattern as defined by WebRTC + OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC = 1 << 0, + // pattern where frames in any layer other than the base layer only depend on at most the very + // last frame from each preceding layer (other than the base layer.) + OMX_VIDEO_AndroidTemporalLayeringPatternAndroid = 1 << 1, +} OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE; + +/** + * Android specific param for configuration of temporal layering. + * Android only supports temporal layering where successive layers each double the + * previous layer's framerate. + * NOTE: Reading this parameter at run-time SHALL return actual run-time values. + * + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to (output port for encoders) + * eSupportedPatterns : A bitmask of supported layering patterns + * nLayerCountMax : Max number of temporal coding layers supported + * by the encoder (must be at least 1, 1 meaning temporal layering + * is NOT supported) + * nBLayerCountMax : Max number of layers that can contain B frames + * (0) to (nLayerCountMax - 1) + * ePattern : Layering pattern. + * nPLayerCountActual : Number of temporal layers to be coded with non-B frames, + * starting from and including the base-layer. + * (1 to nLayerCountMax - nBLayerCountActual) + * If nPLayerCountActual is 1 and nBLayerCountActual is 0, temporal + * layering is disabled. Otherwise, it is enabled. + * nBLayerCountActual : Number of temporal layers to be coded with B frames, + * starting after non-B layers. + * (0 to nBLayerCountMax) + * bBitrateRatiosSpecified : Flag to indicate if layer-wise bitrate + * distribution is specified. + * nBitrateRatios : Bitrate ratio (100 based) per layer (index 0 is base layer). + * Honored if bBitrateRatiosSpecified is set. + * i.e for 4 layers with desired distribution (25% 25% 25% 25%), + * nBitrateRatio = {25, 50, 75, 100, ... } + * Values in indices not less than 'the actual number of layers + * minus 1' MAY be ignored and assumed to be 100. + */ +typedef struct OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE eSupportedPatterns; + OMX_U32 nLayerCountMax; + OMX_U32 nBLayerCountMax; + OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern; + OMX_U32 nPLayerCountActual; + OMX_U32 nBLayerCountActual; + OMX_BOOL bBitrateRatiosSpecified; + OMX_U32 nBitrateRatios[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS]; +} OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE; + +/** + * Android specific config for changing the temporal-layer count or + * bitrate-distribution at run-time. + * + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to (output port for encoders) + * ePattern : Layering pattern. + * nPLayerCountActual : Number of temporal layers to be coded with non-B frames. + * (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.) + * nBLayerCountActual : Number of temporal layers to be coded with B frames. + * (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.) + * bBitrateRatiosSpecified : Flag to indicate if layer-wise bitrate + * distribution is specified. + * nBitrateRatios : Bitrate ratio (100 based, Q16 values) per layer (0 is base layer). + * Honored if bBitrateRatiosSpecified is set. + * (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.) + */ +typedef struct OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern; + OMX_U32 nPLayerCountActual; + OMX_U32 nBLayerCountActual; + OMX_BOOL bBitrateRatiosSpecified; + OMX_U32 nBitrateRatios[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS]; +} OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE; + +#endif +// android end + + + +// for custom component +typedef struct _EXYNOS_OMX_VIDEO_PARAM_CORRUPTEDHEADER { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bDiscardEvent; +} EXYNOS_OMX_VIDEO_PARAM_CORRUPTEDHEADER; + +typedef struct _OMX_VIDEO_PARAM_IMG_CONV { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnable; + OMX_U32 nWidth; + OMX_U32 nHeight; +} OMX_VIDEO_PARAM_IMG_CONV; + +// custom component end + + + +// for Skype HD +typedef struct OMX_VIDEO_PARAM_DRIVERVER { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U64 nDriverVersion; +} OMX_VIDEO_PARAM_DRIVERVER; + +typedef struct OMX_VIDEO_CONFIG_MARKLTRFRAME { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nLongTermFrmIdx; +} OMX_VIDEO_CONFIG_MARKLTRFRAME; + +typedef struct OMX_VIDEO_CONFIG_USELTRFRAME { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U16 nUsedLTRFrameBM; +} OMX_VIDEO_CONFIG_USELTRFRAME; + +typedef struct OMX_VIDEO_CONFIG_QP { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nQP; +} OMX_VIDEO_CONFIG_QP; + +typedef struct OMX_VIDEO_CONFIG_BASELAYERPID{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nPID; +} OMX_VIDEO_CONFIG_BASELAYERPID; + +typedef struct __OMX_PARAM_ENC_MAX_TEMPORALLAYER_COUNT { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nMaxCountP; + OMX_U32 nMaxCountB; +} OMX_PARAM_ENC_MAX_TEMPORALLAYER_COUNT; + +typedef struct __OMX_PARAM_ENC_PREPROCESS { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nResize; + OMX_U32 nRotation; +} OMX_PARAM_ENC_PREPROCESS; + +typedef struct __OMX_PARAM_ENC_SAR { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nWidth; + OMX_U32 nHeight; +} OMX_PARAM_ENC_SAR; + +typedef struct __OMX_CONFIG_ENC_TRIGGER_TS { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S64 nTimestamp; +} OMX_CONFIG_ENC_TRIGGER_TS; + +#ifndef __OMX_EXPORTS +#define __OMX_EXPORTS +#define EXYNOS_EXPORT_REF __attribute__((visibility("default"))) +#define EXYNOS_IMPORT_REF __attribute__((visibility("default"))) +#endif + +#endif diff --git a/openmax/include/exynos/Exynos_OMX_Macros.h b/openmax/include/exynos/Exynos_OMX_Macros.h new file mode 100644 index 0000000..d97bf1d --- /dev/null +++ b/openmax/include/exynos/Exynos_OMX_Macros.h @@ -0,0 +1,137 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OMX_Macros.h + * @brief Macros + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OMX_MACROS +#define EXYNOS_OMX_MACROS + +#include "Exynos_OMX_Def.h" +#include "Exynos_OSAL_Memory.h" + + +/* + * MACROS + */ +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define ALIGN_TO_16B(x) ((((x) + (1 << 4) - 1) >> 4) << 4) +#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5) +#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7) +#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13) + +/* This is for single FD support. + * data is not filled like as continuous padding area for satisfying H/W constraints. + */ +/* 8bit format */ +#define GET_Y_SIZE(w, h) (ALIGN(w, 16) * ALIGN(h, 16) + 256) +#define GET_UV_SIZE(w, h) (ALIGN(((ALIGN(w, 16) * ALIGN(h, 16) / 2) + 256), 16)) +#define GET_CB_SIZE(w, h) (ALIGN(((ALIGN(w / 2, 16) * ALIGN(h, 16) / 2) + 256), 16)) +#define GET_CR_SIZE(w, h) (ALIGN(((ALIGN(w / 2, 16) * ALIGN(h, 16) / 2) + 256), 16)) + +#define GET_UV_OFFSET(w, h) GET_Y_SIZE(w, h) +#define GET_CB_OFFSET(w, h) GET_Y_SIZE(w, h) +#define GET_CR_OFFSET(w, h) (GET_Y_SIZE(w, h) + GET_CB_SIZE(w, h)) + +/* 10bit format */ + +#ifndef S10B_FORMAT_8B_ALIGNMENT +#define S10B_FORMAT_8B_ALIGNMENT 16 +#endif +#define GET_8B_Y_SIZE(w, h) (ALIGN(w, S10B_FORMAT_8B_ALIGNMENT) * ALIGN(h, 16) + 256) +#define GET_8B_UV_SIZE(w, h) (ALIGN(((ALIGN(w, S10B_FORMAT_8B_ALIGNMENT) * ALIGN(h, 16) / 2) + 256), 16)) +#define GET_8B_CB_SIZE(w, h) (ALIGN(((ALIGN(w / 2, S10B_FORMAT_8B_ALIGNMENT) * ALIGN(h, 16) / 2) + 256), 16)) +#define GET_8B_CR_SIZE(w, h) (ALIGN(((ALIGN(w / 2, S10B_FORMAT_8B_ALIGNMENT) * ALIGN(h, 16) / 2) + 256), 16)) +#define GET_2B_SIZE(w, h) (ALIGN(w / 4, 16) * ALIGN(h, 16) + 64) +#define GET_10B_Y_SIZE(w, h) (GET_8B_Y_SIZE(w, h) + GET_2B_SIZE(w, h)) +#define GET_10B_UV_SIZE(w, h) (GET_8B_UV_SIZE(w, h) + GET_2B_SIZE(w, h / 2)) +#define GET_10B_CB_SIZE(w, h) (GET_8B_CB_SIZE(w, h) + GET_2B_SIZE(w, h / 2)) +#define GET_10B_CR_SIZE(w, h) (GET_8B_CR_SIZE(w, h) + GET_2B_SIZE(w, h / 2)) + +#define GET_10B_UV_OFFSET(w, h) GET_10B_Y_SIZE(w, h) +#define GET_10B_CB_OFFSET(w, h) GET_10B_Y_SIZE(w, h) +#define GET_10B_CR_OFFSET(w, h) (GET_10B_Y_SIZE(w, h) + GET_10B_CB_SIZE(w, h)) + +#define SBWC_8B_STRIDE(w) (128 * (((w) + 31) / 32)) +#define SBWC_10B_STRIDE(w) (160 * (((w) + 31) / 32)) +#define SBWC_HEADER_STRIDE(w) ((((((w) + 63) / 64) + 15) / 16) * 16) + +#define SBWC_8B_Y_SIZE(w, h) ((SBWC_8B_STRIDE(w) * ((ALIGN((h), 16) + 3) / 4)) + 64) +#define SBWC_8B_Y_HEADER_SIZE(w, h) ALIGN(((SBWC_HEADER_STRIDE(w) * ((ALIGN((h), 16) + 3) / 4)) + 256), 32) +#define SBWC_8B_CBCR_SIZE(w, h) ((SBWC_8B_STRIDE(w) * (((ALIGN((h), 16) / 2) + 3) / 4)) + 64) +#define SBWC_8B_CBCR_HEADER_SIZE(w, h) ((SBWC_HEADER_STRIDE(w) * (((ALIGN((h), 16) / 2) + 3) / 4)) + 128) + +#define SBWC_10B_Y_SIZE(w, h) ((SBWC_10B_STRIDE(w) * ((ALIGN((h), 16) + 3) / 4)) + 64) +#define SBWC_10B_Y_HEADER_SIZE(w, h) ALIGN((((ALIGN((w), 32) * ALIGN((h), 16) * 2) + 256) - SBWC_10B_Y_SIZE(w, h)), 32) +#define SBWC_10B_CBCR_SIZE(w, h) ((SBWC_10B_STRIDE(w) * (((ALIGN((h), 16) / 2) + 3) / 4)) + 64) +#define SBWC_10B_CBCR_HEADER_SIZE(w, h) (((ALIGN((w), 32) * ALIGN((h), 16)) + 256) - SBWC_10B_CBCR_SIZE(w, h)) + +#define SBWCL_8B_STRIDE(w, r) (((128 * (r)) / 100) * (((w) + 31) / 32)) +#define SBWCL_10B_STRIDE(w, r) (((160 * (r)) / 100) * (((w) + 31) / 32)) +#define SBWCL_8B_Y_SIZE(w, h, r) ((SBWCL_8B_STRIDE(w, r) * ((ALIGN((h), 16) + 3) / 4)) + 64) +#define SBWCL_8B_CBCR_SIZE(w, h, r) ((SBWCL_8B_STRIDE(w, r) * (((ALIGN((h), 16) / 2) + 3) / 4)) + 64) +#define SBWCL_10B_Y_SIZE(w, h, r) ((SBWCL_10B_STRIDE(w, r) * ((ALIGN((h), 16) + 3) / 4)) + 64) +#define SBWCL_10B_CBCR_SIZE(w, h, r) ((SBWCL_10B_STRIDE(w, r) * (((ALIGN((h), 16) / 2) + 3) / 4)) + 64) + +#define InitOMXParams(params, size) \ + do { \ + (params)->nSize = size; \ + (params)->nVersion.s.nVersionMajor = 1; \ + (params)->nVersion.s.nVersionMinor = 0; \ + (params)->nVersion.s.nRevision = 0; \ + (params)->nVersion.s.nStep = 0; \ + } while(0) + +#define INIT_SET_SIZE_VERSION(_struct_, _structType_) \ + do { \ + Exynos_OSAL_Memset((_struct_), 0, sizeof(_structType_)); \ + (_struct_)->nSize = sizeof(_structType_); \ + (_struct_)->nVersion.s.nVersionMajor = VERSIONMAJOR_NUMBER; \ + (_struct_)->nVersion.s.nVersionMinor = VERSIONMINOR_NUMBER; \ + (_struct_)->nVersion.s.nRevision = REVISION_NUMBER; \ + (_struct_)->nVersion.s.nStep = STEP_NUMBER; \ + } while (0) + +#define INIT_ARRAY_TO_VAL(array, value, size) \ + do { \ + int i; \ + for (i = 0; i < size; i++) { \ + array[i] = value; \ + } \ + } while(0) + +/* + * Port Specific + */ +#define EXYNOS_TUNNEL_ESTABLISHED 0x0001 +#define EXYNOS_TUNNEL_IS_SUPPLIER 0x0002 + +#define CHECK_PORT_BEING_FLUSHED(port) (((port)->portState == EXYNOS_OMX_PortStateFlushing) || ((port)->portState == EXYNOS_OMX_PortStateFlushingForDisable)) +#define CHECK_PORT_BEING_DISABLED(port) ((port)->portState == EXYNOS_OMX_PortStateDisabling) +#define CHECK_PORT_BEING_ENABLED(port) ((port)->portState == EXYNOS_OMX_PortStateEnabling) +#define CHECK_PORT_ENABLED(port) ((port)->portDefinition.bEnabled == OMX_TRUE) +#define CHECK_PORT_POPULATED(port) ((port)->portDefinition.bPopulated == OMX_TRUE) +#define CHECK_PORT_TUNNELED(port) ((port)->tunnelFlags & EXYNOS_TUNNEL_ESTABLISHED) +#define CHECK_PORT_BUFFER_SUPPLIER(port) ((port)->tunnelFlags & EXYNOS_TUNNEL_IS_SUPPLIER) + +#endif diff --git a/openmax/include/khronos/OMX_Audio.h b/openmax/include/khronos/OMX_Audio.h new file mode 100644 index 0000000..04f1a99 --- /dev/null +++ b/openmax/include/khronos/OMX_Audio.h @@ -0,0 +1,1311 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** @file OMX_Audio.h - OpenMax IL version 1.1.2 + * The structures needed by Audio components to exchange + * parameters and configuration data with the componenmilts. + */ + +#ifndef OMX_Audio_h +#define OMX_Audio_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include + +/** @defgroup midi MIDI + * @ingroup audio + */ + +/** @defgroup effects Audio effects + * @ingroup audio + */ + +/** @defgroup audio OpenMAX IL Audio Domain + * Structures for OpenMAX IL Audio domain + * @{ + */ + +/** Enumeration used to define the possible audio codings. + * If "OMX_AUDIO_CodingUnused" is selected, the coding selection must + * be done in a vendor specific way. Since this is for an audio + * processing element this enum is relevant. However, for another + * type of component other enums would be in this area. + */ +typedef enum OMX_AUDIO_CODINGTYPE { + OMX_AUDIO_CodingUnused = 0, /**< Placeholder value when coding is N/A */ + OMX_AUDIO_CodingAutoDetect, /**< auto detection of audio format */ + OMX_AUDIO_CodingPCM, /**< Any variant of PCM coding */ + OMX_AUDIO_CodingADPCM, /**< Any variant of ADPCM encoded data */ + OMX_AUDIO_CodingAMR, /**< Any variant of AMR encoded data */ + OMX_AUDIO_CodingGSMFR, /**< Any variant of GSM fullrate (i.e. GSM610) */ + OMX_AUDIO_CodingGSMEFR, /**< Any variant of GSM Enhanced Fullrate encoded data*/ + OMX_AUDIO_CodingGSMHR, /**< Any variant of GSM Halfrate encoded data */ + OMX_AUDIO_CodingPDCFR, /**< Any variant of PDC Fullrate encoded data */ + OMX_AUDIO_CodingPDCEFR, /**< Any variant of PDC Enhanced Fullrate encoded data */ + OMX_AUDIO_CodingPDCHR, /**< Any variant of PDC Halfrate encoded data */ + OMX_AUDIO_CodingTDMAFR, /**< Any variant of TDMA Fullrate encoded data (TIA/EIA-136-420) */ + OMX_AUDIO_CodingTDMAEFR, /**< Any variant of TDMA Enhanced Fullrate encoded data (TIA/EIA-136-410) */ + OMX_AUDIO_CodingQCELP8, /**< Any variant of QCELP 8kbps encoded data */ + OMX_AUDIO_CodingQCELP13, /**< Any variant of QCELP 13kbps encoded data */ + OMX_AUDIO_CodingEVRC, /**< Any variant of EVRC encoded data */ + OMX_AUDIO_CodingSMV, /**< Any variant of SMV encoded data */ + OMX_AUDIO_CodingG711, /**< Any variant of G.711 encoded data */ + OMX_AUDIO_CodingG723, /**< Any variant of G.723 dot 1 encoded data */ + OMX_AUDIO_CodingG726, /**< Any variant of G.726 encoded data */ + OMX_AUDIO_CodingG729, /**< Any variant of G.729 encoded data */ + OMX_AUDIO_CodingAAC, /**< Any variant of AAC encoded data */ + OMX_AUDIO_CodingMP3, /**< Any variant of MP3 encoded data */ + OMX_AUDIO_CodingSBC, /**< Any variant of SBC encoded data */ + OMX_AUDIO_CodingVORBIS, /**< Any variant of VORBIS encoded data */ + OMX_AUDIO_CodingWMA, /**< Any variant of WMA encoded data */ + OMX_AUDIO_CodingRA, /**< Any variant of RA encoded data */ + OMX_AUDIO_CodingMIDI, /**< Any variant of MIDI encoded data */ + OMX_AUDIO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_CodingMax = 0x7FFFFFFF +} OMX_AUDIO_CODINGTYPE; + + +/** The PortDefinition structure is used to define all of the parameters + * necessary for the compliant component to setup an input or an output audio + * path. If additional information is needed to define the parameters of the + * port (such as frequency), additional structures must be sent such as the + * OMX_AUDIO_PARAM_PCMMODETYPE structure to supply the extra parameters for the port. + */ +typedef struct OMX_AUDIO_PORTDEFINITIONTYPE { + OMX_STRING cMIMEType; /**< MIME type of data for the port */ + OMX_NATIVE_DEVICETYPE pNativeRender; /** < platform specific reference + for an output device, + otherwise this field is 0 */ + OMX_BOOL bFlagErrorConcealment; /**< Turns on error concealment if it is + supported by the OMX component */ + OMX_AUDIO_CODINGTYPE eEncoding; /**< Type of data expected for this + port (e.g. PCM, AMR, MP3, etc) */ +} OMX_AUDIO_PORTDEFINITIONTYPE; + + +/** Port format parameter. This structure is used to enumerate + * the various data input/output format supported by the port. + */ +typedef struct OMX_AUDIO_PARAM_PORTFORMATTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Indicates which port to set */ + OMX_U32 nIndex; /**< Indicates the enumeration index for the format from 0x0 to N-1 */ + OMX_AUDIO_CODINGTYPE eEncoding; /**< Type of data expected for this port (e.g. PCM, AMR, MP3, etc) */ +} OMX_AUDIO_PARAM_PORTFORMATTYPE; + + +/** PCM mode type */ +typedef enum OMX_AUDIO_PCMMODETYPE { + OMX_AUDIO_PCMModeLinear = 0, /**< Linear PCM encoded data */ + OMX_AUDIO_PCMModeALaw, /**< A law PCM encoded data (G.711) */ + OMX_AUDIO_PCMModeMULaw, /**< Mu law PCM encoded data (G.711) */ + OMX_AUDIO_PCMModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_PCMModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_PCMModeMax = 0x7FFFFFFF +} OMX_AUDIO_PCMMODETYPE; + + +typedef enum OMX_AUDIO_CHANNELTYPE { + OMX_AUDIO_ChannelNone = 0x0, /**< Unused or empty */ + OMX_AUDIO_ChannelLF = 0x1, /**< Left front */ + OMX_AUDIO_ChannelRF = 0x2, /**< Right front */ + OMX_AUDIO_ChannelCF = 0x3, /**< Center front */ + OMX_AUDIO_ChannelLS = 0x4, /**< Left surround */ + OMX_AUDIO_ChannelRS = 0x5, /**< Right surround */ + OMX_AUDIO_ChannelLFE = 0x6, /**< Low frequency effects */ + OMX_AUDIO_ChannelCS = 0x7, /**< Back surround */ + OMX_AUDIO_ChannelLR = 0x8, /**< Left rear. */ + OMX_AUDIO_ChannelRR = 0x9, /**< Right rear. */ + OMX_AUDIO_ChannelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_ChannelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_ChannelMax = 0x7FFFFFFF +} OMX_AUDIO_CHANNELTYPE; + +#define OMX_AUDIO_MAXCHANNELS 16 /**< maximum number distinct audio channels that a buffer may contain */ +#define OMX_MIN_PCMPAYLOAD_MSEC 5 /**< Minimum audio buffer payload size for uncompressed (PCM) audio */ + +/** PCM format description */ +typedef struct OMX_AUDIO_PARAM_PCMMODETYPE { + OMX_U32 nSize; /**< Size of this structure, in Bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels (e.g. 2 for stereo) */ + OMX_NUMERICALDATATYPE eNumData; /**< indicates PCM data as signed or unsigned */ + OMX_ENDIANTYPE eEndian; /**< indicates PCM data as little or big endian */ + OMX_BOOL bInterleaved; /**< True for normal interleaved data; false for + non-interleaved data (e.g. block data) */ + OMX_U32 nBitPerSample; /**< Bit per sample */ + OMX_U32 nSamplingRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ + OMX_AUDIO_PCMMODETYPE ePCMMode; /**< PCM mode enumeration */ + OMX_AUDIO_CHANNELTYPE eChannelMapping[OMX_AUDIO_MAXCHANNELS]; /**< Slot i contains channel defined by eChannelMap[i] */ + +} OMX_AUDIO_PARAM_PCMMODETYPE; + + +/** Audio channel mode. This is used by both AAC and MP3, although the names are more appropriate + * for the MP3. For example, JointStereo for MP3 is CouplingChannels for AAC. + */ +typedef enum OMX_AUDIO_CHANNELMODETYPE { + OMX_AUDIO_ChannelModeStereo = 0, /**< 2 channels, the bitrate allocation between those + two channels changes accordingly to each channel information */ + OMX_AUDIO_ChannelModeJointStereo, /**< mode that takes advantage of what is common between + 2 channels for higher compression gain */ + OMX_AUDIO_ChannelModeDual, /**< 2 mono-channels, each channel is encoded with half + the bitrate of the overall bitrate */ + OMX_AUDIO_ChannelModeMono, /**< Mono channel mode */ + OMX_AUDIO_ChannelModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_ChannelModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_ChannelModeMax = 0x7FFFFFFF +} OMX_AUDIO_CHANNELMODETYPE; + + +typedef enum OMX_AUDIO_MP3STREAMFORMATTYPE { + OMX_AUDIO_MP3StreamFormatMP1Layer3 = 0, /**< MP3 Audio MPEG 1 Layer 3 Stream format */ + OMX_AUDIO_MP3StreamFormatMP2Layer3, /**< MP3 Audio MPEG 2 Layer 3 Stream format */ + OMX_AUDIO_MP3StreamFormatMP2_5Layer3, /**< MP3 Audio MPEG2.5 Layer 3 Stream format */ + OMX_AUDIO_MP3StreamFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_MP3StreamFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_MP3StreamFormatMax = 0x7FFFFFFF +} OMX_AUDIO_MP3STREAMFORMATTYPE; + +/** MP3 params */ +typedef struct OMX_AUDIO_PARAM_MP3TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable + rate or unknown bit rates */ + OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ + OMX_U32 nAudioBandWidth; /**< Audio band width (in Hz) to which an encoder should + limit the audio signal. Use 0 to let encoder decide */ + OMX_AUDIO_CHANNELMODETYPE eChannelMode; /**< Channel mode enumeration */ + OMX_AUDIO_MP3STREAMFORMATTYPE eFormat; /**< MP3 stream format */ +} OMX_AUDIO_PARAM_MP3TYPE; + + +typedef enum OMX_AUDIO_AACSTREAMFORMATTYPE { + OMX_AUDIO_AACStreamFormatMP2ADTS = 0, /**< AAC Audio Data Transport Stream 2 format */ + OMX_AUDIO_AACStreamFormatMP4ADTS, /**< AAC Audio Data Transport Stream 4 format */ + OMX_AUDIO_AACStreamFormatMP4LOAS, /**< AAC Low Overhead Audio Stream format */ + OMX_AUDIO_AACStreamFormatMP4LATM, /**< AAC Low overhead Audio Transport Multiplex */ + OMX_AUDIO_AACStreamFormatADIF, /**< AAC Audio Data Interchange Format */ + OMX_AUDIO_AACStreamFormatMP4FF, /**< AAC inside MPEG-4/ISO File Format */ + OMX_AUDIO_AACStreamFormatRAW, /**< AAC Raw Format */ + OMX_AUDIO_AACStreamFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_AACStreamFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_AACStreamFormatMax = 0x7FFFFFFF +} OMX_AUDIO_AACSTREAMFORMATTYPE; + + +/** AAC mode type. Note that the term profile is used with the MPEG-2 + * standard and the term object type and profile is used with MPEG-4 */ +typedef enum OMX_AUDIO_AACPROFILETYPE{ + OMX_AUDIO_AACObjectNull = 0, /**< Null, not used */ + OMX_AUDIO_AACObjectMain = 1, /**< AAC Main object */ + OMX_AUDIO_AACObjectLC, /**< AAC Low Complexity object (AAC profile) */ + OMX_AUDIO_AACObjectSSR, /**< AAC Scalable Sample Rate object */ + OMX_AUDIO_AACObjectLTP, /**< AAC Long Term Prediction object */ + OMX_AUDIO_AACObjectHE, /**< AAC High Efficiency (object type SBR, HE-AAC profile) */ + OMX_AUDIO_AACObjectScalable, /**< AAC Scalable object */ + OMX_AUDIO_AACObjectERLC = 17, /**< ER AAC Low Complexity object (Error Resilient AAC-LC) */ + OMX_AUDIO_AACObjectLD = 23, /**< AAC Low Delay object (Error Resilient) */ + OMX_AUDIO_AACObjectHE_PS = 29, /**< AAC High Efficiency with Parametric Stereo coding (HE-AAC v2, object type PS) */ + OMX_AUDIO_AACObjectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_AACObjectVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_AACObjectMax = 0x7FFFFFFF +} OMX_AUDIO_AACPROFILETYPE; + + +/** AAC tool usage (for nAACtools in OMX_AUDIO_PARAM_AACPROFILETYPE). + * Required for encoder configuration and optional as decoder info output. + * For MP3, OMX_AUDIO_CHANNELMODETYPE is sufficient. */ +#define OMX_AUDIO_AACToolNone 0x00000000 /**< no AAC tools allowed (encoder config) or active (decoder info output) */ +#define OMX_AUDIO_AACToolMS 0x00000001 /**< MS: Mid/side joint coding tool allowed or active */ +#define OMX_AUDIO_AACToolIS 0x00000002 /**< IS: Intensity stereo tool allowed or active */ +#define OMX_AUDIO_AACToolTNS 0x00000004 /**< TNS: Temporal Noise Shaping tool allowed or active */ +#define OMX_AUDIO_AACToolPNS 0x00000008 /**< PNS: MPEG-4 Perceptual Noise substitution tool allowed or active */ +#define OMX_AUDIO_AACToolLTP 0x00000010 /**< LTP: MPEG-4 Long Term Prediction tool allowed or active */ +#define OMX_AUDIO_AACToolAll 0x7FFFFFFF /**< all AAC tools allowed or active (*/ + +/** MPEG-4 AAC error resilience (ER) tool usage (for nAACERtools in OMX_AUDIO_PARAM_AACPROFILETYPE). + * Required for ER encoder configuration and optional as decoder info output */ +#define OMX_AUDIO_AACERNone 0x00000000 /**< no AAC ER tools allowed/used */ +#define OMX_AUDIO_AACERVCB11 0x00000001 /**< VCB11: Virtual Code Books for AAC section data */ +#define OMX_AUDIO_AACERRVLC 0x00000002 /**< RVLC: Reversible Variable Length Coding */ +#define OMX_AUDIO_AACERHCR 0x00000004 /**< HCR: Huffman Codeword Reordering */ +#define OMX_AUDIO_AACERAll 0x7FFFFFFF /**< all AAC ER tools allowed/used */ + + +/** AAC params */ +typedef struct OMX_AUDIO_PARAM_AACPROFILETYPE { + OMX_U32 nSize; /**< Size of this structure, in Bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ + OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable + rate or unknown bit rates */ + OMX_U32 nAudioBandWidth; /**< Audio band width (in Hz) to which an encoder should + limit the audio signal. Use 0 to let encoder decide */ + OMX_U32 nFrameLength; /**< Frame length (in audio samples per channel) of the codec. + Can be 1024 or 960 (AAC-LC), 2048 (HE-AAC), 480 or 512 (AAC-LD). + Use 0 to let encoder decide */ + OMX_U32 nAACtools; /**< AAC tool usage */ + OMX_U32 nAACERtools; /**< MPEG-4 AAC error resilience tool usage */ + OMX_AUDIO_AACPROFILETYPE eAACProfile; /**< AAC profile enumeration */ + OMX_AUDIO_AACSTREAMFORMATTYPE eAACStreamFormat; /**< AAC stream format enumeration */ + OMX_AUDIO_CHANNELMODETYPE eChannelMode; /**< Channel mode enumeration */ +} OMX_AUDIO_PARAM_AACPROFILETYPE; + + +/** VORBIS params */ +typedef struct OMX_AUDIO_PARAM_VORBISTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nBitRate; /**< Bit rate of the encoded data data. Use 0 for variable + rate or unknown bit rates. Encoding is set to the + bitrate closest to specified value (in bps) */ + OMX_U32 nMinBitRate; /**< Sets minimum bitrate (in bps). */ + OMX_U32 nMaxBitRate; /**< Sets maximum bitrate (in bps). */ + + OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ + OMX_U32 nAudioBandWidth; /**< Audio band width (in Hz) to which an encoder should + limit the audio signal. Use 0 to let encoder decide */ + OMX_S32 nQuality; /**< Sets encoding quality to n, between -1 (low) and 10 (high). + In the default mode of operation, teh quality level is 3. + Normal quality range is 0 - 10. */ + OMX_BOOL bManaged; /**< Set bitrate management mode. This turns off the + normal VBR encoding, but allows hard or soft bitrate + constraints to be enforced by the encoder. This mode can + be slower, and may also be lower quality. It is + primarily useful for streaming. */ + OMX_BOOL bDownmix; /**< Downmix input from stereo to mono (has no effect on + non-stereo streams). Useful for lower-bitrate encoding. */ +} OMX_AUDIO_PARAM_VORBISTYPE; + + +/** WMA Version */ +typedef enum OMX_AUDIO_WMAFORMATTYPE { + OMX_AUDIO_WMAFormatUnused = 0, /**< format unused or unknown */ + OMX_AUDIO_WMAFormat7, /**< Windows Media Audio format 7 */ + OMX_AUDIO_WMAFormat8, /**< Windows Media Audio format 8 */ + OMX_AUDIO_WMAFormat9, /**< Windows Media Audio format 9 */ + OMX_AUDIO_WMAFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_WMAFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_WMAFormatMax = 0x7FFFFFFF +} OMX_AUDIO_WMAFORMATTYPE; + + +/** WMA Profile */ +typedef enum OMX_AUDIO_WMAPROFILETYPE { + OMX_AUDIO_WMAProfileUnused = 0, /**< profile unused or unknown */ + OMX_AUDIO_WMAProfileL1, /**< Windows Media audio version 9 profile L1 */ + OMX_AUDIO_WMAProfileL2, /**< Windows Media audio version 9 profile L2 */ + OMX_AUDIO_WMAProfileL3, /**< Windows Media audio version 9 profile L3 */ + OMX_AUDIO_WMAProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_WMAProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_WMAProfileMax = 0x7FFFFFFF +} OMX_AUDIO_WMAPROFILETYPE; + + +/** WMA params */ +typedef struct OMX_AUDIO_PARAM_WMATYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U16 nChannels; /**< Number of channels */ + OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable + rate or unknown bit rates */ + OMX_AUDIO_WMAFORMATTYPE eFormat; /**< Version of WMA stream / data */ + OMX_AUDIO_WMAPROFILETYPE eProfile; /**< Profile of WMA stream / data */ + OMX_U32 nSamplingRate; /**< Sampling rate of the source data */ + OMX_U16 nBlockAlign; /**< is the block alignment, or block size, in bytes of the audio codec */ + OMX_U16 nEncodeOptions; /**< WMA Type-specific data */ + OMX_U32 nSuperBlockAlign; /**< WMA Type-specific data */ +} OMX_AUDIO_PARAM_WMATYPE; + +/** + * RealAudio format + */ +typedef enum OMX_AUDIO_RAFORMATTYPE { + OMX_AUDIO_RAFormatUnused = 0, /**< Format unused or unknown */ + OMX_AUDIO_RA8, /**< RealAudio 8 codec */ + OMX_AUDIO_RA9, /**< RealAudio 9 codec */ + OMX_AUDIO_RA10_AAC, /**< MPEG-4 AAC codec for bitrates of more than 128kbps */ + OMX_AUDIO_RA10_CODEC, /**< RealAudio codec for bitrates less than 128 kbps */ + OMX_AUDIO_RA10_LOSSLESS, /**< RealAudio Lossless */ + OMX_AUDIO_RA10_MULTICHANNEL, /**< RealAudio Multichannel */ + OMX_AUDIO_RA10_VOICE, /**< RealAudio Voice for bitrates below 15 kbps */ + OMX_AUDIO_RAFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_RAFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_RAFormatMax = 0x7FFFFFFF +} OMX_AUDIO_RAFORMATTYPE; + +/** RA (Real Audio) params */ +typedef struct OMX_AUDIO_PARAM_RATYPE { + OMX_U32 nSize; /**< Size of this structure, in Bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nSamplingRate; /**< is the sampling rate of the source data */ + OMX_U32 nBitsPerFrame; /**< is the value for bits per frame */ + OMX_U32 nSamplePerFrame; /**< is the value for samples per frame */ + OMX_U32 nCouplingQuantBits; /**< is the number of coupling quantization bits in the stream */ + OMX_U32 nCouplingStartRegion; /**< is the coupling start region in the stream */ + OMX_U32 nNumRegions; /**< is the number of regions value */ + OMX_AUDIO_RAFORMATTYPE eFormat; /**< is the RealAudio audio format */ +} OMX_AUDIO_PARAM_RATYPE; + + +/** SBC Allocation Method Type */ +typedef enum OMX_AUDIO_SBCALLOCMETHODTYPE { + OMX_AUDIO_SBCAllocMethodLoudness, /**< Loudness allocation method */ + OMX_AUDIO_SBCAllocMethodSNR, /**< SNR allocation method */ + OMX_AUDIO_SBCAllocMethodKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_SBCAllocMethodVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_SBCAllocMethodMax = 0x7FFFFFFF +} OMX_AUDIO_SBCALLOCMETHODTYPE; + + +/** SBC params */ +typedef struct OMX_AUDIO_PARAM_SBCTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable + rate or unknown bit rates */ + OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ + OMX_U32 nBlocks; /**< Number of blocks */ + OMX_U32 nSubbands; /**< Number of subbands */ + OMX_U32 nBitPool; /**< Bitpool value */ + OMX_BOOL bEnableBitrate; /**< Use bitrate value instead of bitpool */ + OMX_AUDIO_CHANNELMODETYPE eChannelMode; /**< Channel mode enumeration */ + OMX_AUDIO_SBCALLOCMETHODTYPE eSBCAllocType; /**< SBC Allocation method type */ +} OMX_AUDIO_PARAM_SBCTYPE; + + +/** ADPCM stream format parameters */ +typedef struct OMX_AUDIO_PARAM_ADPCMTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_U32 nBitsPerSample; /**< Number of bits in each sample */ + OMX_U32 nSampleRate; /**< Sampling rate of the source data. Use 0 for + variable or unknown sampling rate. */ +} OMX_AUDIO_PARAM_ADPCMTYPE; + + +/** G723 rate */ +typedef enum OMX_AUDIO_G723RATE { + OMX_AUDIO_G723ModeUnused = 0, /**< AMRNB Mode unused / unknown */ + OMX_AUDIO_G723ModeLow, /**< 5300 bps */ + OMX_AUDIO_G723ModeHigh, /**< 6300 bps */ + OMX_AUDIO_G723ModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_G723ModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_G723ModeMax = 0x7FFFFFFF +} OMX_AUDIO_G723RATE; + + +/** G723 - Sample rate must be 8 KHz */ +typedef struct OMX_AUDIO_PARAM_G723TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_AUDIO_G723RATE eBitRate; /**< todo: Should this be moved to a config? */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ + OMX_BOOL bPostFilter; /**< Enable Post Filter */ +} OMX_AUDIO_PARAM_G723TYPE; + + +/** ITU G726 (ADPCM) rate */ +typedef enum OMX_AUDIO_G726MODE { + OMX_AUDIO_G726ModeUnused = 0, /**< G726 Mode unused / unknown */ + OMX_AUDIO_G726Mode16, /**< 16 kbps */ + OMX_AUDIO_G726Mode24, /**< 24 kbps */ + OMX_AUDIO_G726Mode32, /**< 32 kbps, most common rate, also G721 */ + OMX_AUDIO_G726Mode40, /**< 40 kbps */ + OMX_AUDIO_G726ModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_G726ModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_G726ModeMax = 0x7FFFFFFF +} OMX_AUDIO_G726MODE; + + +/** G.726 stream format parameters - must be at 8KHz */ +typedef struct OMX_AUDIO_PARAM_G726TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_AUDIO_G726MODE eG726Mode; +} OMX_AUDIO_PARAM_G726TYPE; + + +/** G729 coder type */ +typedef enum OMX_AUDIO_G729TYPE { + OMX_AUDIO_G729 = 0, /**< ITU G.729 encoded data */ + OMX_AUDIO_G729A, /**< ITU G.729 annex A encoded data */ + OMX_AUDIO_G729B, /**< ITU G.729 with annex B encoded data */ + OMX_AUDIO_G729AB, /**< ITU G.729 annexes A and B encoded data */ + OMX_AUDIO_G729KhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_G729VendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_G729Max = 0x7FFFFFFF +} OMX_AUDIO_G729TYPE; + + +/** G729 stream format parameters - fixed 6KHz sample rate */ +typedef struct OMX_AUDIO_PARAM_G729TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_AUDIO_G729TYPE eBitType; +} OMX_AUDIO_PARAM_G729TYPE; + + +/** AMR Frame format */ +typedef enum OMX_AUDIO_AMRFRAMEFORMATTYPE { + OMX_AUDIO_AMRFrameFormatConformance = 0, /**< Frame Format is AMR Conformance + (Standard) Format */ + OMX_AUDIO_AMRFrameFormatIF1, /**< Frame Format is AMR Interface + Format 1 */ + OMX_AUDIO_AMRFrameFormatIF2, /**< Frame Format is AMR Interface + Format 2*/ + OMX_AUDIO_AMRFrameFormatFSF, /**< Frame Format is AMR File Storage + Format */ + OMX_AUDIO_AMRFrameFormatRTPPayload, /**< Frame Format is AMR Real-Time + Transport Protocol Payload Format */ + OMX_AUDIO_AMRFrameFormatITU, /**< Frame Format is ITU Format (added at Motorola request) */ + OMX_AUDIO_AMRFrameFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_AMRFrameFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_AMRFrameFormatMax = 0x7FFFFFFF +} OMX_AUDIO_AMRFRAMEFORMATTYPE; + + +/** AMR band mode */ +typedef enum OMX_AUDIO_AMRBANDMODETYPE { + OMX_AUDIO_AMRBandModeUnused = 0, /**< AMRNB Mode unused / unknown */ + OMX_AUDIO_AMRBandModeNB0, /**< AMRNB Mode 0 = 4750 bps */ + OMX_AUDIO_AMRBandModeNB1, /**< AMRNB Mode 1 = 5150 bps */ + OMX_AUDIO_AMRBandModeNB2, /**< AMRNB Mode 2 = 5900 bps */ + OMX_AUDIO_AMRBandModeNB3, /**< AMRNB Mode 3 = 6700 bps */ + OMX_AUDIO_AMRBandModeNB4, /**< AMRNB Mode 4 = 7400 bps */ + OMX_AUDIO_AMRBandModeNB5, /**< AMRNB Mode 5 = 7950 bps */ + OMX_AUDIO_AMRBandModeNB6, /**< AMRNB Mode 6 = 10200 bps */ + OMX_AUDIO_AMRBandModeNB7, /**< AMRNB Mode 7 = 12200 bps */ + OMX_AUDIO_AMRBandModeWB0, /**< AMRWB Mode 0 = 6600 bps */ + OMX_AUDIO_AMRBandModeWB1, /**< AMRWB Mode 1 = 8850 bps */ + OMX_AUDIO_AMRBandModeWB2, /**< AMRWB Mode 2 = 12650 bps */ + OMX_AUDIO_AMRBandModeWB3, /**< AMRWB Mode 3 = 14250 bps */ + OMX_AUDIO_AMRBandModeWB4, /**< AMRWB Mode 4 = 15850 bps */ + OMX_AUDIO_AMRBandModeWB5, /**< AMRWB Mode 5 = 18250 bps */ + OMX_AUDIO_AMRBandModeWB6, /**< AMRWB Mode 6 = 19850 bps */ + OMX_AUDIO_AMRBandModeWB7, /**< AMRWB Mode 7 = 23050 bps */ + OMX_AUDIO_AMRBandModeWB8, /**< AMRWB Mode 8 = 23850 bps */ + OMX_AUDIO_AMRBandModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_AMRBandModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_AMRBandModeMax = 0x7FFFFFFF +} OMX_AUDIO_AMRBANDMODETYPE; + + +/** AMR Discontinuous Transmission mode */ +typedef enum OMX_AUDIO_AMRDTXMODETYPE { + OMX_AUDIO_AMRDTXModeOff = 0, /**< AMR Discontinuous Transmission Mode is disabled */ + OMX_AUDIO_AMRDTXModeOnVAD1, /**< AMR Discontinuous Transmission Mode using + Voice Activity Detector 1 (VAD1) is enabled */ + OMX_AUDIO_AMRDTXModeOnVAD2, /**< AMR Discontinuous Transmission Mode using + Voice Activity Detector 2 (VAD2) is enabled */ + OMX_AUDIO_AMRDTXModeOnAuto, /**< The codec will automatically select between + Off, VAD1 or VAD2 modes */ + + OMX_AUDIO_AMRDTXasEFR, /**< DTX as EFR instead of AMR standard (3GPP 26.101, frame type =8,9,10) */ + + OMX_AUDIO_AMRDTXModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_AMRDTXModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_AMRDTXModeMax = 0x7FFFFFFF +} OMX_AUDIO_AMRDTXMODETYPE; + + +/** AMR params */ +typedef struct OMX_AUDIO_PARAM_AMRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels */ + OMX_U32 nBitRate; /**< Bit rate read only field */ + OMX_AUDIO_AMRBANDMODETYPE eAMRBandMode; /**< AMR Band Mode enumeration */ + OMX_AUDIO_AMRDTXMODETYPE eAMRDTXMode; /**< AMR DTX Mode enumeration */ + OMX_AUDIO_AMRFRAMEFORMATTYPE eAMRFrameFormat; /**< AMR frame format enumeration */ +} OMX_AUDIO_PARAM_AMRTYPE; + + +/** GSM_FR (ETSI 06.10, 3GPP 46.010) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_GSMFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_GSMFRTYPE; + + +/** GSM-HR (ETSI 06.20, 3GPP 46.020) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_GSMHRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_GSMHRTYPE; + + +/** GSM-EFR (ETSI 06.60, 3GPP 46.060) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_GSMEFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_GSMEFRTYPE; + + +/** TDMA FR (TIA/EIA-136-420, VSELP 7.95kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_TDMAFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_TDMAFRTYPE; + + +/** TDMA EFR (TIA/EIA-136-410, ACELP 7.4kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_TDMAEFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_TDMAEFRTYPE; + + +/** PDC FR ( RCR-27, VSELP 6.7kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_PDCFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_PDCFRTYPE; + + +/** PDC EFR ( RCR-27, ACELP 6.7kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_PDCEFRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_PDCEFRTYPE; + +/** PDC HR ( RCR-27, PSI-CELP 3.45kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_PDCHRTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_BOOL bDTX; /**< Enable Discontinuous Transmisssion */ + OMX_BOOL bHiPassFilter; /**< Enable High Pass Filter */ +} OMX_AUDIO_PARAM_PDCHRTYPE; + + +/** CDMA Rate types */ +typedef enum OMX_AUDIO_CDMARATETYPE { + OMX_AUDIO_CDMARateBlank = 0, /**< CDMA encoded frame is blank */ + OMX_AUDIO_CDMARateFull, /**< CDMA encoded frame in full rate */ + OMX_AUDIO_CDMARateHalf, /**< CDMA encoded frame in half rate */ + OMX_AUDIO_CDMARateQuarter, /**< CDMA encoded frame in quarter rate */ + OMX_AUDIO_CDMARateEighth, /**< CDMA encoded frame in eighth rate (DTX)*/ + OMX_AUDIO_CDMARateErasure, /**< CDMA erasure frame */ + OMX_AUDIO_CDMARateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_CDMARateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_CDMARateMax = 0x7FFFFFFF +} OMX_AUDIO_CDMARATETYPE; + + +/** QCELP8 (TIA/EIA-96, up to 8kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_QCELP8TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_U32 nBitRate; /**< Bit rate of the input data. Use 0 for variable + rate or unknown bit rates */ + OMX_AUDIO_CDMARATETYPE eCDMARate; /**< Frame rate */ + OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 */ + OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 */ +} OMX_AUDIO_PARAM_QCELP8TYPE; + + +/** QCELP13 ( CDMA, EIA/TIA-733, 13.3kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_QCELP13TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_AUDIO_CDMARATETYPE eCDMARate; /**< Frame rate */ + OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 */ + OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 */ +} OMX_AUDIO_PARAM_QCELP13TYPE; + + +/** EVRC ( CDMA, EIA/TIA-127, RCELP up to 8.55kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_EVRCTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_AUDIO_CDMARATETYPE eCDMARate; /**< actual Frame rate */ + OMX_BOOL bRATE_REDUCon; /**< RATE_REDUCtion is requested for this frame */ + OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 */ + OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 */ + OMX_BOOL bHiPassFilter; /**< Enable encoder's High Pass Filter */ + OMX_BOOL bNoiseSuppressor; /**< Enable encoder's noise suppressor pre-processing */ + OMX_BOOL bPostFilter; /**< Enable decoder's post Filter */ +} OMX_AUDIO_PARAM_EVRCTYPE; + + +/** SMV ( up to 8.55kbps coder) stream format parameters */ +typedef struct OMX_AUDIO_PARAM_SMVTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannels; /**< Number of channels in the data stream (not + necessarily the same as the number of channels + to be rendered. */ + OMX_AUDIO_CDMARATETYPE eCDMARate; /**< Frame rate */ + OMX_BOOL bRATE_REDUCon; /**< RATE_REDUCtion is requested for this frame */ + OMX_U32 nMinBitRate; /**< minmal rate for the encoder = 1,2,3,4, default = 1 ??*/ + OMX_U32 nMaxBitRate; /**< maximal rate for the encoder = 1,2,3,4, default = 4 ??*/ + OMX_BOOL bHiPassFilter; /**< Enable encoder's High Pass Filter ??*/ + OMX_BOOL bNoiseSuppressor; /**< Enable encoder's noise suppressor pre-processing */ + OMX_BOOL bPostFilter; /**< Enable decoder's post Filter ??*/ +} OMX_AUDIO_PARAM_SMVTYPE; + + +/** MIDI Format + * @ingroup midi + */ +typedef enum OMX_AUDIO_MIDIFORMATTYPE +{ + OMX_AUDIO_MIDIFormatUnknown = 0, /**< MIDI Format unknown or don't care */ + OMX_AUDIO_MIDIFormatSMF0, /**< Standard MIDI File Type 0 */ + OMX_AUDIO_MIDIFormatSMF1, /**< Standard MIDI File Type 1 */ + OMX_AUDIO_MIDIFormatSMF2, /**< Standard MIDI File Type 2 */ + OMX_AUDIO_MIDIFormatSPMIDI, /**< SP-MIDI */ + OMX_AUDIO_MIDIFormatXMF0, /**< eXtensible Music Format type 0 */ + OMX_AUDIO_MIDIFormatXMF1, /**< eXtensible Music Format type 1 */ + OMX_AUDIO_MIDIFormatMobileXMF, /**< Mobile XMF (eXtensible Music Format type 2) */ + OMX_AUDIO_MIDIFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_MIDIFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_MIDIFormatMax = 0x7FFFFFFF +} OMX_AUDIO_MIDIFORMATTYPE; + + +/** MIDI params + * @ingroup midi + */ +typedef struct OMX_AUDIO_PARAM_MIDITYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nFileSize; /**< size of the MIDI file in bytes, where the entire + MIDI file passed in, otherwise if 0x0, the MIDI data + is merged and streamed (instead of passed as an + entire MIDI file) */ + OMX_BU32 sMaxPolyphony; /**< Specifies the maximum simultaneous polyphonic + voices. A value of zero indicates that the default + polyphony of the device is used */ + OMX_BOOL bLoadDefaultSound; /**< Whether to load default sound + bank at initialization */ + OMX_AUDIO_MIDIFORMATTYPE eMidiFormat; /**< Version of the MIDI file */ +} OMX_AUDIO_PARAM_MIDITYPE; + + +/** Type of the MIDI sound bank + * @ingroup midi + */ +typedef enum OMX_AUDIO_MIDISOUNDBANKTYPE { + OMX_AUDIO_MIDISoundBankUnused = 0, /**< unused/unknown soundbank type */ + OMX_AUDIO_MIDISoundBankDLS1, /**< DLS version 1 */ + OMX_AUDIO_MIDISoundBankDLS2, /**< DLS version 2 */ + OMX_AUDIO_MIDISoundBankMobileDLSBase, /**< Mobile DLS, using the base functionality */ + OMX_AUDIO_MIDISoundBankMobileDLSPlusOptions, /**< Mobile DLS, using the specification-defined optional feature set */ + OMX_AUDIO_MIDISoundBankKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_MIDISoundBankVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_MIDISoundBankMax = 0x7FFFFFFF +} OMX_AUDIO_MIDISOUNDBANKTYPE; + + +/** Bank Layout describes how bank MSB & LSB are used in the DLS instrument definitions sound bank + * @ingroup midi + */ +typedef enum OMX_AUDIO_MIDISOUNDBANKLAYOUTTYPE { + OMX_AUDIO_MIDISoundBankLayoutUnused = 0, /**< unused/unknown soundbank type */ + OMX_AUDIO_MIDISoundBankLayoutGM, /**< GS layout (based on bank MSB 0x00) */ + OMX_AUDIO_MIDISoundBankLayoutGM2, /**< General MIDI 2 layout (using MSB 0x78/0x79, LSB 0x00) */ + OMX_AUDIO_MIDISoundBankLayoutUser, /**< Does not conform to any bank numbering standards */ + OMX_AUDIO_MIDISoundBankLayoutKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_MIDISoundBankLayoutVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_MIDISoundBankLayoutMax = 0x7FFFFFFF +} OMX_AUDIO_MIDISOUNDBANKLAYOUTTYPE; + + +/** MIDI params to load/unload user soundbank + * @ingroup midi + */ +typedef struct OMX_AUDIO_PARAM_MIDILOADUSERSOUNDTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nDLSIndex; /**< DLS file index to be loaded */ + OMX_U32 nDLSSize; /**< Size in bytes */ + OMX_PTR pDLSData; /**< Pointer to DLS file data */ + OMX_AUDIO_MIDISOUNDBANKTYPE eMidiSoundBank; /**< Midi sound bank type enumeration */ + OMX_AUDIO_MIDISOUNDBANKLAYOUTTYPE eMidiSoundBankLayout; /**< Midi sound bank layout enumeration */ +} OMX_AUDIO_PARAM_MIDILOADUSERSOUNDTYPE; + + +/** Structure for Live MIDI events and MIP messages. + * (MIP = Maximum Instantaneous Polyphony; part of the SP-MIDI standard.) + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDIIMMEDIATEEVENTTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_U32 nMidiEventSize; /**< Size of immediate MIDI events or MIP message in bytes */ + OMX_U8 nMidiEvents[1]; /**< MIDI event array to be rendered immediately, or an + array for the MIP message buffer, where the size is + indicated by nMidiEventSize */ +} OMX_AUDIO_CONFIG_MIDIIMMEDIATEEVENTTYPE; + + +/** MIDI sound bank/ program pair in a given channel + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDISOUNDBANKPROGRAMTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_U32 nChannel; /**< Valid channel values range from 1 to 16 */ + OMX_U16 nIDProgram; /**< Valid program ID range is 1 to 128 */ + OMX_U16 nIDSoundBank; /**< Sound bank ID */ + OMX_U32 nUserSoundBankIndex;/**< User soundbank index, easier to access soundbanks + by index if multiple banks are present */ +} OMX_AUDIO_CONFIG_MIDISOUNDBANKPROGRAMTYPE; + + +/** MIDI control + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDICONTROLTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BS32 sPitchTransposition; /**< Pitch transposition in semitones, stored as Q22.10 + format based on JAVA MMAPI (JSR-135) requirement */ + OMX_BU32 sPlayBackRate; /**< Relative playback rate, stored as Q14.17 fixed-point + number based on JSR-135 requirement */ + OMX_BU32 sTempo ; /**< Tempo in beats per minute (BPM), stored as Q22.10 + fixed-point number based on JSR-135 requirement */ + OMX_U32 nMaxPolyphony; /**< Specifies the maximum simultaneous polyphonic + voices. A value of zero indicates that the default + polyphony of the device is used */ + OMX_U32 nNumRepeat; /**< Number of times to repeat playback */ + OMX_U32 nStopTime; /**< Time in milliseconds to indicate when playback + will stop automatically. Set to zero if not used */ + OMX_U16 nChannelMuteMask; /**< 16 bit mask for channel mute status */ + OMX_U16 nChannelSoloMask; /**< 16 bit mask for channel solo status */ + OMX_U32 nTrack0031MuteMask; /**< 32 bit mask for track mute status. Note: This is for tracks 0-31 */ + OMX_U32 nTrack3263MuteMask; /**< 32 bit mask for track mute status. Note: This is for tracks 32-63 */ + OMX_U32 nTrack0031SoloMask; /**< 32 bit mask for track solo status. Note: This is for tracks 0-31 */ + OMX_U32 nTrack3263SoloMask; /**< 32 bit mask for track solo status. Note: This is for tracks 32-63 */ + +} OMX_AUDIO_CONFIG_MIDICONTROLTYPE; + + +/** MIDI Playback States + * @ingroup midi + */ +typedef enum OMX_AUDIO_MIDIPLAYBACKSTATETYPE { + OMX_AUDIO_MIDIPlayBackStateUnknown = 0, /**< Unknown state or state does not map to + other defined states */ + OMX_AUDIO_MIDIPlayBackStateClosedEngaged, /**< No MIDI resource is currently open. + The MIDI engine is currently processing + MIDI events. */ + OMX_AUDIO_MIDIPlayBackStateParsing, /**< A MIDI resource is open and is being + primed. The MIDI engine is currently + processing MIDI events. */ + OMX_AUDIO_MIDIPlayBackStateOpenEngaged, /**< A MIDI resource is open and primed but + not playing. The MIDI engine is currently + processing MIDI events. The transition to + this state is only possible from the + OMX_AUDIO_MIDIPlayBackStatePlaying state, + when the 'playback head' reaches the end + of media data or the playback stops due + to stop time set.*/ + OMX_AUDIO_MIDIPlayBackStatePlaying, /**< A MIDI resource is open and currently + playing. The MIDI engine is currently + processing MIDI events.*/ + OMX_AUDIO_MIDIPlayBackStatePlayingPartially, /**< Best-effort playback due to SP-MIDI/DLS + resource constraints */ + OMX_AUDIO_MIDIPlayBackStatePlayingSilently, /**< Due to system resource constraints and + SP-MIDI content constraints, there is + no audible MIDI content during playback + currently. The situation may change if + resources are freed later.*/ + OMX_AUDIO_MIDIPlayBackStateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_MIDIPlayBackStateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_MIDIPlayBackStateMax = 0x7FFFFFFF +} OMX_AUDIO_MIDIPLAYBACKSTATETYPE; + + +/** MIDI status + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDISTATUSTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U16 nNumTracks; /**< Number of MIDI tracks in the file, read only field. + NOTE: May not return a meaningful value until the entire + file is parsed and buffered. */ + OMX_U32 nDuration; /**< The length of the currently open MIDI resource + in milliseconds. NOTE: May not return a meaningful value + until the entire file is parsed and buffered. */ + OMX_U32 nPosition; /**< Current Position of the MIDI resource being played + in milliseconds */ + OMX_BOOL bVibra; /**< Does Vibra track exist? NOTE: May not return a meaningful + value until the entire file is parsed and buffered. */ + OMX_U32 nNumMetaEvents; /**< Total number of MIDI Meta Events in the currently + open MIDI resource. NOTE: May not return a meaningful value + until the entire file is parsed and buffered. */ + OMX_U32 nNumActiveVoices; /**< Number of active voices in the currently playing + MIDI resource. NOTE: May not return a meaningful value until + the entire file is parsed and buffered. */ + OMX_AUDIO_MIDIPLAYBACKSTATETYPE eMIDIPlayBackState; /**< MIDI playback state enumeration, read only field */ +} OMX_AUDIO_CONFIG_MIDISTATUSTYPE; + + +/** MIDI Meta Event structure one per Meta Event. + * MIDI Meta Events are like audio metadata, except that they are interspersed + * with the MIDI content throughout the file and are not localized in the header. + * As such, it is necessary to retrieve information about these Meta Events from + * the engine, as it encounters these Meta Events within the MIDI content. + * For example, SMF files can have up to 14 types of MIDI Meta Events (copyright, + * author, default tempo, etc.) scattered throughout the file. + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDIMETAEVENTTYPE{ + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nIndex; /**< Index of Meta Event */ + OMX_U8 nMetaEventType; /**< Meta Event Type, 7bits (i.e. 0 - 127) */ + OMX_U32 nMetaEventSize; /**< size of the Meta Event in bytes */ + OMX_U32 nTrack; /**< track number for the meta event */ + OMX_U32 nPosition; /**< Position of the meta-event in milliseconds */ +} OMX_AUDIO_CONFIG_MIDIMETAEVENTTYPE; + + +/** MIDI Meta Event Data structure - one per Meta Event. + * @ingroup midi + */ +typedef struct OMX_AUDIO_CONFIG_MIDIMETAEVENTDATATYPE{ + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nIndex; /**< Index of Meta Event */ + OMX_U32 nMetaEventSize; /**< size of the Meta Event in bytes */ + OMX_U8 nData[1]; /**< array of one or more bytes of meta data + as indicated by the nMetaEventSize field */ +} OMX_AUDIO_CONFIG__MIDIMETAEVENTDATATYPE; + + +/** Audio Volume adjustment for a port */ +typedef struct OMX_AUDIO_CONFIG_VOLUMETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port index indicating which port to + set. Select the input port to set + just that port's volume. Select the + output port to adjust the master + volume. */ + OMX_BOOL bLinear; /**< Is the volume to be set in linear (0.100) + or logarithmic scale (mB) */ + OMX_BS32 sVolume; /**< Volume linear setting in the 0..100 range, OR + Volume logarithmic setting for this port. The values + for volume are in mB (millibels = 1/100 dB) relative + to a gain of 1 (e.g. the output is the same as the + input level). Values are in mB from nMax + (maximum volume) to nMin mB (typically negative). + Since the volume is "voltage" + and not a "power", it takes a setting of + -600 mB to decrease the volume by 1/2. If + a component cannot accurately set the + volume to the requested value, it must + set the volume to the closest value BELOW + the requested value. When getting the + volume setting, the current actual volume + must be returned. */ +} OMX_AUDIO_CONFIG_VOLUMETYPE; + + +/** Audio Volume adjustment for a channel */ +typedef struct OMX_AUDIO_CONFIG_CHANNELVOLUMETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port index indicating which port to + set. Select the input port to set + just that port's volume. Select the + output port to adjust the master + volume. */ + OMX_U32 nChannel; /**< channel to select from 0 to N-1, + using OMX_ALL to apply volume settings + to all channels */ + OMX_BOOL bLinear; /**< Is the volume to be set in linear (0.100) or + logarithmic scale (mB) */ + OMX_BS32 sVolume; /**< Volume linear setting in the 0..100 range, OR + Volume logarithmic setting for this port. + The values for volume are in mB + (millibels = 1/100 dB) relative to a gain + of 1 (e.g. the output is the same as the + input level). Values are in mB from nMax + (maximum volume) to nMin mB (typically negative). + Since the volume is "voltage" + and not a "power", it takes a setting of + -600 mB to decrease the volume by 1/2. If + a component cannot accurately set the + volume to the requested value, it must + set the volume to the closest value BELOW + the requested value. When getting the + volume setting, the current actual volume + must be returned. */ + OMX_BOOL bIsMIDI; /**< TRUE if nChannel refers to a MIDI channel, + FALSE otherwise */ +} OMX_AUDIO_CONFIG_CHANNELVOLUMETYPE; + + +/** Audio balance setting */ +typedef struct OMX_AUDIO_CONFIG_BALANCETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port index indicating which port to + set. Select the input port to set + just that port's balance. Select the + output port to adjust the master + balance. */ + OMX_S32 nBalance; /**< balance setting for this port + (-100 to 100, where -100 indicates + all left, and no right */ +} OMX_AUDIO_CONFIG_BALANCETYPE; + + +/** Audio Port mute */ +typedef struct OMX_AUDIO_CONFIG_MUTETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port index indicating which port to + set. Select the input port to set + just that port's mute. Select the + output port to adjust the master + mute. */ + OMX_BOOL bMute; /**< Mute setting for this port */ +} OMX_AUDIO_CONFIG_MUTETYPE; + + +/** Audio Channel mute */ +typedef struct OMX_AUDIO_CONFIG_CHANNELMUTETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nChannel; /**< channel to select from 0 to N-1, + using OMX_ALL to apply mute settings + to all channels */ + OMX_BOOL bMute; /**< Mute setting for this channel */ + OMX_BOOL bIsMIDI; /**< TRUE if nChannel refers to a MIDI channel, + FALSE otherwise */ +} OMX_AUDIO_CONFIG_CHANNELMUTETYPE; + + + +/** Enable / Disable for loudness control, which boosts bass and to a + * smaller extent high end frequencies to compensate for hearing + * ability at the extreme ends of the audio spectrum + */ +typedef struct OMX_AUDIO_CONFIG_LOUDNESSTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bLoudness; /**< Enable/disable for loudness */ +} OMX_AUDIO_CONFIG_LOUDNESSTYPE; + + +/** Enable / Disable for bass, which controls low frequencies + */ +typedef struct OMX_AUDIO_CONFIG_BASSTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for bass control */ + OMX_S32 nBass; /**< bass setting for the port, as a + continuous value from -100 to 100 + (0 means no change in bass level)*/ +} OMX_AUDIO_CONFIG_BASSTYPE; + + +/** Enable / Disable for treble, which controls high frequencies tones + */ +typedef struct OMX_AUDIO_CONFIG_TREBLETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for treble control */ + OMX_S32 nTreble; /**< treble setting for the port, as a + continuous value from -100 to 100 + (0 means no change in treble level) */ +} OMX_AUDIO_CONFIG_TREBLETYPE; + + +/** An equalizer is typically used for two reasons: to compensate for an + * sub-optimal frequency response of a system to make it sound more natural + * or to create intentionally some unnatural coloring to the sound to create + * an effect. + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_EQUALIZERTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for equalizer */ + OMX_BU32 sBandIndex; /**< Band number to be set. Upper Limit is + N-1, where N is the number of bands, lower limit is 0 */ + OMX_BU32 sCenterFreq; /**< Center frequecies in Hz. This is a + read only element and is used to determine + the lower, center and upper frequency of + this band. */ + OMX_BS32 sBandLevel; /**< band level in millibels */ +} OMX_AUDIO_CONFIG_EQUALIZERTYPE; + + +/** Stereo widening mode type + * @ingroup effects + */ +typedef enum OMX_AUDIO_STEREOWIDENINGTYPE { + OMX_AUDIO_StereoWideningHeadphones, /**< Stereo widening for loudspeakers */ + OMX_AUDIO_StereoWideningLoudspeakers, /**< Stereo widening for closely spaced loudspeakers */ + OMX_AUDIO_StereoWideningKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_StereoWideningVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_StereoWideningMax = 0x7FFFFFFF +} OMX_AUDIO_STEREOWIDENINGTYPE; + + +/** Control for stereo widening, which is a special 2-channel + * case of the audio virtualizer effect. For example, for 5.1-channel + * output, it translates to virtual surround sound. + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_STEREOWIDENINGTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for stereo widening control */ + OMX_AUDIO_STEREOWIDENINGTYPE eWideningType; /**< Stereo widening algorithm type */ + OMX_U32 nStereoWidening; /**< stereo widening setting for the port, + as a continuous value from 0 to 100 */ +} OMX_AUDIO_CONFIG_STEREOWIDENINGTYPE; + + +/** The chorus effect (or ``choralizer'') is any signal processor which makes + * one sound source (such as a voice) sound like many such sources singing + * (or playing) in unison. Since performance in unison is never exact, chorus + * effects simulate this by making independently modified copies of the input + * signal. Modifications may include (1) delay, (2) frequency shift, and + * (3) amplitude modulation. + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_CHORUSTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for chorus */ + OMX_BU32 sDelay; /**< average delay in milliseconds */ + OMX_BU32 sModulationRate; /**< rate of modulation in millihertz */ + OMX_U32 nModulationDepth; /**< depth of modulation as a percentage of + delay (i.e. 0 to 100) */ + OMX_BU32 nFeedback; /**< Feedback from chorus output to input in percentage */ +} OMX_AUDIO_CONFIG_CHORUSTYPE; + + +/** Reverberation is part of the reflected sound that follows the early + * reflections. In a typical room, this consists of a dense succession of + * echoes whose energy decays exponentially. The reverberation effect structure + * as defined here includes both (early) reflections as well as (late) reverberations. + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_REVERBERATIONTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bEnable; /**< Enable/disable for reverberation control */ + OMX_BS32 sRoomLevel; /**< Intensity level for the whole room effect + (i.e. both early reflections and late + reverberation) in millibels */ + OMX_BS32 sRoomHighFreqLevel; /**< Attenuation at high frequencies + relative to the intensity at low + frequencies in millibels */ + OMX_BS32 sReflectionsLevel; /**< Intensity level of early reflections + (relative to room value), in millibels */ + OMX_BU32 sReflectionsDelay; /**< Delay time of the first reflection relative + to the direct path, in milliseconds */ + OMX_BS32 sReverbLevel; /**< Intensity level of late reverberation + relative to room level, in millibels */ + OMX_BU32 sReverbDelay; /**< Time delay from the first early reflection + to the beginning of the late reverberation + section, in milliseconds */ + OMX_BU32 sDecayTime; /**< Late reverberation decay time at low + frequencies, in milliseconds */ + OMX_BU32 nDecayHighFreqRatio; /**< Ratio of high frequency decay time relative + to low frequency decay time in percent */ + OMX_U32 nDensity; /**< Modal density in the late reverberation decay, + in percent (i.e. 0 - 100) */ + OMX_U32 nDiffusion; /**< Echo density in the late reverberation decay, + in percent (i.e. 0 - 100) */ + OMX_BU32 sReferenceHighFreq; /**< Reference high frequency in Hertz. This is + the frequency used as the reference for all + the high-frequency settings above */ + +} OMX_AUDIO_CONFIG_REVERBERATIONTYPE; + + +/** Possible settings for the Echo Cancelation structure to use + * @ingroup effects + */ +typedef enum OMX_AUDIO_ECHOCANTYPE { + OMX_AUDIO_EchoCanOff = 0, /**< Echo Cancellation is disabled */ + OMX_AUDIO_EchoCanNormal, /**< Echo Cancellation normal operation - + echo from plastics and face */ + OMX_AUDIO_EchoCanHFree, /**< Echo Cancellation optimized for + Hands Free operation */ + OMX_AUDIO_EchoCanCarKit, /**< Echo Cancellation optimized for + Car Kit (longer echo) */ + OMX_AUDIO_EchoCanKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_AUDIO_EchoCanVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_AUDIO_EchoCanMax = 0x7FFFFFFF +} OMX_AUDIO_ECHOCANTYPE; + + +/** Enable / Disable for echo cancelation, which removes undesired echo's + * from the audio + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_ECHOCANCELATIONTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_AUDIO_ECHOCANTYPE eEchoCancelation; /**< Echo cancelation settings */ +} OMX_AUDIO_CONFIG_ECHOCANCELATIONTYPE; + + +/** Enable / Disable for noise reduction, which undesired noise from + * the audio + * @ingroup effects + */ +typedef struct OMX_AUDIO_CONFIG_NOISEREDUCTIONTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BOOL bNoiseReduction; /**< Enable/disable for noise reduction */ +} OMX_AUDIO_CONFIG_NOISEREDUCTIONTYPE; + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ + diff --git a/openmax/include/khronos/OMX_Component.h b/openmax/include/khronos/OMX_Component.h new file mode 100644 index 0000000..d595640 --- /dev/null +++ b/openmax/include/khronos/OMX_Component.h @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_Component.h - OpenMax IL version 1.1.2 + * The OMX_Component header file contains the definitions used to define + * the public interface of a component. This header file is intended to + * be used by both the application and the component. + */ + +#ifndef OMX_Component_h +#define OMX_Component_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + + +/* Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include +#include +#include +#include + +/** @ingroup comp */ +typedef enum OMX_PORTDOMAINTYPE { + OMX_PortDomainAudio, + OMX_PortDomainVideo, + OMX_PortDomainImage, + OMX_PortDomainOther, + OMX_PortDomainKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_PortDomainVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_PortDomainMax = 0x7ffffff +} OMX_PORTDOMAINTYPE; + +/** @ingroup comp */ +typedef struct OMX_PARAM_PORTDEFINITIONTYPE { + OMX_U32 nSize; /**< Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port number the structure applies to */ + OMX_DIRTYPE eDir; /**< Direction (input or output) of this port */ + OMX_U32 nBufferCountActual; /**< The actual number of buffers allocated on this port */ + OMX_U32 nBufferCountMin; /**< The minimum number of buffers this port requires */ + OMX_U32 nBufferSize; /**< Size, in bytes, for buffers to be used for this channel */ + OMX_BOOL bEnabled; /**< Ports default to enabled and are enabled/disabled by + OMX_CommandPortEnable/OMX_CommandPortDisable. + When disabled a port is unpopulated. A disabled port + is not populated with buffers on a transition to IDLE. */ + OMX_BOOL bPopulated; /**< Port is populated with all of its buffers as indicated by + nBufferCountActual. A disabled port is always unpopulated. + An enabled port is populated on a transition to OMX_StateIdle + and unpopulated on a transition to loaded. */ + OMX_PORTDOMAINTYPE eDomain; /**< Domain of the port. Determines the contents of metadata below. */ + union { + OMX_AUDIO_PORTDEFINITIONTYPE audio; + OMX_VIDEO_PORTDEFINITIONTYPE video; + OMX_IMAGE_PORTDEFINITIONTYPE image; + OMX_OTHER_PORTDEFINITIONTYPE other; + } format; + OMX_BOOL bBuffersContiguous; + OMX_U32 nBufferAlignment; +} OMX_PARAM_PORTDEFINITIONTYPE; + +/** @ingroup comp */ +typedef struct OMX_PARAM_U32TYPE { + OMX_U32 nSize; /**< Size of this structure, in Bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_U32 nU32; /**< U32 value */ +} OMX_PARAM_U32TYPE; + +/** @ingroup rpm */ +typedef enum OMX_SUSPENSIONPOLICYTYPE { + OMX_SuspensionDisabled, /**< No suspension; v1.0 behavior */ + OMX_SuspensionEnabled, /**< Suspension allowed */ + OMX_SuspensionPolicyKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_SuspensionPolicyStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_SuspensionPolicyMax = 0x7fffffff +} OMX_SUSPENSIONPOLICYTYPE; + +/** @ingroup rpm */ +typedef struct OMX_PARAM_SUSPENSIONPOLICYTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_SUSPENSIONPOLICYTYPE ePolicy; +} OMX_PARAM_SUSPENSIONPOLICYTYPE; + +/** @ingroup rpm */ +typedef enum OMX_SUSPENSIONTYPE { + OMX_NotSuspended, /**< component is not suspended */ + OMX_Suspended, /**< component is suspended */ + OMX_SuspensionKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_SuspensionVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_SuspendMax = 0x7FFFFFFF +} OMX_SUSPENSIONTYPE; + +/** @ingroup rpm */ +typedef struct OMX_PARAM_SUSPENSIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_SUSPENSIONTYPE eType; +} OMX_PARAM_SUSPENSIONTYPE ; + +typedef struct OMX_CONFIG_BOOLEANTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bEnabled; +} OMX_CONFIG_BOOLEANTYPE; + +/* Parameter specifying the content uri to use. */ +/** @ingroup cp */ +typedef struct OMX_PARAM_CONTENTURITYPE +{ + OMX_U32 nSize; /**< size of the structure in bytes, including + actual URI name */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U8 contentURI[1]; /**< The URI name */ +} OMX_PARAM_CONTENTURITYPE; + +/* Parameter specifying the pipe to use. */ +/** @ingroup cp */ +typedef struct OMX_PARAM_CONTENTPIPETYPE +{ + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_HANDLETYPE hPipe; /**< The pipe handle*/ +} OMX_PARAM_CONTENTPIPETYPE; + +/** @ingroup rpm */ +typedef struct OMX_RESOURCECONCEALMENTTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bResourceConcealmentForbidden; /**< disallow the use of resource concealment + methods (like degrading algorithm quality to + lower resource consumption or functional bypass) + on a component as a resolution to resource conflicts. */ +} OMX_RESOURCECONCEALMENTTYPE; + + +/** @ingroup metadata */ +typedef enum OMX_METADATACHARSETTYPE { + OMX_MetadataCharsetUnknown = 0, + OMX_MetadataCharsetASCII, + OMX_MetadataCharsetBinary, + OMX_MetadataCharsetCodePage1252, + OMX_MetadataCharsetUTF8, + OMX_MetadataCharsetJavaConformantUTF8, + OMX_MetadataCharsetUTF7, + OMX_MetadataCharsetImapUTF7, + OMX_MetadataCharsetUTF16LE, + OMX_MetadataCharsetUTF16BE, + OMX_MetadataCharsetGB12345, + OMX_MetadataCharsetHZGB2312, + OMX_MetadataCharsetGB2312, + OMX_MetadataCharsetGB18030, + OMX_MetadataCharsetGBK, + OMX_MetadataCharsetBig5, + OMX_MetadataCharsetISO88591, + OMX_MetadataCharsetISO88592, + OMX_MetadataCharsetISO88593, + OMX_MetadataCharsetISO88594, + OMX_MetadataCharsetISO88595, + OMX_MetadataCharsetISO88596, + OMX_MetadataCharsetISO88597, + OMX_MetadataCharsetISO88598, + OMX_MetadataCharsetISO88599, + OMX_MetadataCharsetISO885910, + OMX_MetadataCharsetISO885913, + OMX_MetadataCharsetISO885914, + OMX_MetadataCharsetISO885915, + OMX_MetadataCharsetShiftJIS, + OMX_MetadataCharsetISO2022JP, + OMX_MetadataCharsetISO2022JP1, + OMX_MetadataCharsetISOEUCJP, + OMX_MetadataCharsetSMS7Bit, + OMX_MetadataCharsetKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MetadataCharsetVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_MetadataCharsetTypeMax= 0x7FFFFFFF +} OMX_METADATACHARSETTYPE; + +/** @ingroup metadata */ +typedef enum OMX_METADATASCOPETYPE +{ + OMX_MetadataScopeAllLevels, + OMX_MetadataScopeTopLevel, + OMX_MetadataScopePortLevel, + OMX_MetadataScopeNodeLevel, + OMX_MetadataScopeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MetadataScopeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_MetadataScopeTypeMax = 0x7fffffff +} OMX_METADATASCOPETYPE; + +/** @ingroup metadata */ +typedef enum OMX_METADATASEARCHMODETYPE +{ + OMX_MetadataSearchValueSizeByIndex, + OMX_MetadataSearchItemByIndex, + OMX_MetadataSearchNextItemByKey, + OMX_MetadataSearchKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MetadataSearchVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_MetadataSearchTypeMax = 0x7fffffff +} OMX_METADATASEARCHMODETYPE; +/** @ingroup metadata */ +typedef struct OMX_CONFIG_METADATAITEMCOUNTTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_METADATASCOPETYPE eScopeMode; + OMX_U32 nScopeSpecifier; + OMX_U32 nMetadataItemCount; +} OMX_CONFIG_METADATAITEMCOUNTTYPE; + +/** @ingroup metadata */ +typedef struct OMX_CONFIG_METADATAITEMTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_METADATASCOPETYPE eScopeMode; + OMX_U32 nScopeSpecifier; + OMX_U32 nMetadataItemIndex; + OMX_METADATASEARCHMODETYPE eSearchMode; + OMX_METADATACHARSETTYPE eKeyCharset; + OMX_U8 nKeySizeUsed; + OMX_U8 nKey[128]; + OMX_METADATACHARSETTYPE eValueCharset; + OMX_STRING sLanguageCountry; + OMX_U32 nValueMaxSize; + OMX_U32 nValueSizeUsed; + OMX_U8 nValue[1]; +} OMX_CONFIG_METADATAITEMTYPE; + +/* @ingroup metadata */ +typedef struct OMX_CONFIG_CONTAINERNODECOUNTTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bAllKeys; + OMX_U32 nParentNodeID; + OMX_U32 nNumNodes; +} OMX_CONFIG_CONTAINERNODECOUNTTYPE; + +/** @ingroup metadata */ +typedef struct OMX_CONFIG_CONTAINERNODEIDTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bAllKeys; + OMX_U32 nParentNodeID; + OMX_U32 nNodeIndex; + OMX_U32 nNodeID; + OMX_STRING cNodeName; + OMX_BOOL bIsLeafType; +} OMX_CONFIG_CONTAINERNODEIDTYPE; + +/** @ingroup metadata */ +typedef struct OMX_PARAM_METADATAFILTERTYPE +{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bAllKeys; /* if true then this structure refers to all keys and + * the three key fields below are ignored */ + OMX_METADATACHARSETTYPE eKeyCharset; + OMX_U32 nKeySizeUsed; + OMX_U8 nKey [128]; + OMX_U32 nLanguageCountrySizeUsed; + OMX_U8 nLanguageCountry[128]; + OMX_BOOL bEnabled; /* if true then key is part of filter (e.g. + * retained for query later). If false then + * key is not part of filter */ +} OMX_PARAM_METADATAFILTERTYPE; + +/** The OMX_HANDLETYPE structure defines the component handle. The component + * handle is used to access all of the component's public methods and also + * contains pointers to the component's private data area. The component + * handle is initialized by the OMX core (with help from the component) + * during the process of loading the component. After the component is + * successfully loaded, the application can safely access any of the + * component's public functions (although some may return an error because + * the state is inappropriate for the access). + * + * @ingroup comp + */ +typedef struct OMX_COMPONENTTYPE +{ + /** The size of this structure, in bytes. It is the responsibility + of the allocator of this structure to fill in this value. Since + this structure is allocated by the GetHandle function, this + function will fill in this value. */ + OMX_U32 nSize; + + /** nVersion is the version of the OMX specification that the structure + is built against. It is the responsibility of the creator of this + structure to initialize this value and every user of this structure + should verify that it knows how to use the exact version of + this structure found herein. */ + OMX_VERSIONTYPE nVersion; + + /** pComponentPrivate is a pointer to the component private data area. + This member is allocated and initialized by the component when the + component is first loaded. The application should not access this + data area. */ + OMX_PTR pComponentPrivate; + + /** pApplicationPrivate is a pointer that is a parameter to the + OMX_GetHandle method, and contains an application private value + provided by the IL client. This application private data is + returned to the IL Client by OMX in all callbacks */ + OMX_PTR pApplicationPrivate; + + /** refer to OMX_GetComponentVersion in OMX_core.h or the OMX IL + specification for details on the GetComponentVersion method. + */ + OMX_ERRORTYPE (*GetComponentVersion)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STRING pComponentName, + OMX_OUT OMX_VERSIONTYPE* pComponentVersion, + OMX_OUT OMX_VERSIONTYPE* pSpecVersion, + OMX_OUT OMX_UUIDTYPE* pComponentUUID); + + /** refer to OMX_SendCommand in OMX_core.h or the OMX IL + specification for details on the SendCommand method. + */ + OMX_ERRORTYPE (*SendCommand)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_COMMANDTYPE Cmd, + OMX_IN OMX_U32 nParam1, + OMX_IN OMX_PTR pCmdData); + + /** refer to OMX_GetParameter in OMX_core.h or the OMX IL + specification for details on the GetParameter method. + */ + OMX_ERRORTYPE (*GetParameter)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure); + + + /** refer to OMX_SetParameter in OMX_core.h or the OMX IL + specification for details on the SetParameter method. + */ + OMX_ERRORTYPE (*SetParameter)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure); + + + /** refer to OMX_GetConfig in OMX_core.h or the OMX IL + specification for details on the GetConfig method. + */ + OMX_ERRORTYPE (*GetConfig)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_INOUT OMX_PTR pComponentConfigStructure); + + + /** refer to OMX_SetConfig in OMX_core.h or the OMX IL + specification for details on the SetConfig method. + */ + OMX_ERRORTYPE (*SetConfig)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure); + + + /** refer to OMX_GetExtensionIndex in OMX_core.h or the OMX IL + specification for details on the GetExtensionIndex method. + */ + OMX_ERRORTYPE (*GetExtensionIndex)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, + OMX_OUT OMX_INDEXTYPE* pIndexType); + + + /** refer to OMX_GetState in OMX_core.h or the OMX IL + specification for details on the GetState method. + */ + OMX_ERRORTYPE (*GetState)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_STATETYPE* pState); + + + /** The ComponentTunnelRequest method will interact with another OMX + component to determine if tunneling is possible and to setup the + tunneling. The return codes for this method can be used to + determine if tunneling is not possible, or if tunneling is not + supported. + + Base profile components (i.e. non-interop) do not support this + method and should return OMX_ErrorNotImplemented + + The interop profile component MUST support tunneling to another + interop profile component with a compatible port parameters. + A component may also support proprietary communication. + + If proprietary communication is supported the negotiation of + proprietary communication is done outside of OMX in a vendor + specific way. It is only required that the proper result be + returned and the details of how the setup is done is left + to the component implementation. + + When this method is invoked when nPort in an output port, the + component will: + 1. Populate the pTunnelSetup structure with the output port's + requirements and constraints for the tunnel. + + When this method is invoked when nPort in an input port, the + component will: + 1. Query the necessary parameters from the output port to + determine if the ports are compatible for tunneling + 2. If the ports are compatible, the component should store + the tunnel step provided by the output port + 3. Determine which port (either input or output) is the buffer + supplier, and call OMX_SetParameter on the output port to + indicate this selection. + + The component will return from this call within 5 msec. + + @param [in] hComp + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle method. + @param [in] nPort + nPort is used to select the port on the component to be used + for tunneling. + @param [in] hTunneledComp + Handle of the component to tunnel with. This is the component + handle returned by the call to the OMX_GetHandle method. When + this parameter is 0x0 the component should setup the port for + communication with the application / IL Client. + @param [in] nPortOutput + nPortOutput is used indicate the port the component should + tunnel with. + @param [in] pTunnelSetup + Pointer to the tunnel setup structure. When nPort is an output port + the component should populate the fields of this structure. When + When nPort is an input port the component should review the setup + provided by the component with the output port. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup tun + */ + + OMX_ERRORTYPE (*ComponentTunnelRequest)( + OMX_IN OMX_HANDLETYPE hComp, + OMX_IN OMX_U32 nPort, + OMX_IN OMX_HANDLETYPE hTunneledComp, + OMX_IN OMX_U32 nTunneledPort, + OMX_INOUT OMX_TUNNELSETUPTYPE* pTunnelSetup); + + /** refer to OMX_UseBuffer in OMX_core.h or the OMX IL + specification for details on the UseBuffer method. + @ingroup buf + */ + OMX_ERRORTYPE (*UseBuffer)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes, + OMX_IN OMX_U8* pBuffer); + + /** refer to OMX_AllocateBuffer in OMX_core.h or the OMX IL + specification for details on the AllocateBuffer method. + @ingroup buf + */ + OMX_ERRORTYPE (*AllocateBuffer)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN OMX_U32 nSizeBytes); + + /** refer to OMX_FreeBuffer in OMX_core.h or the OMX IL + specification for details on the FreeBuffer method. + @ingroup buf + */ + OMX_ERRORTYPE (*FreeBuffer)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + + /** refer to OMX_EmptyThisBuffer in OMX_core.h or the OMX IL + specification for details on the EmptyThisBuffer method. + @ingroup buf + */ + OMX_ERRORTYPE (*EmptyThisBuffer)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + + /** refer to OMX_FillThisBuffer in OMX_core.h or the OMX IL + specification for details on the FillThisBuffer method. + @ingroup buf + */ + OMX_ERRORTYPE (*FillThisBuffer)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + + /** The SetCallbacks method is used by the core to specify the callback + structure from the application to the component. This is a blocking + call. The component will return from this call within 5 msec. + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the GetHandle function. + @param [in] pCallbacks + pointer to an OMX_CALLBACKTYPE structure used to provide the + callback information to the component + @param [in] pAppData + pointer to an application defined value. It is anticipated that + the application will pass a pointer to a data structure or a "this + pointer" in this area to allow the callback (in the application) + to determine the context of the call + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + */ + OMX_ERRORTYPE (*SetCallbacks)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_CALLBACKTYPE* pCallbacks, + OMX_IN OMX_PTR pAppData); + + /** ComponentDeInit method is used to deinitialize the component + providing a means to free any resources allocated at component + initialization. NOTE: After this call the component handle is + not valid for further use. + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the GetHandle function. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + */ + OMX_ERRORTYPE (*ComponentDeInit)( + OMX_IN OMX_HANDLETYPE hComponent); + + /** @ingroup buf */ + OMX_ERRORTYPE (*UseEGLImage)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr, + OMX_IN OMX_U32 nPortIndex, + OMX_IN OMX_PTR pAppPrivate, + OMX_IN void* eglImage); + + OMX_ERRORTYPE (*ComponentRoleEnum)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_OUT OMX_U8 *cRole, + OMX_IN OMX_U32 nIndex); + +} OMX_COMPONENTTYPE; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ diff --git a/openmax/include/khronos/OMX_ComponentExt.h b/openmax/include/khronos/OMX_ComponentExt.h new file mode 100644 index 0000000..3a5eeb5 --- /dev/null +++ b/openmax/include/khronos/OMX_ComponentExt.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2010 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_ComponentExt.h - OpenMax IL version 1.1.2 + * The OMX_ComponentExt header file contains extensions to the definitions used + * by both the application and the component to access common items. + */ + +#ifndef OMX_ComponentExt_h +#define OMX_ComponentExt_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ +#include + + +/** Set/query the commit mode */ +typedef struct OMX_CONFIG_COMMITMODETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bDeferred; +} OMX_CONFIG_COMMITMODETYPE; + +/** Explicit commit */ +typedef struct OMX_CONFIG_COMMITTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; +} OMX_CONFIG_COMMITTYPE; + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OMX_ComponentExt_h */ diff --git a/openmax/include/khronos/OMX_ContentPipe.h b/openmax/include/khronos/OMX_ContentPipe.h new file mode 100644 index 0000000..5f6310c --- /dev/null +++ b/openmax/include/khronos/OMX_ContentPipe.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_ContentPipe.h - OpenMax IL version 1.1.2 + * The OMX_ContentPipe header file contains the definitions used to define + * the public interface for content piples. This header file is intended to + * be used by the component. + */ + +#ifndef OMX_CONTENTPIPE_H +#define OMX_CONTENTPIPE_H + +#ifndef KD_EACCES +/* OpenKODE error codes. CPResult values may be zero (indicating success + or one of the following values) */ +#define KD_EACCES (1) +#define KD_EADDRINUSE (2) +#define KD_EAGAIN (5) +#define KD_EBADF (7) +#define KD_EBUSY (8) +#define KD_ECONNREFUSED (9) +#define KD_ECONNRESET (10) +#define KD_EDEADLK (11) +#define KD_EDESTADDRREQ (12) +#define KD_ERANGE (35) +#define KD_EEXIST (13) +#define KD_EFBIG (14) +#define KD_EHOSTUNREACH (15) +#define KD_EINVAL (17) +#define KD_EIO (18) +#define KD_EISCONN (20) +#define KD_EISDIR (21) +#define KD_EMFILE (22) +#define KD_ENAMETOOLONG (23) +#define KD_ENOENT (24) +#define KD_ENOMEM (25) +#define KD_ENOSPC (26) +#define KD_ENOSYS (27) +#define KD_ENOTCONN (28) +#define KD_EPERM (33) +#define KD_ETIMEDOUT (36) +#define KD_EILSEQ (19) +#endif + +/** Map types from OMX standard types only here so interface is as generic as possible. */ +typedef OMX_U32 CPresult; +typedef char * CPstring; +typedef void * CPhandle; +typedef OMX_U32 CPuint; +typedef OMX_S32 CPint; +typedef char CPbyte; +typedef OMX_BOOL CPbool; + +/** enumeration of origin types used in the CP_PIPETYPE's Seek function + * @ingroup cp + */ +typedef enum CP_ORIGINTYPE { + CP_OriginBegin, + CP_OriginCur, + CP_OriginEnd, + CP_OriginKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + CP_OriginVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + CP_OriginMax = 0X7FFFFFFF +} CP_ORIGINTYPE; + +/** enumeration of contact access types used in the CP_PIPETYPE's Open function + * @ingroup cp + */ +typedef enum CP_ACCESSTYPE { + CP_AccessRead, + CP_AccessWrite, + CP_AccessReadWrite , + CP_AccessKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + CP_AccessVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + CP_AccessMax = 0X7FFFFFFF +} CP_ACCESSTYPE; + +/** enumeration of results returned by the CP_PIPETYPE's CheckAvailableBytes function + * @ingroup cp + */ +typedef enum CP_CHECKBYTESRESULTTYPE +{ + CP_CheckBytesOk, /**< There are at least the request number + of bytes available */ + CP_CheckBytesNotReady, /**< The pipe is still retrieving bytes + and presently lacks sufficient bytes. + Client will be called when they are + sufficient bytes are available. */ + CP_CheckBytesInsufficientBytes , /**< The pipe has retrieved all bytes + but those available are less than those + requested */ + CP_CheckBytesAtEndOfStream, /**< The pipe has reached the end of stream + and no more bytes are available. */ + CP_CheckBytesOutOfBuffers, /**< All read/write buffers are currently in use. */ + CP_CheckBytesKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + CP_CheckBytesVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + CP_CheckBytesMax = 0X7FFFFFFF +} CP_CHECKBYTESRESULTTYPE; + +/** enumeration of content pipe events sent to the client callback. + * @ingroup cp + */ +typedef enum CP_EVENTTYPE{ + CP_BytesAvailable, /** bytes requested in a CheckAvailableBytes call are now available*/ + CP_Overflow, /** enumeration of content pipe events sent to the client callback*/ + CP_PipeDisconnected , /** enumeration of content pipe events sent to the client callback*/ + CP_EventKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + CP_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + CP_EventMax = 0X7FFFFFFF +} CP_EVENTTYPE; + +/** content pipe definition + * @ingroup cp + */ +typedef struct CP_PIPETYPE +{ + /** Open a content stream for reading or writing. */ + CPresult (*Open)( CPhandle* hContent, CPstring szURI, CP_ACCESSTYPE eAccess ); + + /** Close a content stream. */ + CPresult (*Close)( CPhandle hContent ); + + /** Create a content source and open it for writing. */ + CPresult (*Create)( CPhandle *hContent, CPstring szURI ); + + /** Check the that specified number of bytes are available for reading or writing (depending on access type).*/ + CPresult (*CheckAvailableBytes)( CPhandle hContent, CPuint nBytesRequested, CP_CHECKBYTESRESULTTYPE *eResult ); + + /** Seek to certain position in the content relative to the specified origin. */ + CPresult (*SetPosition)( CPhandle hContent, CPint nOffset, CP_ORIGINTYPE eOrigin); + + /** Retrieve the current position relative to the start of the content. */ + CPresult (*GetPosition)( CPhandle hContent, CPuint *pPosition); + + /** Retrieve data of the specified size from the content stream (advance content pointer by size of data). + Note: pipe client provides pointer. This function is appropriate for small high frequency reads. */ + CPresult (*Read)( CPhandle hContent, CPbyte *pData, CPuint nSize); + + /** Retrieve a buffer allocated by the pipe that contains the requested number of bytes. + Buffer contains the next block of bytes, as specified by nSize, of the content. nSize also + returns the size of the block actually read. Content pointer advances the by the returned size. + Note: pipe provides pointer. This function is appropriate for large reads. The client must call + ReleaseReadBuffer when done with buffer. + + In some cases the requested block may not reside in contiguous memory within the + pipe implementation. For instance if the pipe leverages a circular buffer then the requested + block may straddle the boundary of the circular buffer. By default a pipe implementation + performs a copy in this case to provide the block to the pipe client in one contiguous buffer. + If, however, the client sets bForbidCopy, then the pipe returns only those bytes preceding the memory + boundary. Here the client may retrieve the data in segments over successive calls. */ + CPresult (*ReadBuffer)( CPhandle hContent, CPbyte **ppBuffer, CPuint *nSize, CPbool bForbidCopy); + + /** Release a buffer obtained by ReadBuffer back to the pipe. */ + CPresult (*ReleaseReadBuffer)(CPhandle hContent, CPbyte *pBuffer); + + /** Write data of the specified size to the content (advance content pointer by size of data). + Note: pipe client provides pointer. This function is appropriate for small high frequency writes. */ + CPresult (*Write)( CPhandle hContent, CPbyte *data, CPuint nSize); + + /** Retrieve a buffer allocated by the pipe used to write data to the content. + Client will fill buffer with output data. Note: pipe provides pointer. This function is appropriate + for large writes. The client must call WriteBuffer when done it has filled the buffer with data.*/ + CPresult (*GetWriteBuffer)( CPhandle hContent, CPbyte **ppBuffer, CPuint nSize); + + /** Deliver a buffer obtained via GetWriteBuffer to the pipe. Pipe will write the + the contents of the buffer to content and advance content pointer by the size of the buffer */ + CPresult (*WriteBuffer)( CPhandle hContent, CPbyte *pBuffer, CPuint nFilledSize); + + /** Register a per-handle client callback with the content pipe. */ + CPresult (*RegisterCallback)( CPhandle hContent, CPresult (*ClientCallback)(CP_EVENTTYPE eEvent, CPuint iParam)); + +} CP_PIPETYPE; + +#endif + diff --git a/openmax/include/khronos/OMX_Core.h b/openmax/include/khronos/OMX_Core.h new file mode 100644 index 0000000..a076f2f --- /dev/null +++ b/openmax/include/khronos/OMX_Core.h @@ -0,0 +1,1431 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_Core.h - OpenMax IL version 1.1.2 + * The OMX_Core header file contains the definitions used by both the + * application and the component to access common items. + */ + +#ifndef OMX_Core_h +#define OMX_Core_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* Each OMX header shall include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include + + +/** The OMX_COMMANDTYPE enumeration is used to specify the action in the + * OMX_SendCommand macro. + * @ingroup core + */ +typedef enum OMX_COMMANDTYPE +{ + OMX_CommandStateSet, /**< Change the component state */ + OMX_CommandFlush, /**< Flush the data queue(s) of a component */ + OMX_CommandPortDisable, /**< Disable a port on a component. */ + OMX_CommandPortEnable, /**< Enable a port on a component. */ + OMX_CommandMarkBuffer, /**< Mark a component/buffer for observation */ + OMX_CommandKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_CommandVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_CommandMax = 0X7FFFFFFF +} OMX_COMMANDTYPE; + + + +/** The OMX_STATETYPE enumeration is used to indicate or change the component + * state. This enumeration reflects the current state of the component when + * used with the OMX_GetState macro or becomes the parameter in a state change + * command when used with the OMX_SendCommand macro. + * + * The component will be in the Loaded state after the component is initially + * loaded into memory. In the Loaded state, the component is not allowed to + * allocate or hold resources other than to build it's internal parameter + * and configuration tables. The application will send one or more + * SetParameters/GetParameters and SetConfig/GetConfig commands to the + * component and the component will record each of these parameter and + * configuration changes for use later. When the application sends the + * Idle command, the component will acquire the resources needed for the + * specified configuration and will transition to the idle state if the + * allocation is successful. If the component cannot successfully + * transition to the idle state for any reason, the state of the component + * shall be fully rolled back to the Loaded state (e.g. all allocated + * resources shall be released). When the component receives the command + * to go to the Executing state, it shall begin processing buffers by + * sending all input buffers it holds to the application. While + * the component is in the Idle state, the application may also send the + * Pause command. If the component receives the pause command while in the + * Idle state, the component shall send all input buffers it holds to the + * application, but shall not begin processing buffers. This will allow the + * application to prefill buffers. + * + * @ingroup comp + */ + +typedef enum OMX_STATETYPE +{ + OMX_StateInvalid, /**< component has detected that it's internal data + structures are corrupted to the point that + it cannot determine it's state properly */ + OMX_StateLoaded, /**< component has been loaded but has not completed + initialization. The OMX_SetParameter macro + and the OMX_GetParameter macro are the only + valid macros allowed to be sent to the + component in this state. */ + OMX_StateIdle, /**< component initialization has been completed + successfully and the component is ready to + to start. */ + OMX_StateExecuting, /**< component has accepted the start command and + is processing data (if data is available) */ + OMX_StatePause, /**< component has received pause command */ + OMX_StateWaitForResources, /**< component is waiting for resources, either after + preemption or before it gets the resources requested. + See specification for complete details. */ + OMX_StateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_StateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_StateMax = 0X7FFFFFFF +} OMX_STATETYPE; + +/** The OMX_ERRORTYPE enumeration defines the standard OMX Errors. These + * errors should cover most of the common failure cases. However, + * vendors are free to add additional error messages of their own as + * long as they follow these rules: + * 1. Vendor error messages shall be in the range of 0x90000000 to + * 0x9000FFFF. + * 2. Vendor error messages shall be defined in a header file provided + * with the component. No error messages are allowed that are + * not defined. + */ +typedef enum OMX_ERRORTYPE +{ + OMX_ErrorNone = 0, + + /** There were insufficient resources to perform the requested operation */ + OMX_ErrorInsufficientResources = (OMX_S32) 0x80001000, + + /** There was an error, but the cause of the error could not be determined */ + OMX_ErrorUndefined = (OMX_S32) 0x80001001, + + /** The component name string was not valid */ + OMX_ErrorInvalidComponentName = (OMX_S32) 0x80001002, + + /** No component with the specified name string was found */ + OMX_ErrorComponentNotFound = (OMX_S32) 0x80001003, + + /** The component specified did not have a "OMX_ComponentInit" or + "OMX_ComponentDeInit entry point */ + OMX_ErrorInvalidComponent = (OMX_S32) 0x80001004, + + /** One or more parameters were not valid */ + OMX_ErrorBadParameter = (OMX_S32) 0x80001005, + + /** The requested function is not implemented */ + OMX_ErrorNotImplemented = (OMX_S32) 0x80001006, + + /** The buffer was emptied before the next buffer was ready */ + OMX_ErrorUnderflow = (OMX_S32) 0x80001007, + + /** The buffer was not available when it was needed */ + OMX_ErrorOverflow = (OMX_S32) 0x80001008, + + /** The hardware failed to respond as expected */ + OMX_ErrorHardware = (OMX_S32) 0x80001009, + + /** The component is in the state OMX_StateInvalid */ + OMX_ErrorInvalidState = (OMX_S32) 0x8000100A, + + /** Stream is found to be corrupt */ + OMX_ErrorStreamCorrupt = (OMX_S32) 0x8000100B, + + /** Ports being connected are not compatible */ + OMX_ErrorPortsNotCompatible = (OMX_S32) 0x8000100C, + + /** Resources allocated to an idle component have been + lost resulting in the component returning to the loaded state */ + OMX_ErrorResourcesLost = (OMX_S32) 0x8000100D, + + /** No more indicies can be enumerated */ + OMX_ErrorNoMore = (OMX_S32) 0x8000100E, + + /** The component detected a version mismatch */ + OMX_ErrorVersionMismatch = (OMX_S32) 0x8000100F, + + /** The component is not ready to return data at this time */ + OMX_ErrorNotReady = (OMX_S32) 0x80001010, + + /** There was a timeout that occurred */ + OMX_ErrorTimeout = (OMX_S32) 0x80001011, + + /** This error occurs when trying to transition into the state you are already in */ + OMX_ErrorSameState = (OMX_S32) 0x80001012, + + /** Resources allocated to an executing or paused component have been + preempted, causing the component to return to the idle state */ + OMX_ErrorResourcesPreempted = (OMX_S32) 0x80001013, + + /** A non-supplier port sends this error to the IL client (via the EventHandler callback) + during the allocation of buffers (on a transition from the LOADED to the IDLE state or + on a port restart) when it deems that it has waited an unusually long time for the supplier + to send it an allocated buffer via a UseBuffer call. */ + OMX_ErrorPortUnresponsiveDuringAllocation = (OMX_S32) 0x80001014, + + /** A non-supplier port sends this error to the IL client (via the EventHandler callback) + during the deallocation of buffers (on a transition from the IDLE to LOADED state or + on a port stop) when it deems that it has waited an unusually long time for the supplier + to request the deallocation of a buffer header via a FreeBuffer call. */ + OMX_ErrorPortUnresponsiveDuringDeallocation = (OMX_S32) 0x80001015, + + /** A supplier port sends this error to the IL client (via the EventHandler callback) + during the stopping of a port (either on a transition from the IDLE to LOADED + state or a port stop) when it deems that it has waited an unusually long time for + the non-supplier to return a buffer via an EmptyThisBuffer or FillThisBuffer call. */ + OMX_ErrorPortUnresponsiveDuringStop = (OMX_S32) 0x80001016, + + /** Attempting a state transtion that is not allowed */ + OMX_ErrorIncorrectStateTransition = (OMX_S32) 0x80001017, + + /* Attempting a command that is not allowed during the present state. */ + OMX_ErrorIncorrectStateOperation = (OMX_S32) 0x80001018, + + /** The values encapsulated in the parameter or config structure are not supported. */ + OMX_ErrorUnsupportedSetting = (OMX_S32) 0x80001019, + + /** The parameter or config indicated by the given index is not supported. */ + OMX_ErrorUnsupportedIndex = (OMX_S32) 0x8000101A, + + /** The port index supplied is incorrect. */ + OMX_ErrorBadPortIndex = (OMX_S32) 0x8000101B, + + /** The port has lost one or more of its buffers and it thus unpopulated. */ + OMX_ErrorPortUnpopulated = (OMX_S32) 0x8000101C, + + /** Component suspended due to temporary loss of resources */ + OMX_ErrorComponentSuspended = (OMX_S32) 0x8000101D, + + /** Component suspended due to an inability to acquire dynamic resources */ + OMX_ErrorDynamicResourcesUnavailable = (OMX_S32) 0x8000101E, + + /** When the macroblock error reporting is enabled the component returns new error + for every frame that has errors */ + OMX_ErrorMbErrorsInFrame = (OMX_S32) 0x8000101F, + + /** A component reports this error when it cannot parse or determine the format of an input stream. */ + OMX_ErrorFormatNotDetected = (OMX_S32) 0x80001020, + + /** The content open operation failed. */ + OMX_ErrorContentPipeOpenFailed = (OMX_S32) 0x80001021, + + /** The content creation operation failed. */ + OMX_ErrorContentPipeCreationFailed = (OMX_S32) 0x80001022, + + /** Separate table information is being used */ + OMX_ErrorSeperateTablesUsed = (OMX_S32) 0x80001023, + + /** Tunneling is unsupported by the component*/ + OMX_ErrorTunnelingUnsupported = (OMX_S32) 0x80001024, + + OMX_ErrorKhronosExtensions = (OMX_S32)0x8F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ErrorVendorStartUnused = (OMX_S32)0x90000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_ErrorMax = 0x7FFFFFFF +} OMX_ERRORTYPE; + +/** @ingroup core */ +typedef OMX_ERRORTYPE (* OMX_COMPONENTINITTYPE)(OMX_IN OMX_HANDLETYPE hComponent); + +/** @ingroup core */ +typedef struct OMX_COMPONENTREGISTERTYPE +{ + const char * pName; /* Component name, 128 byte limit (including '\0') applies */ + OMX_COMPONENTINITTYPE pInitialize; /* Component instance initialization function */ +} OMX_COMPONENTREGISTERTYPE; + +/** @ingroup core */ +extern OMX_COMPONENTREGISTERTYPE OMX_ComponentRegistered[]; + +/** @ingroup rpm */ +typedef struct OMX_PRIORITYMGMTTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nGroupPriority; /**< Priority of the component group */ + OMX_U32 nGroupID; /**< ID of the component group */ +} OMX_PRIORITYMGMTTYPE; + +/* Component name and Role names are limited to 128 characters including the terminating '\0'. */ +#define OMX_MAX_STRINGNAME_SIZE 128 + +/** @ingroup comp */ +typedef struct OMX_PARAM_COMPONENTROLETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U8 cRole[OMX_MAX_STRINGNAME_SIZE]; /**< name of standard component which defines component role */ +} OMX_PARAM_COMPONENTROLETYPE; + +/** End of Stream Buffer Flag: + * + * A component sets EOS when it has no more data to emit on a particular + * output port. Thus an output port shall set EOS on the last buffer it + * emits. A component's determination of when an output port should + * cease sending data is implemenation specific. + * @ingroup buf + */ + +#define OMX_BUFFERFLAG_EOS 0x00000001 + +/** Start Time Buffer Flag: + * + * The source of a stream (e.g. a demux component) sets the STARTTIME + * flag on the buffer that contains the starting timestamp for the + * stream. The starting timestamp corresponds to the first data that + * should be displayed at startup or after a seek. + * The first timestamp of the stream is not necessarily the start time. + * For instance, in the case of a seek to a particular video frame, + * the target frame may be an interframe. Thus the first buffer of + * the stream will be the intra-frame preceding the target frame and + * the starttime will occur with the target frame (with any other + * required frames required to reconstruct the target intervening). + * + * The STARTTIME flag is directly associated with the buffer's + * timestamp ' thus its association to buffer data and its + * propagation is identical to the timestamp's. + * + * When a Sync Component client receives a buffer with the + * STARTTIME flag it shall perform a SetConfig on its sync port + * using OMX_ConfigTimeClientStartTime and passing the buffer's + * timestamp. + * + * @ingroup buf + */ + +#define OMX_BUFFERFLAG_STARTTIME 0x00000002 + + + +/** Decode Only Buffer Flag: + * + * The source of a stream (e.g. a demux component) sets the DECODEONLY + * flag on any buffer that should shall be decoded but should not be + * displayed. This flag is used, for instance, when a source seeks to + * a target interframe that requires the decode of frames preceding the + * target to facilitate the target's reconstruction. In this case the + * source would emit the frames preceding the target downstream + * but mark them as decode only. + * + * The DECODEONLY is associated with buffer data and propagated in a + * manner identical to the buffer timestamp. + * + * A component that renders data should ignore all buffers with + * the DECODEONLY flag set. + * + * @ingroup buf + */ + +#define OMX_BUFFERFLAG_DECODEONLY 0x00000004 + + +/* Data Corrupt Flag: This flag is set when the IL client believes the data in the associated buffer is corrupt + * @ingroup buf + */ + +#define OMX_BUFFERFLAG_DATACORRUPT 0x00000008 + +/* End of Frame: The buffer contains exactly one end of frame and no data + * occurs after the end of frame. This flag is an optional hint. The absence + * of this flag does not imply the absence of an end of frame within the buffer. + * @ingroup buf +*/ +#define OMX_BUFFERFLAG_ENDOFFRAME 0x00000010 + +/* Sync Frame Flag: This flag is set when the buffer content contains a coded sync frame ' + * a frame that has no dependency on any other frame information + * @ingroup buf + */ +#define OMX_BUFFERFLAG_SYNCFRAME 0x00000020 + +/* Extra data present flag: there is extra data appended to the data stream + * residing in the buffer + * @ingroup buf + */ +#define OMX_BUFFERFLAG_EXTRADATA 0x00000040 + +/** Codec Config Buffer Flag: +* OMX_BUFFERFLAG_CODECCONFIG is an optional flag that is set by an +* output port when all bytes in the buffer form part or all of a set of +* codec specific configuration data. Examples include SPS/PPS nal units +* for OMX_VIDEO_CodingAVC or AudioSpecificConfig data for +* OMX_AUDIO_CodingAAC. Any component that for a given stream sets +* OMX_BUFFERFLAG_CODECCONFIG shall not mix codec configuration bytes +* with frame data in the same buffer, and shall send all buffers +* containing codec configuration bytes before any buffers containing +* frame data that those configurations bytes describe. +* If the stream format for a particular codec has a frame specific +* header at the start of each frame, for example OMX_AUDIO_CodingMP3 or +* OMX_AUDIO_CodingAAC in ADTS mode, then these shall be presented as +* normal without setting OMX_BUFFERFLAG_CODECCONFIG. + * @ingroup buf + */ +#define OMX_BUFFERFLAG_CODECCONFIG 0x00000080 + + + +/** @ingroup buf */ +typedef struct OMX_BUFFERHEADERTYPE +{ + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U8* pBuffer; /**< Pointer to actual block of memory + that is acting as the buffer */ + OMX_U32 nAllocLen; /**< size of the buffer allocated, in bytes */ + OMX_U32 nFilledLen; /**< number of bytes currently in the + buffer */ + OMX_U32 nOffset; /**< start offset of valid data in bytes from + the start of the buffer */ + OMX_PTR pAppPrivate; /**< pointer to any data the application + wants to associate with this buffer */ + OMX_PTR pPlatformPrivate; /**< pointer to any data the platform + wants to associate with this buffer */ + OMX_PTR pInputPortPrivate; /**< pointer to any data the input port + wants to associate with this buffer */ + OMX_PTR pOutputPortPrivate; /**< pointer to any data the output port + wants to associate with this buffer */ + OMX_HANDLETYPE hMarkTargetComponent; /**< The component that will generate a + mark event upon processing this buffer. */ + OMX_PTR pMarkData; /**< Application specific data associated with + the mark sent on a mark event to disambiguate + this mark from others. */ + OMX_U32 nTickCount; /**< Optional entry that the component and + application can update with a tick count + when they access the component. This + value should be in microseconds. Since + this is a value relative to an arbitrary + starting point, this value cannot be used + to determine absolute time. This is an + optional entry and not all components + will update it.*/ + OMX_TICKS nTimeStamp; /**< Timestamp corresponding to the sample + starting at the first logical sample + boundary in the buffer. Timestamps of + successive samples within the buffer may + be inferred by adding the duration of the + of the preceding buffer to the timestamp + of the preceding buffer.*/ + OMX_U32 nFlags; /**< buffer specific flags */ + OMX_U32 nOutputPortIndex; /**< The index of the output port (if any) using + this buffer */ + OMX_U32 nInputPortIndex; /**< The index of the input port (if any) using + this buffer */ +} OMX_BUFFERHEADERTYPE; + +/** The OMX_EXTRADATATYPE enumeration is used to define the + * possible extra data payload types. + * NB: this enum is binary backwards compatible with the previous + * OMX_EXTRADATA_QUANT define. This should be replaced with + * OMX_ExtraDataQuantization. + */ +typedef enum OMX_EXTRADATATYPE +{ + OMX_ExtraDataNone = 0, /**< Indicates that no more extra data sections follow */ + OMX_ExtraDataQuantization, /**< The data payload contains quantization data */ + OMX_ExtraDataKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ExtraDataVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_ExtraDataMax = 0x7FFFFFFF +} OMX_EXTRADATATYPE; + + +typedef struct OMX_OTHER_EXTRADATATYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_EXTRADATATYPE eType; /* Extra Data type */ + OMX_U32 nDataSize; /* Size of the supporting data to follow */ + OMX_U8 data[1]; /* Supporting data hint */ +} OMX_OTHER_EXTRADATATYPE; + +/** @ingroup comp */ +typedef struct OMX_PORT_PARAM_TYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPorts; /**< The number of ports for this component */ + OMX_U32 nStartPortNumber; /** first port number for this type of port */ +} OMX_PORT_PARAM_TYPE; + +/** @ingroup comp */ +typedef enum OMX_EVENTTYPE +{ + OMX_EventCmdComplete, /**< component has sucessfully completed a command */ + OMX_EventError, /**< component has detected an error condition */ + OMX_EventMark, /**< component has detected a buffer mark */ + OMX_EventPortSettingsChanged, /**< component is reported a port settings change */ + OMX_EventBufferFlag, /**< component has detected an EOS */ + OMX_EventResourcesAcquired, /**< component has been granted resources and is + automatically starting the state change from + OMX_StateWaitForResources to OMX_StateIdle. */ + OMX_EventComponentResumed, /**< Component resumed due to reacquisition of resources */ + OMX_EventDynamicResourcesAvailable, /**< Component has acquired previously unavailable dynamic resources */ + OMX_EventPortFormatDetected, /**< Component has detected a supported format. */ + OMX_EventKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_EventVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_EventMax = 0x7FFFFFFF +} OMX_EVENTTYPE; + +typedef struct OMX_CALLBACKTYPE +{ + /** The EventHandler method is used to notify the application when an + event of interest occurs. Events are defined in the OMX_EVENTTYPE + enumeration. Please see that enumeration for details of what will + be returned for each type of event. Callbacks should not return + an error to the component, so if an error occurs, the application + shall handle it internally. This is a blocking call. + + The application should return from this call within 5 msec to avoid + blocking the component for an excessively long period of time. + + @param hComponent + handle of the component to access. This is the component + handle returned by the call to the GetHandle function. + @param pAppData + pointer to an application defined value that was provided in the + pAppData parameter to the OMX_GetHandle method for the component. + This application defined value is provided so that the application + can have a component specific context when receiving the callback. + @param eEvent + Event that the component wants to notify the application about. + @param nData1 + nData will be the OMX_ERRORTYPE for an error event and will be + an OMX_COMMANDTYPE for a command complete event and OMX_INDEXTYPE for a OMX_PortSettingsChanged event. + @param nData2 + nData2 will hold further information related to the event. Can be OMX_STATETYPE for + a OMX_CommandStateSet command or port index for a OMX_PortSettingsChanged event. + Default value is 0 if not used. ) + @param pEventData + Pointer to additional event-specific data (see spec for meaning). + */ + + OMX_ERRORTYPE (*EventHandler)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_EVENTTYPE eEvent, + OMX_IN OMX_U32 nData1, + OMX_IN OMX_U32 nData2, + OMX_IN OMX_PTR pEventData); + + /** The EmptyBufferDone method is used to return emptied buffers from an + input port back to the application for reuse. This is a blocking call + so the application should not attempt to refill the buffers during this + call, but should queue them and refill them in another thread. There + is no error return, so the application shall handle any errors generated + internally. + + The application should return from this call within 5 msec. + + @param hComponent + handle of the component to access. This is the component + handle returned by the call to the GetHandle function. + @param pAppData + pointer to an application defined value that was provided in the + pAppData parameter to the OMX_GetHandle method for the component. + This application defined value is provided so that the application + can have a component specific context when receiving the callback. + @param pBuffer + pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer + or AllocateBuffer indicating the buffer that was emptied. + @ingroup buf + */ + OMX_ERRORTYPE (*EmptyBufferDone)( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_BUFFERHEADERTYPE* pBuffer); + + /** The FillBufferDone method is used to return filled buffers from an + output port back to the application for emptying and then reuse. + This is a blocking call so the application should not attempt to + empty the buffers during this call, but should queue the buffers + and empty them in another thread. There is no error return, so + the application shall handle any errors generated internally. The + application shall also update the buffer header to indicate the + number of bytes placed into the buffer. + + The application should return from this call within 5 msec. + + @param hComponent + handle of the component to access. This is the component + handle returned by the call to the GetHandle function. + @param pAppData + pointer to an application defined value that was provided in the + pAppData parameter to the OMX_GetHandle method for the component. + This application defined value is provided so that the application + can have a component specific context when receiving the callback. + @param pBuffer + pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer + or AllocateBuffer indicating the buffer that was filled. + @ingroup buf + */ + OMX_ERRORTYPE (*FillBufferDone)( + OMX_OUT OMX_HANDLETYPE hComponent, + OMX_OUT OMX_PTR pAppData, + OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer); + +} OMX_CALLBACKTYPE; + +/** The OMX_BUFFERSUPPLIERTYPE enumeration is used to dictate port supplier + preference when tunneling between two ports. + @ingroup tun buf +*/ +typedef enum OMX_BUFFERSUPPLIERTYPE +{ + OMX_BufferSupplyUnspecified = 0x0, /**< port supplying the buffers is unspecified, + or don't care */ + OMX_BufferSupplyInput, /**< input port supplies the buffers */ + OMX_BufferSupplyOutput, /**< output port supplies the buffers */ + OMX_BufferSupplyKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_BufferSupplyVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_BufferSupplyMax = 0x7FFFFFFF +} OMX_BUFFERSUPPLIERTYPE; + + +/** buffer supplier parameter + * @ingroup tun + */ +typedef struct OMX_PARAM_BUFFERSUPPLIERTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_BUFFERSUPPLIERTYPE eBufferSupplier; /**< buffer supplier */ +} OMX_PARAM_BUFFERSUPPLIERTYPE; + + +/**< indicates that buffers received by an input port of a tunnel + may not modify the data in the buffers + @ingroup tun + */ +#define OMX_PORTTUNNELFLAG_READONLY 0x00000001 + + +/** The OMX_TUNNELSETUPTYPE structure is used to pass data from an output + port to an input port as part the two ComponentTunnelRequest calls + resulting from a OMX_SetupTunnel call from the IL Client. + @ingroup tun + */ +typedef struct OMX_TUNNELSETUPTYPE +{ + OMX_U32 nTunnelFlags; /**< bit flags for tunneling */ + OMX_BUFFERSUPPLIERTYPE eSupplier; /**< supplier preference */ +} OMX_TUNNELSETUPTYPE; + +/* OMX Component headers is included to enable the core to use + macros for functions into the component for OMX release 1.0. + Developers should not access any structures or data from within + the component header directly */ +/* TO BE REMOVED - #include */ + +/** GetComponentVersion will return information about the component. + This is a blocking call. This macro will go directly from the + application to the component (via a core macro). The + component will return from this call within 5 msec. + @param [in] hComponent + handle of component to execute the command + @param [out] pComponentName + pointer to an empty string of length 128 bytes. The component + will write its name into this string. The name will be + terminated by a single zero byte. The name of a component will + be 127 bytes or less to leave room for the trailing zero byte. + An example of a valid component name is "OMX.ABC.ChannelMixer\0". + @param [out] pComponentVersion + pointer to an OMX Version structure that the component will fill + in. The component will fill in a value that indicates the + component version. NOTE: the component version is NOT the same + as the OMX Specification version (found in all structures). The + component version is defined by the vendor of the component and + its value is entirely up to the component vendor. + @param [out] pSpecVersion + pointer to an OMX Version structure that the component will fill + in. The SpecVersion is the version of the specification that the + component was built against. Please note that this value may or + may not match the structure's version. For example, if the + component was built against the 2.0 specification, but the + application (which creates the structure is built against the + 1.0 specification the versions would be different. + @param [out] pComponentUUID + pointer to the UUID of the component which will be filled in by + the component. The UUID is a unique identifier that is set at + RUN time for the component and is unique to each instantion of + the component. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_GetComponentVersion( \ + hComponent, \ + pComponentName, \ + pComponentVersion, \ + pSpecVersion, \ + pComponentUUID) \ + ((OMX_COMPONENTTYPE*)hComponent)->GetComponentVersion( \ + hComponent, \ + pComponentName, \ + pComponentVersion, \ + pSpecVersion, \ + pComponentUUID) /* Macro End */ + + +/** Send a command to the component. This call is a non-blocking call. + The component should check the parameters and then queue the command + to the component thread to be executed. The component thread shall + send the EventHandler() callback at the conclusion of the command. + This macro will go directly from the application to the component (via + a core macro). The component will return from this call within 5 msec. + + When the command is "OMX_CommandStateSet" the component will queue a + state transition to the new state idenfied in nParam. + + When the command is "OMX_CommandFlush", to flush a port's buffer queues, + the command will force the component to return all buffers NOT CURRENTLY + BEING PROCESSED to the application, in the order in which the buffers + were received. + + When the command is "OMX_CommandPortDisable" or + "OMX_CommandPortEnable", the component's port (given by the value of + nParam) will be stopped or restarted. + + When the command "OMX_CommandMarkBuffer" is used to mark a buffer, the + pCmdData will point to a OMX_MARKTYPE structure containing the component + handle of the component to examine the buffer chain for the mark. nParam1 + contains the index of the port on which the buffer mark is applied. + + Specification text for more details. + + @param [in] hComponent + handle of component to execute the command + @param [in] Cmd + Command for the component to execute + @param [in] nParam + Parameter for the command to be executed. When Cmd has the value + OMX_CommandStateSet, value is a member of OMX_STATETYPE. When Cmd has + the value OMX_CommandFlush, value of nParam indicates which port(s) + to flush. -1 is used to flush all ports a single port index will + only flush that port. When Cmd has the value "OMX_CommandPortDisable" + or "OMX_CommandPortEnable", the component's port is given by + the value of nParam. When Cmd has the value "OMX_CommandMarkBuffer" + the components pot is given by the value of nParam. + @param [in] pCmdData + Parameter pointing to the OMX_MARKTYPE structure when Cmd has the value + "OMX_CommandMarkBuffer". + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_SendCommand( \ + hComponent, \ + Cmd, \ + nParam, \ + pCmdData) \ + ((OMX_COMPONENTTYPE*)hComponent)->SendCommand( \ + hComponent, \ + Cmd, \ + nParam, \ + pCmdData) /* Macro End */ + + +/** The OMX_GetParameter macro will get one of the current parameter + settings from the component. This macro cannot only be invoked when + the component is in the OMX_StateInvalid state. The nParamIndex + parameter is used to indicate which structure is being requested from + the component. The application shall allocate the correct structure + and shall fill in the structure size and version information before + invoking this macro. When the parameter applies to a port, the + caller shall fill in the appropriate nPortIndex value indicating the + port on which the parameter applies. If the component has not had + any settings changed, then the component should return a set of + valid DEFAULT parameters for the component. This is a blocking + call. + + The component should return from this call within 20 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] nParamIndex + Index of the structure to be filled. This value is from the + OMX_INDEXTYPE enumeration. + @param [in,out] pComponentParameterStructure + Pointer to application allocated structure to be filled by the + component. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_GetParameter( \ + hComponent, \ + nParamIndex, \ + pComponentParameterStructure) \ + ((OMX_COMPONENTTYPE*)hComponent)->GetParameter( \ + hComponent, \ + nParamIndex, \ + pComponentParameterStructure) /* Macro End */ + + +/** The OMX_SetParameter macro will send an initialization parameter + structure to a component. Each structure shall be sent one at a time, + in a separate invocation of the macro. This macro can only be + invoked when the component is in the OMX_StateLoaded state, or the + port is disabled (when the parameter applies to a port). The + nParamIndex parameter is used to indicate which structure is being + passed to the component. The application shall allocate the + correct structure and shall fill in the structure size and version + information (as well as the actual data) before invoking this macro. + The application is free to dispose of this structure after the call + as the component is required to copy any data it shall retain. This + is a blocking call. + + The component should return from this call within 20 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] nIndex + Index of the structure to be sent. This value is from the + OMX_INDEXTYPE enumeration. + @param [in] pComponentParameterStructure + pointer to application allocated structure to be used for + initialization by the component. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_SetParameter( \ + hComponent, \ + nParamIndex, \ + pComponentParameterStructure) \ + ((OMX_COMPONENTTYPE*)hComponent)->SetParameter( \ + hComponent, \ + nParamIndex, \ + pComponentParameterStructure) /* Macro End */ + + +/** The OMX_GetConfig macro will get one of the configuration structures + from a component. This macro can be invoked anytime after the + component has been loaded. The nParamIndex call parameter is used to + indicate which structure is being requested from the component. The + application shall allocate the correct structure and shall fill in the + structure size and version information before invoking this macro. + If the component has not had this configuration parameter sent before, + then the component should return a set of valid DEFAULT values for the + component. This is a blocking call. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] nIndex + Index of the structure to be filled. This value is from the + OMX_INDEXTYPE enumeration. + @param [in,out] pComponentConfigStructure + pointer to application allocated structure to be filled by the + component. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp +*/ +#define OMX_GetConfig( \ + hComponent, \ + nConfigIndex, \ + pComponentConfigStructure) \ + ((OMX_COMPONENTTYPE*)hComponent)->GetConfig( \ + hComponent, \ + nConfigIndex, \ + pComponentConfigStructure) /* Macro End */ + + +/** The OMX_SetConfig macro will send one of the configuration + structures to a component. Each structure shall be sent one at a time, + each in a separate invocation of the macro. This macro can be invoked + anytime after the component has been loaded. The application shall + allocate the correct structure and shall fill in the structure size + and version information (as well as the actual data) before invoking + this macro. The application is free to dispose of this structure after + the call as the component is required to copy any data it shall retain. + This is a blocking call. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] nConfigIndex + Index of the structure to be sent. This value is from the + OMX_INDEXTYPE enumeration above. + @param [in] pComponentConfigStructure + pointer to application allocated structure to be used for + initialization by the component. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_SetConfig( \ + hComponent, \ + nConfigIndex, \ + pComponentConfigStructure) \ + ((OMX_COMPONENTTYPE*)hComponent)->SetConfig( \ + hComponent, \ + nConfigIndex, \ + pComponentConfigStructure) /* Macro End */ + + +/** The OMX_GetExtensionIndex macro will invoke a component to translate + a vendor specific configuration or parameter string into an OMX + structure index. There is no requirement for the vendor to support + this command for the indexes already found in the OMX_INDEXTYPE + enumeration (this is done to save space in small components). The + component shall support all vendor supplied extension indexes not found + in the master OMX_INDEXTYPE enumeration. This is a blocking call. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the GetHandle function. + @param [in] cParameterName + OMX_STRING that shall be less than 128 characters long including + the trailing null byte. This is the string that will get + translated by the component into a configuration index. + @param [out] pIndexType + a pointer to a OMX_INDEXTYPE to receive the index value. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_GetExtensionIndex( \ + hComponent, \ + cParameterName, \ + pIndexType) \ + ((OMX_COMPONENTTYPE*)hComponent)->GetExtensionIndex( \ + hComponent, \ + cParameterName, \ + pIndexType) /* Macro End */ + + +/** The OMX_GetState macro will invoke the component to get the current + state of the component and place the state value into the location + pointed to by pState. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [out] pState + pointer to the location to receive the state. The value returned + is one of the OMX_STATETYPE members + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp + */ +#define OMX_GetState( \ + hComponent, \ + pState) \ + ((OMX_COMPONENTTYPE*)hComponent)->GetState( \ + hComponent, \ + pState) /* Macro End */ + + +/** The OMX_UseBuffer macro will request that the component use + a buffer (and allocate its own buffer header) already allocated + by another component, or by the IL Client. This is a blocking + call. + + The component should return from this call within 20 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [out] ppBuffer + pointer to an OMX_BUFFERHEADERTYPE structure used to receive the + pointer to the buffer header + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ + +#define OMX_UseBuffer( \ + hComponent, \ + ppBufferHdr, \ + nPortIndex, \ + pAppPrivate, \ + nSizeBytes, \ + pBuffer) \ + ((OMX_COMPONENTTYPE*)hComponent)->UseBuffer( \ + hComponent, \ + ppBufferHdr, \ + nPortIndex, \ + pAppPrivate, \ + nSizeBytes, \ + pBuffer) + + +/** The OMX_AllocateBuffer macro will request that the component allocate + a new buffer and buffer header. The component will allocate the + buffer and the buffer header and return a pointer to the buffer + header. This is a blocking call. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [out] ppBuffer + pointer to an OMX_BUFFERHEADERTYPE structure used to receive + the pointer to the buffer header + @param [in] nPortIndex + nPortIndex is used to select the port on the component the buffer will + be used with. The port can be found by using the nPortIndex + value as an index into the Port Definition array of the component. + @param [in] pAppPrivate + pAppPrivate is used to initialize the pAppPrivate member of the + buffer header structure. + @param [in] nSizeBytes + size of the buffer to allocate. Used when bAllocateNew is true. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ +#define OMX_AllocateBuffer( \ + hComponent, \ + ppBuffer, \ + nPortIndex, \ + pAppPrivate, \ + nSizeBytes) \ + ((OMX_COMPONENTTYPE*)hComponent)->AllocateBuffer( \ + hComponent, \ + ppBuffer, \ + nPortIndex, \ + pAppPrivate, \ + nSizeBytes) /* Macro End */ + + +/** The OMX_FreeBuffer macro will release a buffer header from the component + which was allocated using either OMX_AllocateBuffer or OMX_UseBuffer. If + the component allocated the buffer (see the OMX_UseBuffer macro) then + the component shall free the buffer and buffer header. This is a + blocking call. + + The component should return from this call within 20 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] nPortIndex + nPortIndex is used to select the port on the component the buffer will + be used with. + @param [in] pBuffer + pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer + or AllocateBuffer. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ +#define OMX_FreeBuffer( \ + hComponent, \ + nPortIndex, \ + pBuffer) \ + ((OMX_COMPONENTTYPE*)hComponent)->FreeBuffer( \ + hComponent, \ + nPortIndex, \ + pBuffer) /* Macro End */ + + +/** The OMX_EmptyThisBuffer macro will send a buffer full of data to an + input port of a component. The buffer will be emptied by the component + and returned to the application via the EmptyBufferDone call back. + This is a non-blocking call in that the component will record the buffer + and return immediately and then empty the buffer, later, at the proper + time. As expected, this macro may be invoked only while the component + is in the OMX_StateExecuting. If nPortIndex does not specify an input + port, the component shall return an error. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] pBuffer + pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer + or AllocateBuffer. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ +#define OMX_EmptyThisBuffer( \ + hComponent, \ + pBuffer) \ + ((OMX_COMPONENTTYPE*)hComponent)->EmptyThisBuffer( \ + hComponent, \ + pBuffer) /* Macro End */ + + +/** The OMX_FillThisBuffer macro will send an empty buffer to an + output port of a component. The buffer will be filled by the component + and returned to the application via the FillBufferDone call back. + This is a non-blocking call in that the component will record the buffer + and return immediately and then fill the buffer, later, at the proper + time. As expected, this macro may be invoked only while the component + is in the OMX_ExecutingState. If nPortIndex does not specify an output + port, the component shall return an error. + + The component should return from this call within 5 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [in] pBuffer + pointer to an OMX_BUFFERHEADERTYPE structure allocated with UseBuffer + or AllocateBuffer. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ +#define OMX_FillThisBuffer( \ + hComponent, \ + pBuffer) \ + ((OMX_COMPONENTTYPE*)hComponent)->FillThisBuffer( \ + hComponent, \ + pBuffer) /* Macro End */ + + + +/** The OMX_UseEGLImage macro will request that the component use + a EGLImage provided by EGL (and allocate its own buffer header) + This is a blocking call. + + The component should return from this call within 20 msec. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the OMX_GetHandle function. + @param [out] ppBuffer + pointer to an OMX_BUFFERHEADERTYPE structure used to receive the + pointer to the buffer header. Note that the memory location used + for this buffer is NOT visible to the IL Client. + @param [in] nPortIndex + nPortIndex is used to select the port on the component the buffer will + be used with. The port can be found by using the nPortIndex + value as an index into the Port Definition array of the component. + @param [in] pAppPrivate + pAppPrivate is used to initialize the pAppPrivate member of the + buffer header structure. + @param [in] eglImage + eglImage contains the handle of the EGLImage to use as a buffer on the + specified port. The component is expected to validate properties of + the EGLImage against the configuration of the port to ensure the component + can use the EGLImage as a buffer. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup comp buf + */ +#define OMX_UseEGLImage( \ + hComponent, \ + ppBufferHdr, \ + nPortIndex, \ + pAppPrivate, \ + eglImage) \ + ((OMX_COMPONENTTYPE*)hComponent)->UseEGLImage( \ + hComponent, \ + ppBufferHdr, \ + nPortIndex, \ + pAppPrivate, \ + eglImage) + +/** The OMX_Init method is used to initialize the OMX core. It shall be the + first call made into OMX and it should only be executed one time without + an interviening OMX_Deinit call. + + The core should return from this call within 20 msec. + + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void); + + +/** The OMX_Deinit method is used to deinitialize the OMX core. It shall be + the last call made into OMX. In the event that the core determines that + thare are components loaded when this call is made, the core may return + with an error rather than try to unload the components. + + The core should return from this call within 20 msec. + + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void); + + +/** The OMX_ComponentNameEnum method will enumerate through all the names of + recognised valid components in the system. This function is provided + as a means to detect all the components in the system run-time. There is + no strict ordering to the enumeration order of component names, although + each name will only be enumerated once. If the OMX core supports run-time + installation of new components, it is only requried to detect newly + installed components when the first call to enumerate component names + is made (i.e. when nIndex is 0x0). + + The core should return from this call in 20 msec. + + @param [out] cComponentName + pointer to a null terminated string with the component name. The + names of the components are strings less than 127 bytes in length + plus the trailing null for a maximum size of 128 bytes. An example + of a valid component name is "OMX.TI.AUDIO.DSP.MIXER\0". Names are + assigned by the vendor, but shall start with "OMX." and then have + the Vendor designation next. + @param [in] nNameLength + number of characters in the cComponentName string. With all + component name strings restricted to less than 128 characters + (including the trailing null) it is recomended that the caller + provide a input string for the cComponentName of 128 characters. + @param [in] nIndex + number containing the enumeration index for the component. + Multiple calls to OMX_ComponentNameEnum with increasing values + of nIndex will enumerate through the component names in the + system until OMX_ErrorNoMore is returned. The value of nIndex + is 0 to (N-1), where N is the number of valid installed components + in the system. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. When the value of nIndex exceeds the number of + components in the system minus 1, OMX_ErrorNoMore will be + returned. Otherwise the appropriate OMX error will be returned. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum( + OMX_OUT OMX_STRING cComponentName, + OMX_IN OMX_U32 nNameLength, + OMX_IN OMX_U32 nIndex); + + +/** The OMX_GetHandle method will locate the component specified by the + component name given, load that component into memory and then invoke + the component's methods to create an instance of the component. + + The core should return from this call within 20 msec. + + @param [out] pHandle + pointer to an OMX_HANDLETYPE pointer to be filled in by this method. + @param [in] cComponentName + pointer to a null terminated string with the component name. The + names of the components are strings less than 127 bytes in length + plus the trailing null for a maximum size of 128 bytes. An example + of a valid component name is "OMX.TI.AUDIO.DSP.MIXER\0". Names are + assigned by the vendor, but shall start with "OMX." and then have + the Vendor designation next. + @param [in] pAppData + pointer to an application defined value that will be returned + during callbacks so that the application can identify the source + of the callback. + @param [in] pCallBacks + pointer to a OMX_CALLBACKTYPE structure that will be passed to the + component to initialize it with. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle( + OMX_OUT OMX_HANDLETYPE* pHandle, + OMX_IN OMX_STRING cComponentName, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_CALLBACKTYPE* pCallBacks); + + +/** The OMX_FreeHandle method will free a handle allocated by the OMX_GetHandle + method. If the component reference count goes to zero, the component will + be unloaded from memory. + + The core should return from this call within 20 msec when the component is + in the OMX_StateLoaded state. + + @param [in] hComponent + Handle of the component to be accessed. This is the component + handle returned by the call to the GetHandle function. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle( + OMX_IN OMX_HANDLETYPE hComponent); + + + +/** The OMX_SetupTunnel method will handle the necessary calls to the components + to setup the specified tunnel the two components. NOTE: This is + an actual method (not a #define macro). This method will make calls into + the component ComponentTunnelRequest method to do the actual tunnel + connection. + + The ComponentTunnelRequest method on both components will be called. + This method shall not be called unless the component is in the + OMX_StateLoaded state except when the ports used for the tunnel are + disabled. In this case, the component may be in the OMX_StateExecuting, + OMX_StatePause, or OMX_StateIdle states. + + The core should return from this call within 20 msec. + + @param [in] hOutput + Handle of the component to be accessed. Also this is the handle + of the component whose port, specified in the nPortOutput parameter + will be used the source for the tunnel. This is the component handle + returned by the call to the OMX_GetHandle function. There is a + requirement that hOutput be the source for the data when + tunelling (i.e. nPortOutput is an output port). If 0x0, the component + specified in hInput will have it's port specified in nPortInput + setup for communication with the application / IL client. + @param [in] nPortOutput + nPortOutput is used to select the source port on component to be + used in the tunnel. + @param [in] hInput + This is the component to setup the tunnel with. This is the handle + of the component whose port, specified in the nPortInput parameter + will be used the destination for the tunnel. This is the component handle + returned by the call to the OMX_GetHandle function. There is a + requirement that hInput be the destination for the data when + tunelling (i.e. nPortInut is an input port). If 0x0, the component + specified in hOutput will have it's port specified in nPortPOutput + setup for communication with the application / IL client. + @param [in] nPortInput + nPortInput is used to select the destination port on component to be + used in the tunnel. + @return OMX_ERRORTYPE + If the command successfully executes, the return code will be + OMX_ErrorNone. Otherwise the appropriate OMX error will be returned. + When OMX_ErrorNotImplemented is returned, one or both components is + a non-interop component and does not support tunneling. + + On failure, the ports of both components are setup for communication + with the application / IL Client. + @ingroup core tun + */ +OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel( + OMX_IN OMX_HANDLETYPE hOutput, + OMX_IN OMX_U32 nPortOutput, + OMX_IN OMX_HANDLETYPE hInput, + OMX_IN OMX_U32 nPortInput); + +/** @ingroup cp */ +OMX_API OMX_ERRORTYPE OMX_GetContentPipe( + OMX_OUT OMX_HANDLETYPE *hPipe, + OMX_IN OMX_STRING szURI); + +/** The OMX_GetComponentsOfRole method will return the number of components that support the given + role and (if the compNames field is non-NULL) the names of those components. The call will fail if + an insufficiently sized array of names is supplied. To ensure the array is sufficiently sized the + client should: + * first call this function with the compNames field NULL to determine the number of component names + * second call this function with the compNames field pointing to an array of names allocated + according to the number returned by the first call. + + The core should return from this call within 5 msec. + + @param [in] role + This is generic standard component name consisting only of component class + name and the type within that class (e.g. 'audio_decoder.aac'). + @param [inout] pNumComps + This is used both as input and output. + + If compNames is NULL, the input is ignored and the output specifies how many components support + the given role. + + If compNames is not NULL, on input it bounds the size of the input structure and + on output, it specifies the number of components string names listed within the compNames parameter. + @param [inout] compNames + If NULL this field is ignored. If non-NULL this points to an array of 128-byte strings which accepts + a list of the names of all physical components that implement the specified standard component name. + Each name is NULL terminated. numComps indicates the number of names. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole ( + OMX_IN OMX_STRING role, + OMX_INOUT OMX_U32 *pNumComps, + OMX_INOUT OMX_U8 **compNames); + +/** The OMX_GetRolesOfComponent method will return the number of roles supported by the given + component and (if the roles field is non-NULL) the names of those roles. The call will fail if + an insufficiently sized array of names is supplied. To ensure the array is sufficiently sized the + client should: + * first call this function with the roles field NULL to determine the number of role names + * second call this function with the roles field pointing to an array of names allocated + according to the number returned by the first call. + + The core should return from this call within 5 msec. + + @param [in] compName + This is the name of the component being queried about. + @param [inout] pNumRoles + This is used both as input and output. + + If roles is NULL, the input is ignored and the output specifies how many roles the component supports. + + If compNames is not NULL, on input it bounds the size of the input structure and + on output, it specifies the number of roles string names listed within the roles parameter. + @param [out] roles + If NULL this field is ignored. If non-NULL this points to an array of 128-byte strings + which accepts a list of the names of all standard components roles implemented on the + specified component name. numComps indicates the number of names. + @ingroup core + */ +OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent ( + OMX_IN OMX_STRING compName, + OMX_INOUT OMX_U32 *pNumRoles, + OMX_OUT OMX_U8 **roles); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ + diff --git a/openmax/include/khronos/OMX_CoreExt.h b/openmax/include/khronos/OMX_CoreExt.h new file mode 100644 index 0000000..1241168 --- /dev/null +++ b/openmax/include/khronos/OMX_CoreExt.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2010 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_CoreExt.h - OpenMax IL version 1.1.2 + * The OMX_CoreExt header file contains extensions to the definitions used + * by both the application and the component to access common items. + */ + +#ifndef OMX_CoreExt_h +#define OMX_CoreExt_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Each OMX header shall include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ +#include + +/** Extensions to the standard IL errors. */ +typedef enum OMX_ERROREXTTYPE +{ + OMX_ErrorInvalidMode = (OMX_S32) (OMX_ErrorKhronosExtensions + 0x00000001), + OMX_ErrorExtMax = 0x7FFFFFFF +} OMX_ERROREXTTYPE; + + +/** Event type extensions. */ +typedef enum OMX_EVENTEXTTYPE +{ + OMX_EventIndexSettingChanged = OMX_EventKhronosExtensions, /**< component signals the IL client of a change + in a param, config, or extension */ + OMX_EventExtMax = 0x7FFFFFFF +} OMX_EVENTEXTTYPE; + + +/** Enable or disable a callback event. */ +typedef struct OMX_CONFIG_CALLBACKREQUESTTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_INDEXTYPE nIndex; /**< the index the callback is requested for */ + OMX_BOOL bEnable; /**< enable (OMX_TRUE) or disable (OMX_FALSE) the callback */ +} OMX_CONFIG_CALLBACKREQUESTTYPE; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OMX_CoreExt_h */ +/* File EOF */ diff --git a/openmax/include/khronos/OMX_IVCommon.h b/openmax/include/khronos/OMX_IVCommon.h new file mode 100644 index 0000000..4c4995c --- /dev/null +++ b/openmax/include/khronos/OMX_IVCommon.h @@ -0,0 +1,920 @@ +/** + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file OMX_IVCommon.h - OpenMax IL version 1.1.2 + * The structures needed by Video and Image components to exchange + * parameters and configuration data with the components. + */ +#ifndef OMX_IVCommon_h +#define OMX_IVCommon_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * Each OMX header must include all required header files to allow the header + * to compile without errors. The includes below are required for this header + * file to compile successfully + */ + +#include + +/** @defgroup iv OpenMAX IL Imaging and Video Domain + * Common structures for OpenMAX IL Imaging and Video domains + * @{ + */ + + +/** + * Enumeration defining possible uncompressed image/video formats. + * + * ENUMS: + * Unused : Placeholder value when format is N/A + * Monochrome : black and white + * 8bitRGB332 : Red 7:5, Green 4:2, Blue 1:0 + * 12bitRGB444 : Red 11:8, Green 7:4, Blue 3:0 + * 16bitARGB4444 : Alpha 15:12, Red 11:8, Green 7:4, Blue 3:0 + * 16bitARGB1555 : Alpha 15, Red 14:10, Green 9:5, Blue 4:0 + * 16bitRGB565 : Red 15:11, Green 10:5, Blue 4:0 + * 16bitBGR565 : Blue 15:11, Green 10:5, Red 4:0 + * 18bitRGB666 : Red 17:12, Green 11:6, Blue 5:0 + * 18bitARGB1665 : Alpha 17, Red 16:11, Green 10:5, Blue 4:0 + * 19bitARGB1666 : Alpha 18, Red 17:12, Green 11:6, Blue 5:0 + * 24bitRGB888 : Red 24:16, Green 15:8, Blue 7:0 + * 24bitBGR888 : Blue 24:16, Green 15:8, Red 7:0 + * 24bitARGB1887 : Alpha 23, Red 22:15, Green 14:7, Blue 6:0 + * 25bitARGB1888 : Alpha 24, Red 23:16, Green 15:8, Blue 7:0 + * 32bitBGRA8888 : Blue 31:24, Green 23:16, Red 15:8, Alpha 7:0 + * 32bitARGB8888 : Alpha 31:24, Red 23:16, Green 15:8, Blue 7:0 + * YUV411Planar : U,Y are subsampled by a factor of 4 horizontally + * YUV411PackedPlanar : packed per payload in planar slices + * YUV420Planar : Three arrays Y,U,V. + * YUV420PackedPlanar : packed per payload in planar slices + * YUV420SemiPlanar : Two arrays, one is all Y, the other is U and V + * YUV422Planar : Three arrays Y,U,V. + * YUV422PackedPlanar : packed per payload in planar slices + * YUV422SemiPlanar : Two arrays, one is all Y, the other is U and V + * YCbYCr : Organized as 16bit YUYV (i.e. YCbYCr) + * YCrYCb : Organized as 16bit YVYU (i.e. YCrYCb) + * CbYCrY : Organized as 16bit UYVY (i.e. CbYCrY) + * CrYCbY : Organized as 16bit VYUY (i.e. CrYCbY) + * YUV444Interleaved : Each pixel contains equal parts YUV + * RawBayer8bit : SMIA camera output format + * RawBayer10bit : SMIA camera output format + * RawBayer8bitcompressed : SMIA camera output format + */ +typedef enum OMX_COLOR_FORMATTYPE { + OMX_COLOR_FormatUnused, + OMX_COLOR_FormatMonochrome, + OMX_COLOR_Format8bitRGB332, + OMX_COLOR_Format12bitRGB444, + OMX_COLOR_Format16bitARGB4444, + OMX_COLOR_Format16bitARGB1555, + OMX_COLOR_Format16bitRGB565, + OMX_COLOR_Format16bitBGR565, + OMX_COLOR_Format18bitRGB666, + OMX_COLOR_Format18bitARGB1665, + OMX_COLOR_Format19bitARGB1666, + OMX_COLOR_Format24bitRGB888, + OMX_COLOR_Format24bitBGR888, + OMX_COLOR_Format24bitARGB1887, + OMX_COLOR_Format25bitARGB1888, + OMX_COLOR_Format32bitBGRA8888, + OMX_COLOR_Format32bitARGB8888, + OMX_COLOR_FormatYUV411Planar, + OMX_COLOR_FormatYUV411PackedPlanar, + OMX_COLOR_FormatYUV420Planar, + OMX_COLOR_FormatYUV420PackedPlanar, + OMX_COLOR_FormatYUV420SemiPlanar, + OMX_COLOR_FormatYUV422Planar, + OMX_COLOR_FormatYUV422PackedPlanar, + OMX_COLOR_FormatYUV422SemiPlanar, + OMX_COLOR_FormatYCbYCr, + OMX_COLOR_FormatYCrYCb, + OMX_COLOR_FormatCbYCrY, + OMX_COLOR_FormatCrYCbY, + OMX_COLOR_FormatYUV444Interleaved, + OMX_COLOR_FormatRawBayer8bit, + OMX_COLOR_FormatRawBayer10bit, + OMX_COLOR_FormatRawBayer8bitcompressed, + OMX_COLOR_FormatL2, + OMX_COLOR_FormatL4, + OMX_COLOR_FormatL8, + OMX_COLOR_FormatL16, + OMX_COLOR_FormatL24, + OMX_COLOR_FormatL32, + OMX_COLOR_FormatYUV420PackedSemiPlanar, + OMX_COLOR_FormatYUV422PackedSemiPlanar, + OMX_COLOR_Format18BitBGR666, + OMX_COLOR_Format24BitARGB6666, + OMX_COLOR_Format24BitABGR6666, + OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_COLOR_FormatMax = 0x7FFFFFFF +} OMX_COLOR_FORMATTYPE; + + +/** + * Defines the matrix for conversion from RGB to YUV or vice versa. + * iColorMatrix should be initialized with the fixed point values + * used in converting between formats. + */ +typedef struct OMX_CONFIG_COLORCONVERSIONTYPE { + OMX_U32 nSize; /**< Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version info */ + OMX_U32 nPortIndex; /**< Port that this struct applies to */ + OMX_S32 xColorMatrix[3][3]; /**< Stored in signed Q16 format */ + OMX_S32 xColorOffset[4]; /**< Stored in signed Q16 format */ +}OMX_CONFIG_COLORCONVERSIONTYPE; + + +/** + * Structure defining percent to scale each frame dimension. For example: + * To make the width 50% larger, use fWidth = 1.5 and to make the width + * 1/2 the original size, use fWidth = 0.5 + */ +typedef struct OMX_CONFIG_SCALEFACTORTYPE { + OMX_U32 nSize; /**< Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version info */ + OMX_U32 nPortIndex; /**< Port that this struct applies to */ + OMX_S32 xWidth; /**< Fixed point value stored as Q16 */ + OMX_S32 xHeight; /**< Fixed point value stored as Q16 */ +}OMX_CONFIG_SCALEFACTORTYPE; + + +/** + * Enumeration of possible image filter types + */ +typedef enum OMX_IMAGEFILTERTYPE { + OMX_ImageFilterNone, + OMX_ImageFilterNoise, + OMX_ImageFilterEmboss, + OMX_ImageFilterNegative, + OMX_ImageFilterSketch, + OMX_ImageFilterOilPaint, + OMX_ImageFilterHatch, + OMX_ImageFilterGpen, + OMX_ImageFilterAntialias, + OMX_ImageFilterDeRing, + OMX_ImageFilterSolarize, + OMX_ImageFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ImageFilterVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_ImageFilterMax = 0x7FFFFFFF +} OMX_IMAGEFILTERTYPE; + + +/** + * Image filter configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eImageFilter : Image filter type enumeration + */ +typedef struct OMX_CONFIG_IMAGEFILTERTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_IMAGEFILTERTYPE eImageFilter; +} OMX_CONFIG_IMAGEFILTERTYPE; + + +/** + * Customized U and V for color enhancement + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bColorEnhancement : Enable/disable color enhancement + * nCustomizedU : Practical values: 16-240, range: 0-255, value set for + * U component + * nCustomizedV : Practical values: 16-240, range: 0-255, value set for + * V component + */ +typedef struct OMX_CONFIG_COLORENHANCEMENTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bColorEnhancement; + OMX_U8 nCustomizedU; + OMX_U8 nCustomizedV; +} OMX_CONFIG_COLORENHANCEMENTTYPE; + + +/** + * Define color key and color key mask + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nARGBColor : 32bit Alpha, Red, Green, Blue Color + * nARGBMask : 32bit Mask for Alpha, Red, Green, Blue channels + */ +typedef struct OMX_CONFIG_COLORKEYTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nARGBColor; + OMX_U32 nARGBMask; +} OMX_CONFIG_COLORKEYTYPE; + + +/** + * List of color blend types for pre/post processing + * + * ENUMS: + * None : No color blending present + * AlphaConstant : Function is (alpha_constant * src) + + * (1 - alpha_constant) * dst) + * AlphaPerPixel : Function is (alpha * src) + (1 - alpha) * dst) + * Alternate : Function is alternating pixels from src and dst + * And : Function is (src & dst) + * Or : Function is (src | dst) + * Invert : Function is ~src + */ +typedef enum OMX_COLORBLENDTYPE { + OMX_ColorBlendNone, + OMX_ColorBlendAlphaConstant, + OMX_ColorBlendAlphaPerPixel, + OMX_ColorBlendAlternate, + OMX_ColorBlendAnd, + OMX_ColorBlendOr, + OMX_ColorBlendInvert, + OMX_ColorBlendKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ColorBlendVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_ColorBlendMax = 0x7FFFFFFF +} OMX_COLORBLENDTYPE; + + +/** + * Color blend configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nRGBAlphaConstant : Constant global alpha values when global alpha is used + * eColorBlend : Color blend type enumeration + */ +typedef struct OMX_CONFIG_COLORBLENDTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nRGBAlphaConstant; + OMX_COLORBLENDTYPE eColorBlend; +} OMX_CONFIG_COLORBLENDTYPE; + + +/** + * Hold frame dimension + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nWidth : Frame width in pixels + * nHeight : Frame height in pixels + */ +typedef struct OMX_FRAMESIZETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nWidth; + OMX_U32 nHeight; +} OMX_FRAMESIZETYPE; + + +/** + * Rotation configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nRotation : +/- integer rotation value + */ +typedef struct OMX_CONFIG_ROTATIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nRotation; +} OMX_CONFIG_ROTATIONTYPE; + + +/** + * Possible mirroring directions for pre/post processing + * + * ENUMS: + * None : No mirroring + * Vertical : Vertical mirroring, flip on X axis + * Horizontal : Horizontal mirroring, flip on Y axis + * Both : Both vertical and horizontal mirroring + */ +typedef enum OMX_MIRRORTYPE { + OMX_MirrorNone = 0, + OMX_MirrorVertical, + OMX_MirrorHorizontal, + OMX_MirrorBoth, + OMX_MirrorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MirrorVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_MirrorMax = 0x7FFFFFFF +} OMX_MIRRORTYPE; + + +/** + * Mirroring configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eMirror : Mirror type enumeration + */ +typedef struct OMX_CONFIG_MIRRORTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_MIRRORTYPE eMirror; +} OMX_CONFIG_MIRRORTYPE; + + +/** + * Position information only + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nX : X coordinate for the point + * nY : Y coordinate for the point + */ +typedef struct OMX_CONFIG_POINTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nX; + OMX_S32 nY; +} OMX_CONFIG_POINTTYPE; + + +/** + * Frame size plus position + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nLeft : X Coordinate of the top left corner of the rectangle + * nTop : Y Coordinate of the top left corner of the rectangle + * nWidth : Width of the rectangle + * nHeight : Height of the rectangle + */ +typedef struct OMX_CONFIG_RECTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nLeft; + OMX_S32 nTop; + OMX_U32 nWidth; + OMX_U32 nHeight; +} OMX_CONFIG_RECTTYPE; + + +/** + * Deblocking state; it is required to be set up before starting the codec + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bDeblocking : Enable/disable deblocking mode + */ +typedef struct OMX_PARAM_DEBLOCKINGTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bDeblocking; +} OMX_PARAM_DEBLOCKINGTYPE; + + +/** + * Stabilization state + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bStab : Enable/disable frame stabilization state + */ +typedef struct OMX_CONFIG_FRAMESTABTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bStab; +} OMX_CONFIG_FRAMESTABTYPE; + + +/** + * White Balance control type + * + * STRUCT MEMBERS: + * SunLight : Referenced in JSR-234 + * Flash : Optimal for device's integrated flash + */ +typedef enum OMX_WHITEBALCONTROLTYPE { + OMX_WhiteBalControlOff = 0, + OMX_WhiteBalControlAuto, + OMX_WhiteBalControlSunLight, + OMX_WhiteBalControlCloudy, + OMX_WhiteBalControlShade, + OMX_WhiteBalControlTungsten, + OMX_WhiteBalControlFluorescent, + OMX_WhiteBalControlIncandescent, + OMX_WhiteBalControlFlash, + OMX_WhiteBalControlHorizon, + OMX_WhiteBalControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_WhiteBalControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_WhiteBalControlMax = 0x7FFFFFFF +} OMX_WHITEBALCONTROLTYPE; + + +/** + * White Balance control configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eWhiteBalControl : White balance enumeration + */ +typedef struct OMX_CONFIG_WHITEBALCONTROLTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_WHITEBALCONTROLTYPE eWhiteBalControl; +} OMX_CONFIG_WHITEBALCONTROLTYPE; + + +/** + * Exposure control type + */ +typedef enum OMX_EXPOSURECONTROLTYPE { + OMX_ExposureControlOff = 0, + OMX_ExposureControlAuto, + OMX_ExposureControlNight, + OMX_ExposureControlBackLight, + OMX_ExposureControlSpotLight, + OMX_ExposureControlSports, + OMX_ExposureControlSnow, + OMX_ExposureControlBeach, + OMX_ExposureControlLargeAperture, + OMX_ExposureControlSmallApperture, + OMX_ExposureControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_ExposureControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_ExposureControlMax = 0x7FFFFFFF +} OMX_EXPOSURECONTROLTYPE; + + +/** + * White Balance control configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eExposureControl : Exposure control enumeration + */ +typedef struct OMX_CONFIG_EXPOSURECONTROLTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_EXPOSURECONTROLTYPE eExposureControl; +} OMX_CONFIG_EXPOSURECONTROLTYPE; + + +/** + * Defines sensor supported mode. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nFrameRate : Single shot mode is indicated by a 0 + * bOneShot : Enable for single shot, disable for streaming + * sFrameSize : Framesize + */ +typedef struct OMX_PARAM_SENSORMODETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nFrameRate; + OMX_BOOL bOneShot; + OMX_FRAMESIZETYPE sFrameSize; +} OMX_PARAM_SENSORMODETYPE; + + +/** + * Defines contrast level + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nContrast : Values allowed for contrast -100 to 100, zero means no change + */ +typedef struct OMX_CONFIG_CONTRASTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nContrast; +} OMX_CONFIG_CONTRASTTYPE; + + +/** + * Defines brightness level + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nBrightness : 0-100% + */ +typedef struct OMX_CONFIG_BRIGHTNESSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nBrightness; +} OMX_CONFIG_BRIGHTNESSTYPE; + + +/** + * Defines backlight level configuration for a video sink, e.g. LCD panel + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nBacklight : Values allowed for backlight 0-100% + * nTimeout : Number of milliseconds before backlight automatically turns + * off. A value of 0x0 disables backight timeout + */ +typedef struct OMX_CONFIG_BACKLIGHTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nBacklight; + OMX_U32 nTimeout; +} OMX_CONFIG_BACKLIGHTTYPE; + + +/** + * Defines setting for Gamma + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nGamma : Values allowed for gamma -100 to 100, zero means no change + */ +typedef struct OMX_CONFIG_GAMMATYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nGamma; +} OMX_CONFIG_GAMMATYPE; + + +/** + * Define for setting saturation + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nSaturation : Values allowed for saturation -100 to 100, zero means + * no change + */ +typedef struct OMX_CONFIG_SATURATIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nSaturation; +} OMX_CONFIG_SATURATIONTYPE; + + +/** + * Define for setting Lightness + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nLightness : Values allowed for lightness -100 to 100, zero means no + * change + */ +typedef struct OMX_CONFIG_LIGHTNESSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_S32 nLightness; +} OMX_CONFIG_LIGHTNESSTYPE; + + +/** + * Plane blend configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Index of input port associated with the plane. + * nDepth : Depth of the plane in relation to the screen. Higher + * numbered depths are "behind" lower number depths. + * This number defaults to the Port Index number. + * nAlpha : Transparency blending component for the entire plane. + * See blending modes for more detail. + */ +typedef struct OMX_CONFIG_PLANEBLENDTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nDepth; + OMX_U32 nAlpha; +} OMX_CONFIG_PLANEBLENDTYPE; + + +/** + * Define interlace type + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bEnable : Enable control variable for this functionality + * (see below) + * nInterleavePortIndex : Index of input or output port associated with + * the interleaved plane. + * pPlanarPortIndexes[4] : Index of input or output planar ports. + */ +typedef struct OMX_PARAM_INTERLEAVETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnable; + OMX_U32 nInterleavePortIndex; +} OMX_PARAM_INTERLEAVETYPE; + + +/** + * Defines the picture effect used for an input picture + */ +typedef enum OMX_TRANSITIONEFFECTTYPE { + OMX_EffectNone, + OMX_EffectFadeFromBlack, + OMX_EffectFadeToBlack, + OMX_EffectUnspecifiedThroughConstantColor, + OMX_EffectDissolve, + OMX_EffectWipe, + OMX_EffectUnspecifiedMixOfTwoScenes, + OMX_EffectKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_EffectVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_EffectMax = 0x7FFFFFFF +} OMX_TRANSITIONEFFECTTYPE; + + +/** + * Structure used to configure current transition effect + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eEffect : Effect to enable + */ +typedef struct OMX_CONFIG_TRANSITIONEFFECTTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_TRANSITIONEFFECTTYPE eEffect; +} OMX_CONFIG_TRANSITIONEFFECTTYPE; + + +/** + * Defines possible data unit types for encoded video data. The data unit + * types are used both for encoded video input for playback as well as + * encoded video output from recording. + */ +typedef enum OMX_DATAUNITTYPE { + OMX_DataUnitCodedPicture, + OMX_DataUnitVideoSegment, + OMX_DataUnitSeveralSegments, + OMX_DataUnitArbitraryStreamSection, + OMX_DataUnitKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_DataUnitVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_DataUnitMax = 0x7FFFFFFF +} OMX_DATAUNITTYPE; + + +/** + * Defines possible encapsulation types for coded video data unit. The + * encapsulation information is used both for encoded video input for + * playback as well as encoded video output from recording. + */ +typedef enum OMX_DATAUNITENCAPSULATIONTYPE { + OMX_DataEncapsulationElementaryStream, + OMX_DataEncapsulationGenericPayload, + OMX_DataEncapsulationRtpPayload, + OMX_DataEncapsulationKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_DataEncapsulationVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_DataEncapsulationMax = 0x7FFFFFFF +} OMX_DATAUNITENCAPSULATIONTYPE; + + +/** + * Structure used to configure the type of being decoded/encoded + */ +typedef struct OMX_PARAM_DATAUNITTYPE { + OMX_U32 nSize; /**< Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_DATAUNITTYPE eUnitType; + OMX_DATAUNITENCAPSULATIONTYPE eEncapsulationType; +} OMX_PARAM_DATAUNITTYPE; + + +/** + * Defines dither types + */ +typedef enum OMX_DITHERTYPE { + OMX_DitherNone, + OMX_DitherOrdered, + OMX_DitherErrorDiffusion, + OMX_DitherOther, + OMX_DitherKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_DitherVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_DitherMax = 0x7FFFFFFF +} OMX_DITHERTYPE; + + +/** + * Structure used to configure current type of dithering + */ +typedef struct OMX_CONFIG_DITHERTYPE { + OMX_U32 nSize; /**< Size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_DITHERTYPE eDither; /**< Type of dithering to use */ +} OMX_CONFIG_DITHERTYPE; + +typedef struct OMX_CONFIG_CAPTUREMODETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; /**< Port that this structure applies to */ + OMX_BOOL bContinuous; /**< If true then ignore frame rate and emit capture + * data as fast as possible (otherwise obey port's frame rate). */ + OMX_BOOL bFrameLimited; /**< If true then terminate capture after the port emits the + * specified number of frames (otherwise the port does not + * terminate the capture until instructed to do so by the client). + * Even if set, the client may manually terminate the capture prior + * to reaching the limit. */ + OMX_U32 nFrameLimit; /**< Limit on number of frames emitted during a capture (only + * valid if bFrameLimited is set). */ +} OMX_CONFIG_CAPTUREMODETYPE; + +typedef enum OMX_METERINGTYPE { + + OMX_MeteringModeAverage, /**< Center-weighted average metering. */ + OMX_MeteringModeSpot, /**< Spot (partial) metering. */ + OMX_MeteringModeMatrix, /**< Matrix or evaluative metering. */ + + OMX_MeteringKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_MeteringVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_EVModeMax = 0x7fffffff +} OMX_METERINGTYPE; + +typedef struct OMX_CONFIG_EXPOSUREVALUETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_METERINGTYPE eMetering; + OMX_S32 xEVCompensation; /**< Fixed point value stored as Q16 */ + OMX_U32 nApertureFNumber; /**< e.g. nApertureFNumber = 2 implies "f/2" - Q16 format */ + OMX_BOOL bAutoAperture; /**< Whether aperture number is defined automatically */ + OMX_U32 nShutterSpeedMsec; /**< Shutterspeed in milliseconds */ + OMX_BOOL bAutoShutterSpeed; /**< Whether shutter speed is defined automatically */ + OMX_U32 nSensitivity; /**< e.g. nSensitivity = 100 implies "ISO 100" */ + OMX_BOOL bAutoSensitivity; /**< Whether sensitivity is defined automatically */ +} OMX_CONFIG_EXPOSUREVALUETYPE; + +/** + * Focus region configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bCenter : Use center region as focus region of interest + * bLeft : Use left region as focus region of interest + * bRight : Use right region as focus region of interest + * bTop : Use top region as focus region of interest + * bBottom : Use bottom region as focus region of interest + * bTopLeft : Use top left region as focus region of interest + * bTopRight : Use top right region as focus region of interest + * bBottomLeft : Use bottom left region as focus region of interest + * bBottomRight : Use bottom right region as focus region of interest + */ +typedef struct OMX_CONFIG_FOCUSREGIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bCenter; + OMX_BOOL bLeft; + OMX_BOOL bRight; + OMX_BOOL bTop; + OMX_BOOL bBottom; + OMX_BOOL bTopLeft; + OMX_BOOL bTopRight; + OMX_BOOL bBottomLeft; + OMX_BOOL bBottomRight; +} OMX_CONFIG_FOCUSREGIONTYPE; + +/** + * Focus Status type + */ +typedef enum OMX_FOCUSSTATUSTYPE { + OMX_FocusStatusOff = 0, + OMX_FocusStatusRequest, + OMX_FocusStatusReached, + OMX_FocusStatusUnableToReach, + OMX_FocusStatusLost, + OMX_FocusStatusKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_FocusStatusVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_FocusStatusMax = 0x7FFFFFFF +} OMX_FOCUSSTATUSTYPE; + +/** + * Focus status configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFocusStatus : Specifies the focus status + * bCenterStatus : Use center region as focus region of interest + * bLeftStatus : Use left region as focus region of interest + * bRightStatus : Use right region as focus region of interest + * bTopStatus : Use top region as focus region of interest + * bBottomStatus : Use bottom region as focus region of interest + * bTopLeftStatus : Use top left region as focus region of interest + * bTopRightStatus : Use top right region as focus region of interest + * bBottomLeftStatus : Use bottom left region as focus region of interest + * bBottomRightStatus : Use bottom right region as focus region of interest + */ +typedef struct OMX_PARAM_FOCUSSTATUSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_FOCUSSTATUSTYPE eFocusStatus; + OMX_BOOL bCenterStatus; + OMX_BOOL bLeftStatus; + OMX_BOOL bRightStatus; + OMX_BOOL bTopStatus; + OMX_BOOL bBottomStatus; + OMX_BOOL bTopLeftStatus; + OMX_BOOL bTopRightStatus; + OMX_BOOL bBottomLeftStatus; + OMX_BOOL bBottomRightStatus; +} OMX_PARAM_FOCUSSTATUSTYPE; + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ diff --git a/openmax/include/khronos/OMX_Image.h b/openmax/include/khronos/OMX_Image.h new file mode 100644 index 0000000..a6d4666 --- /dev/null +++ b/openmax/include/khronos/OMX_Image.h @@ -0,0 +1,328 @@ +/** + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @file OMX_Image.h - OpenMax IL version 1.1.2 + * The structures needed by Image components to exchange parameters and + * configuration data with the components. + */ +#ifndef OMX_Image_h +#define OMX_Image_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/** + * Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include + +/** @defgroup imaging OpenMAX IL Imaging Domain + * @ingroup iv + * Structures for OpenMAX IL Imaging domain + * @{ + */ + +/** + * Enumeration used to define the possible image compression coding. + */ +typedef enum OMX_IMAGE_CODINGTYPE { + OMX_IMAGE_CodingUnused, /**< Value when format is N/A */ + OMX_IMAGE_CodingAutoDetect, /**< Auto detection of image format */ + OMX_IMAGE_CodingJPEG, /**< JPEG/JFIF image format */ + OMX_IMAGE_CodingJPEG2K, /**< JPEG 2000 image format */ + OMX_IMAGE_CodingEXIF, /**< EXIF image format */ + OMX_IMAGE_CodingTIFF, /**< TIFF image format */ + OMX_IMAGE_CodingGIF, /**< Graphics image format */ + OMX_IMAGE_CodingPNG, /**< PNG image format */ + OMX_IMAGE_CodingLZW, /**< LZW image format */ + OMX_IMAGE_CodingBMP, /**< Windows Bitmap format */ + OMX_IMAGE_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_IMAGE_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_IMAGE_CodingMax = 0x7FFFFFFF +} OMX_IMAGE_CODINGTYPE; + + +/** + * Data structure used to define an image path. The number of image paths + * for input and output will vary by type of the image component. + * + * Input (aka Source) : Zero Inputs, one Output, + * Splitter : One Input, 2 or more Outputs, + * Processing Element : One Input, one output, + * Mixer : 2 or more inputs, one output, + * Output (aka Sink) : One Input, zero outputs. + * + * The PortDefinition structure is used to define all of the parameters + * necessary for the compliant component to setup an input or an output + * image path. If additional vendor specific data is required, it should + * be transmitted to the component using the CustomCommand function. + * Compliant components will prepopulate this structure with optimal + * values during the OMX_GetParameter() command. + * + * STRUCT MEMBERS: + * cMIMEType : MIME type of data for the port + * pNativeRender : Platform specific reference for a display if a + * sync, otherwise this field is 0 + * nFrameWidth : Width of frame to be used on port if + * uncompressed format is used. Use 0 for + * unknown, don't care or variable + * nFrameHeight : Height of frame to be used on port if + * uncompressed format is used. Use 0 for + * unknown, don't care or variable + * nStride : Number of bytes per span of an image (i.e. + * indicates the number of bytes to get from + * span N to span N+1, where negative stride + * indicates the image is bottom up + * nSliceHeight : Height used when encoding in slices + * bFlagErrorConcealment : Turns on error concealment if it is supported by + * the OMX component + * eCompressionFormat : Compression format used in this instance of + * the component. When OMX_IMAGE_CodingUnused is + * specified, eColorFormat is valid + * eColorFormat : Decompressed format used by this component + * pNativeWindow : Platform specific reference for a window object if a + * display sink , otherwise this field is 0x0. + */ +typedef struct OMX_IMAGE_PORTDEFINITIONTYPE { + OMX_STRING cMIMEType; + OMX_NATIVE_DEVICETYPE pNativeRender; + OMX_U32 nFrameWidth; + OMX_U32 nFrameHeight; + OMX_S32 nStride; + OMX_U32 nSliceHeight; + OMX_BOOL bFlagErrorConcealment; + OMX_IMAGE_CODINGTYPE eCompressionFormat; + OMX_COLOR_FORMATTYPE eColorFormat; + OMX_NATIVE_WINDOWTYPE pNativeWindow; +} OMX_IMAGE_PORTDEFINITIONTYPE; + + +/** + * Port format parameter. This structure is used to enumerate the various + * data input/output format supported by the port. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Indicates which port to set + * nIndex : Indicates the enumeration index for the format from + * 0x0 to N-1 + * eCompressionFormat : Compression format used in this instance of the + * component. When OMX_IMAGE_CodingUnused is specified, + * eColorFormat is valid + * eColorFormat : Decompressed format used by this component + */ +typedef struct OMX_IMAGE_PARAM_PORTFORMATTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nIndex; + OMX_IMAGE_CODINGTYPE eCompressionFormat; + OMX_COLOR_FORMATTYPE eColorFormat; +} OMX_IMAGE_PARAM_PORTFORMATTYPE; + + +/** + * Flash control type + * + * ENUMS + * Torch : Flash forced constantly on + */ +typedef enum OMX_IMAGE_FLASHCONTROLTYPE { + OMX_IMAGE_FlashControlOn = 0, + OMX_IMAGE_FlashControlOff, + OMX_IMAGE_FlashControlAuto, + OMX_IMAGE_FlashControlRedEyeReduction, + OMX_IMAGE_FlashControlFillin, + OMX_IMAGE_FlashControlTorch, + OMX_IMAGE_FlashControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_IMAGE_FlashControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_IMAGE_FlashControlMax = 0x7FFFFFFF +} OMX_IMAGE_FLASHCONTROLTYPE; + + +/** + * Flash control configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFlashControl : Flash control type + */ +typedef struct OMX_IMAGE_PARAM_FLASHCONTROLTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_IMAGE_FLASHCONTROLTYPE eFlashControl; +} OMX_IMAGE_PARAM_FLASHCONTROLTYPE; + + +/** + * Focus control type + */ +typedef enum OMX_IMAGE_FOCUSCONTROLTYPE { + OMX_IMAGE_FocusControlOn = 0, + OMX_IMAGE_FocusControlOff, + OMX_IMAGE_FocusControlAuto, + OMX_IMAGE_FocusControlAutoLock, + OMX_IMAGE_FocusControlKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_IMAGE_FocusControlVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_IMAGE_FocusControlMax = 0x7FFFFFFF +} OMX_IMAGE_FOCUSCONTROLTYPE; + + +/** + * Focus control configuration + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFocusControl : Focus control + * nFocusSteps : Focus can take on values from 0 mm to infinity. + * Interest is only in number of steps over this range. + * nFocusStepIndex : Current focus step index + */ +typedef struct OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_IMAGE_FOCUSCONTROLTYPE eFocusControl; + OMX_U32 nFocusSteps; + OMX_U32 nFocusStepIndex; +} OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE; + + +/** + * Q Factor for JPEG compression, which controls the tradeoff between image + * quality and size. Q Factor provides a more simple means of controlling + * JPEG compression quality, without directly programming Quantization + * tables for chroma and luma + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nQFactor : JPEG Q factor value in the range of 1-100. A factor of 1 + * produces the smallest, worst quality images, and a factor + * of 100 produces the largest, best quality images. A + * typical default is 75 for small good quality images + */ +typedef struct OMX_IMAGE_PARAM_QFACTORTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nQFactor; +} OMX_IMAGE_PARAM_QFACTORTYPE; + +/** + * Quantization table type + */ + +typedef enum OMX_IMAGE_QUANTIZATIONTABLETYPE { + OMX_IMAGE_QuantizationTableLuma = 0, + OMX_IMAGE_QuantizationTableChroma, + OMX_IMAGE_QuantizationTableChromaCb, + OMX_IMAGE_QuantizationTableChromaCr, + OMX_IMAGE_QuantizationTableKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_IMAGE_QuantizationTableVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_IMAGE_QuantizationTableMax = 0x7FFFFFFF +} OMX_IMAGE_QUANTIZATIONTABLETYPE; + +/** + * JPEG quantization tables are used to determine DCT compression for + * YUV data, as an alternative to specifying Q factor, providing exact + * control of compression + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eQuantizationTable : Quantization table type + * nQuantizationMatrix[64] : JPEG quantization table of coefficients stored + * in increasing columns then by rows of data (i.e. + * row 1, ... row 8). Quantization values are in + * the range 0-255 and stored in linear order + * (i.e. the component will zig-zag the + * quantization table data if required internally) + */ +typedef struct OMX_IMAGE_PARAM_QUANTIZATIONTABLETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_IMAGE_QUANTIZATIONTABLETYPE eQuantizationTable; + OMX_U8 nQuantizationMatrix[64]; +} OMX_IMAGE_PARAM_QUANTIZATIONTABLETYPE; + + +/** + * Huffman table type, the same Huffman table is applied for chroma and + * luma component + */ +typedef enum OMX_IMAGE_HUFFMANTABLETYPE { + OMX_IMAGE_HuffmanTableAC = 0, + OMX_IMAGE_HuffmanTableDC, + OMX_IMAGE_HuffmanTableACLuma, + OMX_IMAGE_HuffmanTableACChroma, + OMX_IMAGE_HuffmanTableDCLuma, + OMX_IMAGE_HuffmanTableDCChroma, + OMX_IMAGE_HuffmanTableKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_IMAGE_HuffmanTableVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_IMAGE_HuffmanTableMax = 0x7FFFFFFF +} OMX_IMAGE_HUFFMANTABLETYPE; + +/** + * JPEG Huffman table + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eHuffmanTable : Huffman table type + * nNumberOfHuffmanCodeOfLength[16] : 0-16, number of Huffman codes of each + * possible length + * nHuffmanTable[256] : 0-255, the size used for AC and DC + * HuffmanTable are 16 and 162 + */ +typedef struct OMX_IMAGE_PARAM_HUFFMANTTABLETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_IMAGE_HUFFMANTABLETYPE eHuffmanTable; + OMX_U8 nNumberOfHuffmanCodeOfLength[16]; + OMX_U8 nHuffmanTable[256]; +}OMX_IMAGE_PARAM_HUFFMANTTABLETYPE; + +/** @} */ +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ diff --git a/openmax/include/khronos/OMX_ImageExt.h b/openmax/include/khronos/OMX_ImageExt.h new file mode 100644 index 0000000..664a084 --- /dev/null +++ b/openmax/include/khronos/OMX_ImageExt.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_ImageExt.h - OpenMax IL version 1.1.2 + * The OMX_ImageExt header file contains extensions to the + * definitions used by both the application and the component to + * access image items. + */ + +#ifndef OMX_ImageExt_h +#define OMX_ImageExt_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Each OMX header shall include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ +#include + +/** Enum for standard image codingtype extensions */ +typedef enum OMX_IMAGE_CODINGEXTTYPE { + OMX_IMAGE_CodingExtUnused = OMX_IMAGE_CodingKhronosExtensions, + OMX_IMAGE_CodingWEBP, /**< WebP image format */ +} OMX_IMAGE_CODINGEXTTYPE; + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OMX_ImageExt_h */ +/* File EOF */ diff --git a/openmax/include/khronos/OMX_Index.h b/openmax/include/khronos/OMX_Index.h new file mode 100644 index 0000000..44d4ea7 --- /dev/null +++ b/openmax/include/khronos/OMX_Index.h @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** @file OMX_Index.h - OpenMax IL version 1.1.2 + * The OMX_Index header file contains the definitions for both applications + * and components . + */ + + +#ifndef OMX_Index_h +#define OMX_Index_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ +#include + + +/** The OMX_INDEXTYPE enumeration is used to select a structure when either + * getting or setting parameters and/or configuration data. Each entry in + * this enumeration maps to an OMX specified structure. When the + * OMX_GetParameter, OMX_SetParameter, OMX_GetConfig or OMX_SetConfig methods + * are used, the second parameter will always be an entry from this enumeration + * and the third entry will be the structure shown in the comments for the entry. + * For example, if the application is initializing a cropping function, the + * OMX_SetConfig command would have OMX_IndexConfigCommonInputCrop as the second parameter + * and would send a pointer to an initialized OMX_RECTTYPE structure as the + * third parameter. + * + * The enumeration entries named with the OMX_Config prefix are sent using + * the OMX_SetConfig command and the enumeration entries named with the + * OMX_PARAM_ prefix are sent using the OMX_SetParameter command. + */ +typedef enum OMX_INDEXTYPE { + + OMX_IndexComponentStartUnused = 0x01000000, + OMX_IndexParamPriorityMgmt, /**< reference: OMX_PRIORITYMGMTTYPE */ + OMX_IndexParamAudioInit, /**< reference: OMX_PORT_PARAM_TYPE */ + OMX_IndexParamImageInit, /**< reference: OMX_PORT_PARAM_TYPE */ + OMX_IndexParamVideoInit, /**< reference: OMX_PORT_PARAM_TYPE */ + OMX_IndexParamOtherInit, /**< reference: OMX_PORT_PARAM_TYPE */ + OMX_IndexParamNumAvailableStreams, /**< reference: OMX_PARAM_U32TYPE */ + OMX_IndexParamActiveStream, /**< reference: OMX_PARAM_U32TYPE */ + OMX_IndexParamSuspensionPolicy, /**< reference: OMX_PARAM_SUSPENSIONPOLICYTYPE */ + OMX_IndexParamComponentSuspended, /**< reference: OMX_PARAM_SUSPENSIONTYPE */ + OMX_IndexConfigCapturing, /**< reference: OMX_CONFIG_BOOLEANTYPE */ + OMX_IndexConfigCaptureMode, /**< reference: OMX_CONFIG_CAPTUREMODETYPE */ + OMX_IndexAutoPauseAfterCapture, /**< reference: OMX_CONFIG_BOOLEANTYPE */ + OMX_IndexParamContentURI, /**< reference: OMX_PARAM_CONTENTURITYPE */ + OMX_IndexParamCustomContentPipe, /**< reference: OMX_PARAM_CONTENTPIPETYPE */ + OMX_IndexParamDisableResourceConcealment, /**< reference: OMX_RESOURCECONCEALMENTTYPE */ + OMX_IndexConfigMetadataItemCount, /**< reference: OMX_CONFIG_METADATAITEMCOUNTTYPE */ + OMX_IndexConfigContainerNodeCount, /**< reference: OMX_CONFIG_CONTAINERNODECOUNTTYPE */ + OMX_IndexConfigMetadataItem, /**< reference: OMX_CONFIG_METADATAITEMTYPE */ + OMX_IndexConfigCounterNodeID, /**< reference: OMX_CONFIG_CONTAINERNODEIDTYPE */ + OMX_IndexParamMetadataFilterType, /**< reference: OMX_PARAM_METADATAFILTERTYPE */ + OMX_IndexParamMetadataKeyFilter, /**< reference: OMX_PARAM_METADATAFILTERTYPE */ + OMX_IndexConfigPriorityMgmt, /**< reference: OMX_PRIORITYMGMTTYPE */ + OMX_IndexParamStandardComponentRole, /**< reference: OMX_PARAM_COMPONENTROLETYPE */ + + OMX_IndexPortStartUnused = 0x02000000, + OMX_IndexParamPortDefinition, /**< reference: OMX_PARAM_PORTDEFINITIONTYPE */ + OMX_IndexParamCompBufferSupplier, /**< reference: OMX_PARAM_BUFFERSUPPLIERTYPE */ + OMX_IndexReservedStartUnused = 0x03000000, + + /* Audio parameters and configurations */ + OMX_IndexAudioStartUnused = 0x04000000, + OMX_IndexParamAudioPortFormat, /**< reference: OMX_AUDIO_PARAM_PORTFORMATTYPE */ + OMX_IndexParamAudioPcm, /**< reference: OMX_AUDIO_PARAM_PCMMODETYPE */ + OMX_IndexParamAudioAac, /**< reference: OMX_AUDIO_PARAM_AACPROFILETYPE */ + OMX_IndexParamAudioRa, /**< reference: OMX_AUDIO_PARAM_RATYPE */ + OMX_IndexParamAudioMp3, /**< reference: OMX_AUDIO_PARAM_MP3TYPE */ + OMX_IndexParamAudioAdpcm, /**< reference: OMX_AUDIO_PARAM_ADPCMTYPE */ + OMX_IndexParamAudioG723, /**< reference: OMX_AUDIO_PARAM_G723TYPE */ + OMX_IndexParamAudioG729, /**< reference: OMX_AUDIO_PARAM_G729TYPE */ + OMX_IndexParamAudioAmr, /**< reference: OMX_AUDIO_PARAM_AMRTYPE */ + OMX_IndexParamAudioWma, /**< reference: OMX_AUDIO_PARAM_WMATYPE */ + OMX_IndexParamAudioSbc, /**< reference: OMX_AUDIO_PARAM_SBCTYPE */ + OMX_IndexParamAudioMidi, /**< reference: OMX_AUDIO_PARAM_MIDITYPE */ + OMX_IndexParamAudioGsm_FR, /**< reference: OMX_AUDIO_PARAM_GSMFRTYPE */ + OMX_IndexParamAudioMidiLoadUserSound, /**< reference: OMX_AUDIO_PARAM_MIDILOADUSERSOUNDTYPE */ + OMX_IndexParamAudioG726, /**< reference: OMX_AUDIO_PARAM_G726TYPE */ + OMX_IndexParamAudioGsm_EFR, /**< reference: OMX_AUDIO_PARAM_GSMEFRTYPE */ + OMX_IndexParamAudioGsm_HR, /**< reference: OMX_AUDIO_PARAM_GSMHRTYPE */ + OMX_IndexParamAudioPdc_FR, /**< reference: OMX_AUDIO_PARAM_PDCFRTYPE */ + OMX_IndexParamAudioPdc_EFR, /**< reference: OMX_AUDIO_PARAM_PDCEFRTYPE */ + OMX_IndexParamAudioPdc_HR, /**< reference: OMX_AUDIO_PARAM_PDCHRTYPE */ + OMX_IndexParamAudioTdma_FR, /**< reference: OMX_AUDIO_PARAM_TDMAFRTYPE */ + OMX_IndexParamAudioTdma_EFR, /**< reference: OMX_AUDIO_PARAM_TDMAEFRTYPE */ + OMX_IndexParamAudioQcelp8, /**< reference: OMX_AUDIO_PARAM_QCELP8TYPE */ + OMX_IndexParamAudioQcelp13, /**< reference: OMX_AUDIO_PARAM_QCELP13TYPE */ + OMX_IndexParamAudioEvrc, /**< reference: OMX_AUDIO_PARAM_EVRCTYPE */ + OMX_IndexParamAudioSmv, /**< reference: OMX_AUDIO_PARAM_SMVTYPE */ + OMX_IndexParamAudioVorbis, /**< reference: OMX_AUDIO_PARAM_VORBISTYPE */ + + OMX_IndexConfigAudioMidiImmediateEvent, /**< reference: OMX_AUDIO_CONFIG_MIDIIMMEDIATEEVENTTYPE */ + OMX_IndexConfigAudioMidiControl, /**< reference: OMX_AUDIO_CONFIG_MIDICONTROLTYPE */ + OMX_IndexConfigAudioMidiSoundBankProgram, /**< reference: OMX_AUDIO_CONFIG_MIDISOUNDBANKPROGRAMTYPE */ + OMX_IndexConfigAudioMidiStatus, /**< reference: OMX_AUDIO_CONFIG_MIDISTATUSTYPE */ + OMX_IndexConfigAudioMidiMetaEvent, /**< reference: OMX_AUDIO_CONFIG_MIDIMETAEVENTTYPE */ + OMX_IndexConfigAudioMidiMetaEventData, /**< reference: OMX_AUDIO_CONFIG_MIDIMETAEVENTDATATYPE */ + OMX_IndexConfigAudioVolume, /**< reference: OMX_AUDIO_CONFIG_VOLUMETYPE */ + OMX_IndexConfigAudioBalance, /**< reference: OMX_AUDIO_CONFIG_BALANCETYPE */ + OMX_IndexConfigAudioChannelMute, /**< reference: OMX_AUDIO_CONFIG_CHANNELMUTETYPE */ + OMX_IndexConfigAudioMute, /**< reference: OMX_AUDIO_CONFIG_MUTETYPE */ + OMX_IndexConfigAudioLoudness, /**< reference: OMX_AUDIO_CONFIG_LOUDNESSTYPE */ + OMX_IndexConfigAudioEchoCancelation, /**< reference: OMX_AUDIO_CONFIG_ECHOCANCELATIONTYPE */ + OMX_IndexConfigAudioNoiseReduction, /**< reference: OMX_AUDIO_CONFIG_NOISEREDUCTIONTYPE */ + OMX_IndexConfigAudioBass, /**< reference: OMX_AUDIO_CONFIG_BASSTYPE */ + OMX_IndexConfigAudioTreble, /**< reference: OMX_AUDIO_CONFIG_TREBLETYPE */ + OMX_IndexConfigAudioStereoWidening, /**< reference: OMX_AUDIO_CONFIG_STEREOWIDENINGTYPE */ + OMX_IndexConfigAudioChorus, /**< reference: OMX_AUDIO_CONFIG_CHORUSTYPE */ + OMX_IndexConfigAudioEqualizer, /**< reference: OMX_AUDIO_CONFIG_EQUALIZERTYPE */ + OMX_IndexConfigAudioReverberation, /**< reference: OMX_AUDIO_CONFIG_REVERBERATIONTYPE */ + OMX_IndexConfigAudioChannelVolume, /**< reference: OMX_AUDIO_CONFIG_CHANNELVOLUMETYPE */ + + /* Image specific parameters and configurations */ + OMX_IndexImageStartUnused = 0x05000000, + OMX_IndexParamImagePortFormat, /**< reference: OMX_IMAGE_PARAM_PORTFORMATTYPE */ + OMX_IndexParamFlashControl, /**< reference: OMX_IMAGE_PARAM_FLASHCONTROLTYPE */ + OMX_IndexConfigFocusControl, /**< reference: OMX_IMAGE_CONFIG_FOCUSCONTROLTYPE */ + OMX_IndexParamQFactor, /**< reference: OMX_IMAGE_PARAM_QFACTORTYPE */ + OMX_IndexParamQuantizationTable, /**< reference: OMX_IMAGE_PARAM_QUANTIZATIONTABLETYPE */ + OMX_IndexParamHuffmanTable, /**< reference: OMX_IMAGE_PARAM_HUFFMANTTABLETYPE */ + OMX_IndexConfigFlashControl, /**< reference: OMX_IMAGE_PARAM_FLASHCONTROLTYPE */ + + /* Video specific parameters and configurations */ + OMX_IndexVideoStartUnused = 0x06000000, + OMX_IndexParamVideoPortFormat, /**< reference: OMX_VIDEO_PARAM_PORTFORMATTYPE */ + OMX_IndexParamVideoQuantization, /**< reference: OMX_VIDEO_PARAM_QUANTIZATIONTYPE */ + OMX_IndexParamVideoFastUpdate, /**< reference: OMX_VIDEO_PARAM_VIDEOFASTUPDATETYPE */ + OMX_IndexParamVideoBitrate, /**< reference: OMX_VIDEO_PARAM_BITRATETYPE */ + OMX_IndexParamVideoMotionVector, /**< reference: OMX_VIDEO_PARAM_MOTIONVECTORTYPE */ + OMX_IndexParamVideoIntraRefresh, /**< reference: OMX_VIDEO_PARAM_INTRAREFRESHTYPE */ + OMX_IndexParamVideoErrorCorrection, /**< reference: OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE */ + OMX_IndexParamVideoVBSMC, /**< reference: OMX_VIDEO_PARAM_VBSMCTYPE */ + OMX_IndexParamVideoMpeg2, /**< reference: OMX_VIDEO_PARAM_MPEG2TYPE */ + OMX_IndexParamVideoMpeg4, /**< reference: OMX_VIDEO_PARAM_MPEG4TYPE */ + OMX_IndexParamVideoWmv, /**< reference: OMX_VIDEO_PARAM_WMVTYPE */ + OMX_IndexParamVideoRv, /**< reference: OMX_VIDEO_PARAM_RVTYPE */ + OMX_IndexParamVideoAvc, /**< reference: OMX_VIDEO_PARAM_AVCTYPE */ + OMX_IndexParamVideoH263, /**< reference: OMX_VIDEO_PARAM_H263TYPE */ + OMX_IndexParamVideoProfileLevelQuerySupported, /**< reference: OMX_VIDEO_PARAM_PROFILELEVELTYPE */ + OMX_IndexParamVideoProfileLevelCurrent, /**< reference: OMX_VIDEO_PARAM_PROFILELEVELTYPE */ + OMX_IndexConfigVideoBitrate, /**< reference: OMX_VIDEO_CONFIG_BITRATETYPE */ + OMX_IndexConfigVideoFramerate, /**< reference: OMX_CONFIG_FRAMERATETYPE */ + OMX_IndexConfigVideoIntraVOPRefresh, /**< reference: OMX_CONFIG_INTRAREFRESHVOPTYPE */ + OMX_IndexConfigVideoIntraMBRefresh, /**< reference: OMX_CONFIG_MACROBLOCKERRORMAPTYPE */ + OMX_IndexConfigVideoMBErrorReporting, /**< reference: OMX_CONFIG_MBERRORREPORTINGTYPE */ + OMX_IndexParamVideoMacroblocksPerFrame, /**< reference: OMX_PARAM_MACROBLOCKSTYPE */ + OMX_IndexConfigVideoMacroBlockErrorMap, /**< reference: OMX_CONFIG_MACROBLOCKERRORMAPTYPE */ + OMX_IndexParamVideoSliceFMO, /**< reference: OMX_VIDEO_PARAM_AVCSLICEFMO */ + OMX_IndexConfigVideoAVCIntraPeriod, /**< reference: OMX_VIDEO_CONFIG_AVCINTRAPERIOD */ + OMX_IndexConfigVideoNalSize, /**< reference: OMX_VIDEO_CONFIG_NALSIZE */ + + /* Image & Video common Configurations */ + OMX_IndexCommonStartUnused = 0x07000000, + OMX_IndexParamCommonDeblocking, /**< reference: OMX_PARAM_DEBLOCKINGTYPE */ + OMX_IndexParamCommonSensorMode, /**< reference: OMX_PARAM_SENSORMODETYPE */ + OMX_IndexParamCommonInterleave, /**< reference: OMX_PARAM_INTERLEAVETYPE */ + OMX_IndexConfigCommonColorFormatConversion, /**< reference: OMX_CONFIG_COLORCONVERSIONTYPE */ + OMX_IndexConfigCommonScale, /**< reference: OMX_CONFIG_SCALEFACTORTYPE */ + OMX_IndexConfigCommonImageFilter, /**< reference: OMX_CONFIG_IMAGEFILTERTYPE */ + OMX_IndexConfigCommonColorEnhancement, /**< reference: OMX_CONFIG_COLORENHANCEMENTTYPE */ + OMX_IndexConfigCommonColorKey, /**< reference: OMX_CONFIG_COLORKEYTYPE */ + OMX_IndexConfigCommonColorBlend, /**< reference: OMX_CONFIG_COLORBLENDTYPE */ + OMX_IndexConfigCommonFrameStabilisation,/**< reference: OMX_CONFIG_FRAMESTABTYPE */ + OMX_IndexConfigCommonRotate, /**< reference: OMX_CONFIG_ROTATIONTYPE */ + OMX_IndexConfigCommonMirror, /**< reference: OMX_CONFIG_MIRRORTYPE */ + OMX_IndexConfigCommonOutputPosition, /**< reference: OMX_CONFIG_POINTTYPE */ + OMX_IndexConfigCommonInputCrop, /**< reference: OMX_CONFIG_RECTTYPE */ + OMX_IndexConfigCommonOutputCrop, /**< reference: OMX_CONFIG_RECTTYPE */ + OMX_IndexConfigCommonDigitalZoom, /**< reference: OMX_CONFIG_SCALEFACTORTYPE */ + OMX_IndexConfigCommonOpticalZoom, /**< reference: OMX_CONFIG_SCALEFACTORTYPE*/ + OMX_IndexConfigCommonWhiteBalance, /**< reference: OMX_CONFIG_WHITEBALCONTROLTYPE */ + OMX_IndexConfigCommonExposure, /**< reference: OMX_CONFIG_EXPOSURECONTROLTYPE */ + OMX_IndexConfigCommonContrast, /**< reference: OMX_CONFIG_CONTRASTTYPE */ + OMX_IndexConfigCommonBrightness, /**< reference: OMX_CONFIG_BRIGHTNESSTYPE */ + OMX_IndexConfigCommonBacklight, /**< reference: OMX_CONFIG_BACKLIGHTTYPE */ + OMX_IndexConfigCommonGamma, /**< reference: OMX_CONFIG_GAMMATYPE */ + OMX_IndexConfigCommonSaturation, /**< reference: OMX_CONFIG_SATURATIONTYPE */ + OMX_IndexConfigCommonLightness, /**< reference: OMX_CONFIG_LIGHTNESSTYPE */ + OMX_IndexConfigCommonExclusionRect, /**< reference: OMX_CONFIG_RECTTYPE */ + OMX_IndexConfigCommonDithering, /**< reference: OMX_CONFIG_DITHERTYPE */ + OMX_IndexConfigCommonPlaneBlend, /**< reference: OMX_CONFIG_PLANEBLENDTYPE */ + OMX_IndexConfigCommonExposureValue, /**< reference: OMX_CONFIG_EXPOSUREVALUETYPE */ + OMX_IndexConfigCommonOutputSize, /**< reference: OMX_FRAMESIZETYPE */ + OMX_IndexParamCommonExtraQuantData, /**< reference: OMX_OTHER_EXTRADATATYPE */ + OMX_IndexConfigCommonFocusRegion, /**< reference: OMX_CONFIG_FOCUSREGIONTYPE */ + OMX_IndexConfigCommonFocusStatus, /**< reference: OMX_PARAM_FOCUSSTATUSTYPE */ + OMX_IndexConfigCommonTransitionEffect, /**< reference: OMX_CONFIG_TRANSITIONEFFECTTYPE */ + + /* Reserved Configuration range */ + OMX_IndexOtherStartUnused = 0x08000000, + OMX_IndexParamOtherPortFormat, /**< reference: OMX_OTHER_PARAM_PORTFORMATTYPE */ + OMX_IndexConfigOtherPower, /**< reference: OMX_OTHER_CONFIG_POWERTYPE */ + OMX_IndexConfigOtherStats, /**< reference: OMX_OTHER_CONFIG_STATSTYPE */ + + + /* Reserved Time range */ + OMX_IndexTimeStartUnused = 0x09000000, + OMX_IndexConfigTimeScale, /**< reference: OMX_TIME_CONFIG_SCALETYPE */ + OMX_IndexConfigTimeClockState, /**< reference: OMX_TIME_CONFIG_CLOCKSTATETYPE */ + OMX_IndexConfigTimeActiveRefClock, /**< reference: OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE */ + OMX_IndexConfigTimeCurrentMediaTime, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (read only) */ + OMX_IndexConfigTimeCurrentWallTime, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (read only) */ + OMX_IndexConfigTimeCurrentAudioReference, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (write only) */ + OMX_IndexConfigTimeCurrentVideoReference, /**< reference: OMX_TIME_CONFIG_TIMESTAMPTYPE (write only) */ + OMX_IndexConfigTimeMediaTimeRequest, /**< reference: OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE (write only) */ + OMX_IndexConfigTimeClientStartTime, /** + + +/** Khronos standard extension indices. + +This enum lists the current Khronos extension indices to OpenMAX IL. +*/ +typedef enum OMX_INDEXEXTTYPE { + + /* Component parameters and configurations */ + OMX_IndexExtComponentStartUnused = OMX_IndexKhronosExtensions + 0x00100000, + OMX_IndexConfigCallbackRequest, /**< reference: OMX_CONFIG_CALLBACKREQUESTTYPE */ + OMX_IndexConfigCommitMode, /**< reference: OMX_CONFIG_COMMITMODETYPE */ + OMX_IndexConfigCommit, /**< reference: OMX_CONFIG_COMMITTYPE */ + + /* Port parameters and configurations */ + OMX_IndexExtPortStartUnused = OMX_IndexKhronosExtensions + 0x00200000, + + /* Audio parameters and configurations */ + OMX_IndexExtAudioStartUnused = OMX_IndexKhronosExtensions + 0x00400000, + + /* Image parameters and configurations */ + OMX_IndexExtImageStartUnused = OMX_IndexKhronosExtensions + 0x00500000, + + /* Video parameters and configurations */ + OMX_IndexExtVideoStartUnused = OMX_IndexKhronosExtensions + 0x00600000, + OMX_IndexParamNalStreamFormatSupported, /**< reference: OMX_NALSTREAMFORMATTYPE */ + OMX_IndexParamNalStreamFormat, /**< reference: OMX_NALSTREAMFORMATTYPE */ + OMX_IndexParamNalStreamFormatSelect, /**< reference: OMX_NALSTREAMFORMATTYPE */ + OMX_IndexParamVideoVp8, /**< reference: OMX_VIDEO_PARAM_VP8TYPE */ + OMX_IndexConfigVideoVp8ReferenceFrame, /**< reference: OMX_VIDEO_VP8REFERENCEFRAMETYPE */ + OMX_IndexConfigVideoVp8ReferenceFrameType, /**< reference: OMX_VIDEO_VP8REFERENCEFRAMEINFOTYPE */ + + /* Image & Video common configurations */ + OMX_IndexExtCommonStartUnused = OMX_IndexKhronosExtensions + 0x00700000, + + /* Other configurations */ + OMX_IndexExtOtherStartUnused = OMX_IndexKhronosExtensions + 0x00800000, + + /* Time configurations */ + OMX_IndexExtTimeStartUnused = OMX_IndexKhronosExtensions + 0x00900000, + + OMX_IndexExtMax = 0x7FFFFFFF +} OMX_INDEXEXTTYPE; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OMX_IndexExt_h */ +/* File EOF */ diff --git a/openmax/include/khronos/OMX_Other.h b/openmax/include/khronos/OMX_Other.h new file mode 100644 index 0000000..caf7f38 --- /dev/null +++ b/openmax/include/khronos/OMX_Other.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** @file OMX_Other.h - OpenMax IL version 1.1.2 + * The structures needed by Other components to exchange + * parameters and configuration data with the components. + */ + +#ifndef OMX_Other_h +#define OMX_Other_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include + + +/** + * Enumeration of possible data types which match to multiple domains or no + * domain at all. For types which are vendor specific, a value above + * OMX_OTHER_VENDORTSTART should be used. + */ +typedef enum OMX_OTHER_FORMATTYPE { + OMX_OTHER_FormatTime = 0, /**< Transmission of various timestamps, elapsed time, + time deltas, etc */ + OMX_OTHER_FormatPower, /**< Perhaps used for enabling/disabling power + management, setting clocks? */ + OMX_OTHER_FormatStats, /**< Could be things such as frame rate, frames + dropped, etc */ + OMX_OTHER_FormatBinary, /**< Arbitrary binary data */ + OMX_OTHER_FormatVendorReserved = 1000, /**< Starting value for vendor specific + formats */ + + OMX_OTHER_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_OTHER_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_OTHER_FormatMax = 0x7FFFFFFF +} OMX_OTHER_FORMATTYPE; + +/** + * Enumeration of seek modes. + */ +typedef enum OMX_TIME_SEEKMODETYPE { + OMX_TIME_SeekModeFast = 0, /**< Prefer seeking to an approximation + * of the requested seek position over + * the actual seek position if it + * results in a faster seek. */ + OMX_TIME_SeekModeAccurate, /**< Prefer seeking to the actual seek + * position over an approximation + * of the requested seek position even + * if it results in a slower seek. */ + OMX_TIME_SeekModeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_TIME_SeekModeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_TIME_SeekModeMax = 0x7FFFFFFF +} OMX_TIME_SEEKMODETYPE; + +/* Structure representing the seekmode of the component */ +typedef struct OMX_TIME_CONFIG_SEEKMODETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_TIME_SEEKMODETYPE eType; /**< The seek mode */ +} OMX_TIME_CONFIG_SEEKMODETYPE; + +/** Structure representing a time stamp used with the following configs + * on the Clock Component (CC): + * + * OMX_IndexConfigTimeCurrentWallTime: query of the CC’s current wall + * time + * OMX_IndexConfigTimeCurrentMediaTime: query of the CC’s current media + * time + * OMX_IndexConfigTimeCurrentAudioReference and + * OMX_IndexConfigTimeCurrentVideoReference: audio/video reference + * clock sending SC its reference time + * OMX_IndexConfigTimeClientStartTime: a Clock Component client sends + * this structure to the Clock Component via a SetConfig on its + * client port when it receives a buffer with + * OMX_BUFFERFLAG_STARTTIME set. It must use the timestamp + * specified by that buffer for nStartTimestamp. + * + * It’s also used with the following config on components in general: + * + * OMX_IndexConfigTimePosition: IL client querying component position + * (GetConfig) or commanding a component to seek to the given location + * (SetConfig) + */ +typedef struct OMX_TIME_CONFIG_TIMESTAMPTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version + * information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_TICKS nTimestamp; /**< timestamp .*/ +} OMX_TIME_CONFIG_TIMESTAMPTYPE; + +/** Enumeration of possible reference clocks to the media time. */ +typedef enum OMX_TIME_UPDATETYPE { + OMX_TIME_UpdateRequestFulfillment, /**< Update is the fulfillment of a media time request. */ + OMX_TIME_UpdateScaleChanged, /**< Update was generated because the scale chagned. */ + OMX_TIME_UpdateClockStateChanged, /**< Update was generated because the clock state changed. */ + OMX_TIME_UpdateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_TIME_UpdateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_TIME_UpdateMax = 0x7FFFFFFF +} OMX_TIME_UPDATETYPE; + +/** Enumeration of possible reference clocks to the media time. */ +typedef enum OMX_TIME_REFCLOCKTYPE { + OMX_TIME_RefClockNone, /**< Use no references. */ + OMX_TIME_RefClockAudio, /**< Use references sent through OMX_IndexConfigTimeCurrentAudioReference */ + OMX_TIME_RefClockVideo, /**< Use references sent through OMX_IndexConfigTimeCurrentVideoReference */ + OMX_TIME_RefClockKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_TIME_RefClockVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_TIME_RefClockMax = 0x7FFFFFFF +} OMX_TIME_REFCLOCKTYPE; + +/** Enumeration of clock states. */ +typedef enum OMX_TIME_CLOCKSTATE { + OMX_TIME_ClockStateRunning, /**< Clock running. */ + OMX_TIME_ClockStateWaitingForStartTime, /**< Clock waiting until the + * prescribed clients emit their + * start time. */ + OMX_TIME_ClockStateStopped, /**< Clock stopped. */ + OMX_TIME_ClockStateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_TIME_ClockStateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_TIME_ClockStateMax = 0x7FFFFFFF +} OMX_TIME_CLOCKSTATE; + +/** Structure representing a media time request to the clock component. + * + * A client component sends this structure to the Clock Component via a SetConfig + * on its client port to specify a media timestamp the Clock Component + * should emit. The Clock Component should fulfill the request by sending a + * OMX_TIME_MEDIATIMETYPE when its media clock matches the requested + * timestamp. + * + * The client may require a media time request be fulfilled slightly + * earlier than the media time specified. In this case the client specifies + * an offset which is equal to the difference between wall time corresponding + * to the requested media time and the wall time when it will be + * fulfilled. + * + * A client component may uses these requests and the OMX_TIME_MEDIATIMETYPE to + * time events according to timestamps. If a client must perform an operation O at + * a time T (e.g. deliver a video frame at its corresponding timestamp), it makes a + * media time request at T (perhaps specifying an offset to ensure the request fulfillment + * is a little early). When the clock component passes the resulting OMX_TIME_MEDIATIMETYPE + * structure back to the client component, the client may perform operation O (perhaps having + * to wait a slight amount more time itself as specified by the return values). + */ + +typedef struct OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< port that this structure applies to */ + OMX_PTR pClientPrivate; /**< Client private data to disabiguate this media time + * from others (e.g. the number of the frame to deliver). + * Duplicated in the media time structure that fulfills + * this request. A value of zero is reserved for time scale + * updates. */ + OMX_TICKS nMediaTimestamp; /**< Media timestamp requested.*/ + OMX_TICKS nOffset; /**< Amount of wall clock time by which this + * request should be fulfilled early */ +} OMX_TIME_CONFIG_MEDIATIMEREQUESTTYPE; + +/**< Structure sent from the clock component client either when fulfilling + * a media time request or when the time scale has changed. + * + * In the former case the Clock Component fills this structure and times its emission + * to a client component (via the client port) according to the corresponding media + * time request sent by the client. The Clock Component should time the emission to occur + * when the requested timestamp matches the Clock Component's media time but also the + * prescribed offset early. + * + * Upon scale changes the clock component clears the nClientPrivate data, sends the current + * media time and sets the nScale to the new scale via the client port. It emits a + * OMX_TIME_MEDIATIMETYPE to all clients independent of any requests. This allows clients to + * alter processing to accomodate scaling. For instance a video component might skip inter-frames + * in the case of extreme fastforward. Likewise an audio component might add or remove samples + * from an audio frame to scale audio data. + * + * It is expected that some clock components may not be able to fulfill requests + * at exactly the prescribed time. This is acceptable so long as the request is + * fulfilled at least as early as described and not later. This structure provides + * fields the client may use to wait for the remaining time. + * + * The client may use either the nOffset or nWallTimeAtMedia fields to determine the + * wall time until the nMediaTimestamp actually occurs. In the latter case the + * client can get a more accurate value for offset by getting the current wall + * from the cloc component and subtracting it from nWallTimeAtMedia. + */ + +typedef struct OMX_TIME_MEDIATIMETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nClientPrivate; /**< Client private data to disabiguate this media time + * from others. Copied from the media time request. + * A value of zero is reserved for time scale updates. */ + OMX_TIME_UPDATETYPE eUpdateType; /**< Reason for the update */ + OMX_TICKS nMediaTimestamp; /**< Media time requested. If no media time was + * requested then this is the current media time. */ + OMX_TICKS nOffset; /**< Amount of wall clock time by which this + * request was actually fulfilled early */ + + OMX_TICKS nWallTimeAtMediaTime; /**< Wall time corresponding to nMediaTimeStamp. + * A client may compare this value to current + * media time obtained from the Clock Component to determine + * the wall time until the media timestamp is really + * current. */ + OMX_S32 xScale; /**< Current media time scale in Q16 format. */ + OMX_TIME_CLOCKSTATE eState; /* Seeking Change. Added 7/12.*/ + /**< State of the media time. */ +} OMX_TIME_MEDIATIMETYPE; + +/** Structure representing the current media time scale factor. Applicable only to clock + * component, other components see scale changes via OMX_TIME_MEDIATIMETYPE buffers sent via + * the clock component client ports. Upon recieving this config the clock component changes + * the rate by which the media time increases or decreases effectively implementing trick modes. + */ +typedef struct OMX_TIME_CONFIG_SCALETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_S32 xScale; /**< This is a value in Q16 format which is used for + * scaling the media time */ +} OMX_TIME_CONFIG_SCALETYPE; + +/** Bits used to identify a clock port. Used in OMX_TIME_CONFIG_CLOCKSTATETYPE’s nWaitMask field */ +#define OMX_CLOCKPORT0 0x00000001 +#define OMX_CLOCKPORT1 0x00000002 +#define OMX_CLOCKPORT2 0x00000004 +#define OMX_CLOCKPORT3 0x00000008 +#define OMX_CLOCKPORT4 0x00000010 +#define OMX_CLOCKPORT5 0x00000020 +#define OMX_CLOCKPORT6 0x00000040 +#define OMX_CLOCKPORT7 0x00000080 + +/** Structure representing the current mode of the media clock. + * IL Client uses this config to change or query the mode of the + * media clock of the clock component. Applicable only to clock + * component. + * + * On a SetConfig if eState is OMX_TIME_ClockStateRunning media time + * starts immediately at the prescribed start time. If + * OMX_TIME_ClockStateWaitingForStartTime the Clock Component ignores + * the given nStartTime and waits for all clients specified in the + * nWaitMask to send starttimes (via + * OMX_IndexConfigTimeClientStartTime). The Clock Component then starts + * the media clock using the earliest start time supplied. */ +typedef struct OMX_TIME_CONFIG_CLOCKSTATETYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version + * information */ + OMX_TIME_CLOCKSTATE eState; /**< State of the media time. */ + OMX_TICKS nStartTime; /**< Start time of the media time. */ + OMX_TICKS nOffset; /**< Time to offset the media time by + * (e.g. preroll). Media time will be + * reported to be nOffset ticks earlier. + */ + OMX_U32 nWaitMask; /**< Mask of OMX_CLOCKPORT values. */ +} OMX_TIME_CONFIG_CLOCKSTATETYPE; + +/** Structure representing the reference clock currently being used to + * compute media time. IL client uses this config to change or query the + * clock component's active reference clock */ +typedef struct OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_TIME_REFCLOCKTYPE eClock; /**< Reference clock used to compute media time */ +} OMX_TIME_CONFIG_ACTIVEREFCLOCKTYPE; + +/** Descriptor for setting specifics of power type. + * Note: this structure is listed for backwards compatibility. */ +typedef struct OMX_OTHER_CONFIG_POWERTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_BOOL bEnablePM; /**< Flag to enable Power Management */ +} OMX_OTHER_CONFIG_POWERTYPE; + + +/** Descriptor for setting specifics of stats type. + * Note: this structure is listed for backwards compatibility. */ +typedef struct OMX_OTHER_CONFIG_STATSTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + /* what goes here */ +} OMX_OTHER_CONFIG_STATSTYPE; + + +/** + * The PortDefinition structure is used to define all of the parameters + * necessary for the compliant component to setup an input or an output other + * path. + */ +typedef struct OMX_OTHER_PORTDEFINITIONTYPE { + OMX_OTHER_FORMATTYPE eFormat; /**< Type of data expected for this channel */ +} OMX_OTHER_PORTDEFINITIONTYPE; + +/** Port format parameter. This structure is used to enumerate + * the various data input/output format supported by the port. + */ +typedef struct OMX_OTHER_PARAM_PORTFORMATTYPE { + OMX_U32 nSize; /**< size of the structure in bytes */ + OMX_VERSIONTYPE nVersion; /**< OMX specification version information */ + OMX_U32 nPortIndex; /**< Indicates which port to set */ + OMX_U32 nIndex; /**< Indicates the enumeration index for the format from 0x0 to N-1 */ + OMX_OTHER_FORMATTYPE eFormat; /**< Type of data expected for this channel */ +} OMX_OTHER_PARAM_PORTFORMATTYPE; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ diff --git a/openmax/include/khronos/OMX_Types.h b/openmax/include/khronos/OMX_Types.h new file mode 100644 index 0000000..8698358 --- /dev/null +++ b/openmax/include/khronos/OMX_Types.h @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_Types.h - OpenMax IL version 1.1.2 + * The OMX_Types header file contains the primitive type definitions used by + * the core, the application and the component. This file may need to be + * modified to be used on systems that do not have "char" set to 8 bits, + * "short" set to 16 bits and "long" set to 32 bits. + */ + +#ifndef OMX_Types_h +#define OMX_Types_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** The OMX_API and OMX_APIENTRY are platform specific definitions used + * to declare OMX function prototypes. They are modified to meet the + * requirements for a particular platform */ +#ifdef __SYMBIAN32__ +# ifdef __OMX_EXPORTS +# define OMX_API __declspec(dllexport) +# else +# ifdef _WIN32 +# define OMX_API __declspec(dllexport) +# else +# define OMX_API __declspec(dllimport) +# endif +# endif +#else +# ifdef _WIN32 +# ifdef __OMX_EXPORTS +# define OMX_API __declspec(dllexport) +# else +# define OMX_API __declspec(dllimport) +# endif +# else +# ifdef __OMX_EXPORTS +# define OMX_API +# else +# define OMX_API extern +# endif +# endif +#endif + +#ifndef OMX_APIENTRY +#define OMX_APIENTRY +#endif + +/** OMX_IN is used to identify inputs to an OMX function. This designation + will also be used in the case of a pointer that points to a parameter + that is used as an output. */ +#ifndef OMX_IN +#define OMX_IN +#endif + +/** OMX_OUT is used to identify outputs from an OMX function. This + designation will also be used in the case of a pointer that points + to a parameter that is used as an input. */ +#ifndef OMX_OUT +#define OMX_OUT +#endif + + +/** OMX_INOUT is used to identify parameters that may be either inputs or + outputs from an OMX function at the same time. This designation will + also be used in the case of a pointer that points to a parameter that + is used both as an input and an output. */ +#ifndef OMX_INOUT +#define OMX_INOUT +#endif + +/** OMX_ALL is used to as a wildcard to select all entities of the same type + * when specifying the index, or referring to a object by an index. (i.e. + * use OMX_ALL to indicate all N channels). When used as a port index + * for a config or parameter this OMX_ALL denotes that the config or + * parameter applies to the entire component not just one port. */ +#define OMX_ALL 0xFFFFFFFF + +/** In the following we define groups that help building doxygen documentation */ + +/** @defgroup core OpenMAX IL core + * Functions and structure related to the OMX IL core + */ + + /** @defgroup comp OpenMAX IL component + * Functions and structure related to the OMX IL component + */ + +/** @defgroup rpm Resource and Policy Management + * Structures for resource and policy management of components + */ + +/** @defgroup buf Buffer Management + * Buffer handling functions and structures + */ + +/** @defgroup tun Tunneling + * @ingroup core comp + * Structures and functions to manage tunnels among component ports + */ + +/** @defgroup cp Content Pipes + * @ingroup core + */ + + /** @defgroup metadata Metadata handling + * + */ + +/** OMX_U8 is an 8 bit unsigned quantity that is byte aligned */ +typedef unsigned char OMX_U8; + +/** OMX_S8 is an 8 bit signed quantity that is byte aligned */ +typedef signed char OMX_S8; + +/** OMX_U16 is a 16 bit unsigned quantity that is 16 bit word aligned */ +typedef unsigned short OMX_U16; + +/** OMX_S16 is a 16 bit signed quantity that is 16 bit word aligned */ +typedef signed short OMX_S16; + +/** OMX_U32 is a 32 bit unsigned quantity that is 32 bit word aligned */ +typedef unsigned long OMX_U32; + +/** OMX_S32 is a 32 bit signed quantity that is 32 bit word aligned */ +typedef signed long OMX_S32; + + +/* Users with compilers that cannot accept the "long long" designation should + define the OMX_SKIP64BIT macro. It should be noted that this may cause + some components to fail to compile if the component was written to require + 64 bit integral types. However, these components would NOT compile anyway + since the compiler does not support the way the component was written. +*/ +#ifndef OMX_SKIP64BIT +#ifdef __SYMBIAN32__ +/** OMX_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ +typedef unsigned long long OMX_U64; + +/** OMX_S64 is a 64 bit signed quantity that is 64 bit word aligned */ +typedef signed long long OMX_S64; + +#elif defined(WIN32) + +/** OMX_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ +typedef unsigned __int64 OMX_U64; + +/** OMX_S64 is a 64 bit signed quantity that is 64 bit word aligned */ +typedef signed __int64 OMX_S64; + +#else /* WIN32 */ + +/** OMX_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */ +typedef unsigned long long OMX_U64; + +/** OMX_S64 is a 64 bit signed quantity that is 64 bit word aligned */ +typedef signed long long OMX_S64; + +#endif /* WIN32 */ +#endif + + +/** The OMX_BOOL type is intended to be used to represent a true or a false + value when passing parameters to and from the OMX core and components. The + OMX_BOOL is a 32 bit quantity and is aligned on a 32 bit word boundary. + */ +typedef enum OMX_BOOL { + OMX_FALSE = 0, + OMX_TRUE = !OMX_FALSE, + OMX_BOOL_MAX = 0x7FFFFFFF +} OMX_BOOL; + +/** The OMX_PTR type is intended to be used to pass pointers between the OMX + applications and the OMX Core and components. This is a 32 bit pointer and + is aligned on a 32 bit boundary. + */ +typedef void* OMX_PTR; + +/** The OMX_STRING type is intended to be used to pass "C" type strings between + the application and the core and component. The OMX_STRING type is a 32 + bit pointer to a zero terminated string. The pointer is word aligned and + the string is byte aligned. + */ +typedef char* OMX_STRING; + +/** The OMX_BYTE type is intended to be used to pass arrays of bytes such as + buffers between the application and the component and core. The OMX_BYTE + type is a 32 bit pointer to a zero terminated string. The pointer is word + aligned and the string is byte aligned. + */ +typedef unsigned char* OMX_BYTE; + +/** OMX_UUIDTYPE is a very long unique identifier to uniquely identify + at runtime. This identifier should be generated by a component in a way + that guarantees that every instance of the identifier running on the system + is unique. */ +typedef unsigned char OMX_UUIDTYPE[128]; + +/** The OMX_DIRTYPE enumeration is used to indicate if a port is an input or + an output port. This enumeration is common across all component types. + */ +typedef enum OMX_DIRTYPE +{ + OMX_DirInput, /**< Port is an input port */ + OMX_DirOutput, /**< Port is an output port */ + OMX_DirMax = 0x7FFFFFFF +} OMX_DIRTYPE; + +/** The OMX_ENDIANTYPE enumeration is used to indicate the bit ordering + for numerical data (i.e. big endian, or little endian). + */ +typedef enum OMX_ENDIANTYPE +{ + OMX_EndianBig, /**< big endian */ + OMX_EndianLittle, /**< little endian */ + OMX_EndianMax = 0x7FFFFFFF +} OMX_ENDIANTYPE; + + +/** The OMX_NUMERICALDATATYPE enumeration is used to indicate if data + is signed or unsigned + */ +typedef enum OMX_NUMERICALDATATYPE +{ + OMX_NumericalDataSigned, /**< signed data */ + OMX_NumericalDataUnsigned, /**< unsigned data */ + OMX_NumercialDataMax = 0x7FFFFFFF +} OMX_NUMERICALDATATYPE; + + +/** Unsigned bounded value type */ +typedef struct OMX_BU32 { + OMX_U32 nValue; /**< actual value */ + OMX_U32 nMin; /**< minimum for value (i.e. nValue >= nMin) */ + OMX_U32 nMax; /**< maximum for value (i.e. nValue <= nMax) */ +} OMX_BU32; + + +/** Signed bounded value type */ +typedef struct OMX_BS32 { + OMX_S32 nValue; /**< actual value */ + OMX_S32 nMin; /**< minimum for value (i.e. nValue >= nMin) */ + OMX_S32 nMax; /**< maximum for value (i.e. nValue <= nMax) */ +} OMX_BS32; + + +/** Structure representing some time or duration in microseconds. This structure + * must be interpreted as a signed 64 bit value. The quantity is signed to accommodate + * negative deltas and preroll scenarios. The quantity is represented in microseconds + * to accomodate high resolution timestamps (e.g. DVD presentation timestamps based + * on a 90kHz clock) and to allow more accurate and synchronized delivery (e.g. + * individual audio samples delivered at 192 kHz). The quantity is 64 bit to + * accommodate a large dynamic range (signed 32 bit values would allow only for plus + * or minus 35 minutes). + * + * Implementations with limited precision may convert the signed 64 bit value to + * a signed 32 bit value internally but risk loss of precision. + */ +#ifndef OMX_SKIP64BIT +typedef OMX_S64 OMX_TICKS; +#else +typedef struct OMX_TICKS +{ + OMX_U32 nLowPart; /** low bits of the signed 64 bit tick value */ + OMX_U32 nHighPart; /** high bits of the signed 64 bit tick value */ +} OMX_TICKS; +#endif +#define OMX_TICKS_PER_SECOND 1000000 + +/** Define the public interface for the OMX Handle. The core will not use + this value internally, but the application should only use this value. + */ +typedef void* OMX_HANDLETYPE; + +typedef struct OMX_MARKTYPE +{ + OMX_HANDLETYPE hMarkTargetComponent; /**< The component that will + generate a mark event upon + processing the mark. */ + OMX_PTR pMarkData; /**< Application specific data associated with + the mark sent on a mark event to disambiguate + this mark from others. */ +} OMX_MARKTYPE; + + +/** OMX_NATIVE_DEVICETYPE is used to map a OMX video port to the + * platform & operating specific object used to reference the display + * or can be used by a audio port for native audio rendering */ +typedef void* OMX_NATIVE_DEVICETYPE; + +/** OMX_NATIVE_WINDOWTYPE is used to map a OMX video port to the + * platform & operating specific object used to reference the window */ +typedef void* OMX_NATIVE_WINDOWTYPE; + + +/** Define the OMX IL version that corresponds to this set of header files. + * We also define a combined version that can be used to write or compare + * values of the 32bit nVersion field, assuming a little endian architecture */ +#define OMX_VERSION_MAJOR 1 +#define OMX_VERSION_MINOR 1 +#define OMX_VERSION_REVISION 2 +#define OMX_VERSION_STEP 0 + +#define OMX_VERSION ((OMX_VERSION_STEP<<24) | (OMX_VERSION_REVISION<<16) | (OMX_VERSION_MINOR<<8) | OMX_VERSION_MAJOR) + + +/** The OMX_VERSIONTYPE union is used to specify the version for + a structure or component. For a component, the version is entirely + specified by the component vendor. Components doing the same function + from different vendors may or may not have the same version. For + structures, the version shall be set by the entity that allocates the + structure. For structures specified in the OMX 1.1 specification, the + value of the version shall be set to 1.1.0.0 in all cases. Access to the + OMX_VERSIONTYPE can be by a single 32 bit access (e.g. by nVersion) or + by accessing one of the structure elements to, for example, check only + the Major revision. + */ +typedef union OMX_VERSIONTYPE +{ + struct + { + OMX_U8 nVersionMajor; /**< Major version accessor element */ + OMX_U8 nVersionMinor; /**< Minor version accessor element */ + OMX_U8 nRevision; /**< Revision version accessor element */ + OMX_U8 nStep; /**< Step version accessor element */ + } s; + OMX_U32 nVersion; /**< 32 bit value to make accessing the + version easily done in a single word + size copy/compare operation */ +} OMX_VERSIONTYPE; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ diff --git a/openmax/include/khronos/OMX_Video.h b/openmax/include/khronos/OMX_Video.h new file mode 100644 index 0000000..163e450 --- /dev/null +++ b/openmax/include/khronos/OMX_Video.h @@ -0,0 +1,1060 @@ +/** + * Copyright (c) 2008 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** + * @file OMX_Video.h - OpenMax IL version 1.1.2 + * The structures is needed by Video components to exchange parameters + * and configuration data with OMX components. + */ +#ifndef OMX_Video_h +#define OMX_Video_h + +/** @defgroup video OpenMAX IL Video Domain + * @ingroup iv + * Structures for OpenMAX IL Video domain + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/** + * Each OMX header must include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ + +#include + + +/** + * Enumeration used to define the possible video compression codings. + * NOTE: This essentially refers to file extensions. If the coding is + * being used to specify the ENCODE type, then additional work + * must be done to configure the exact flavor of the compression + * to be used. For decode cases where the user application can + * not differentiate between MPEG-4 and H.264 bit streams, it is + * up to the codec to handle this. + */ +typedef enum OMX_VIDEO_CODINGTYPE { + OMX_VIDEO_CodingUnused, /**< Value when coding is N/A */ + OMX_VIDEO_CodingAutoDetect, /**< Autodetection of coding type */ + OMX_VIDEO_CodingMPEG2, /**< AKA: H.262 */ + OMX_VIDEO_CodingH263, /**< H.263 */ + OMX_VIDEO_CodingMPEG4, /**< MPEG-4 */ + OMX_VIDEO_CodingWMV, /**< all versions of Windows Media Video */ + OMX_VIDEO_CodingRV, /**< all versions of Real Video */ + OMX_VIDEO_CodingAVC, /**< H.264/AVC */ + OMX_VIDEO_CodingMJPEG, /**< Motion JPEG */ + OMX_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_CodingMax = 0x7FFFFFFF +} OMX_VIDEO_CODINGTYPE; + + +/** + * Data structure used to define a video path. The number of Video paths for + * input and output will vary by type of the Video component. + * + * Input (aka Source) : zero Inputs, one Output, + * Splitter : one Input, 2 or more Outputs, + * Processing Element : one Input, one output, + * Mixer : 2 or more inputs, one output, + * Output (aka Sink) : one Input, zero outputs. + * + * The PortDefinition structure is used to define all of the parameters + * necessary for the compliant component to setup an input or an output video + * path. If additional vendor specific data is required, it should be + * transmitted to the component using the CustomCommand function. Compliant + * components will prepopulate this structure with optimal values during the + * GetDefaultInitParams command. + * + * STRUCT MEMBERS: + * cMIMEType : MIME type of data for the port + * pNativeRender : Platform specific reference for a display if a + * sync, otherwise this field is 0 + * nFrameWidth : Width of frame to be used on channel if + * uncompressed format is used. Use 0 for unknown, + * don't care or variable + * nFrameHeight : Height of frame to be used on channel if + * uncompressed format is used. Use 0 for unknown, + * don't care or variable + * nStride : Number of bytes per span of an image + * (i.e. indicates the number of bytes to get + * from span N to span N+1, where negative stride + * indicates the image is bottom up + * nSliceHeight : Height used when encoding in slices + * nBitrate : Bit rate of frame to be used on channel if + * compressed format is used. Use 0 for unknown, + * don't care or variable + * xFramerate : Frame rate to be used on channel if uncompressed + * format is used. Use 0 for unknown, don't care or + * variable. Units are Q16 frames per second. + * bFlagErrorConcealment : Turns on error concealment if it is supported by + * the OMX component + * eCompressionFormat : Compression format used in this instance of the + * component. When OMX_VIDEO_CodingUnused is + * specified, eColorFormat is used + * eColorFormat : Decompressed format used by this component + * pNativeWindow : Platform specific reference for a window object if a + * display sink , otherwise this field is 0x0. + */ +typedef struct OMX_VIDEO_PORTDEFINITIONTYPE { + OMX_STRING cMIMEType; + OMX_NATIVE_DEVICETYPE pNativeRender; + OMX_U32 nFrameWidth; + OMX_U32 nFrameHeight; + OMX_S32 nStride; + OMX_U32 nSliceHeight; + OMX_U32 nBitrate; + OMX_U32 xFramerate; + OMX_BOOL bFlagErrorConcealment; + OMX_VIDEO_CODINGTYPE eCompressionFormat; + OMX_COLOR_FORMATTYPE eColorFormat; + OMX_NATIVE_WINDOWTYPE pNativeWindow; +} OMX_VIDEO_PORTDEFINITIONTYPE; + +/** + * Port format parameter. This structure is used to enumerate the various + * data input/output format supported by the port. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Indicates which port to set + * nIndex : Indicates the enumeration index for the format from + * 0x0 to N-1 + * eCompressionFormat : Compression format used in this instance of the + * component. When OMX_VIDEO_CodingUnused is specified, + * eColorFormat is used + * eColorFormat : Decompressed format used by this component + * xFrameRate : Indicates the video frame rate in Q16 format + */ +typedef struct OMX_VIDEO_PARAM_PORTFORMATTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nIndex; + OMX_VIDEO_CODINGTYPE eCompressionFormat; + OMX_COLOR_FORMATTYPE eColorFormat; + OMX_U32 xFramerate; +} OMX_VIDEO_PARAM_PORTFORMATTYPE; + + +/** + * This is a structure for configuring video compression quantization + * parameter values. Codecs may support different QP values for different + * frame types. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * nQpI : QP value to use for index frames + * nQpP : QP value to use for P frames + * nQpB : QP values to use for bidirectional frames + */ +typedef struct OMX_VIDEO_PARAM_QUANTIZATIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nQpI; + OMX_U32 nQpP; + OMX_U32 nQpB; +} OMX_VIDEO_PARAM_QUANTIZATIONTYPE; + + +/** + * Structure for configuration of video fast update parameters. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version info + * nPortIndex : Port that this structure applies to + * bEnableVFU : Enable/Disable video fast update + * nFirstGOB : Specifies the number of the first macroblock row + * nFirstMB : specifies the first MB relative to the specified first GOB + * nNumMBs : Specifies the number of MBs to be refreshed from nFirstGOB + * and nFirstMB + */ +typedef struct OMX_VIDEO_PARAM_VIDEOFASTUPDATETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnableVFU; + OMX_U32 nFirstGOB; + OMX_U32 nFirstMB; + OMX_U32 nNumMBs; +} OMX_VIDEO_PARAM_VIDEOFASTUPDATETYPE; + + +/** + * Enumeration of possible bitrate control types + */ +typedef enum OMX_VIDEO_CONTROLRATETYPE { + OMX_Video_ControlRateDisable, + OMX_Video_ControlRateVariable, + OMX_Video_ControlRateConstant, + OMX_Video_ControlRateVariableSkipFrames, + OMX_Video_ControlRateConstantSkipFrames, + OMX_Video_ControlRateKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_Video_ControlRateVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_Video_ControlRateMax = 0x7FFFFFFF +} OMX_VIDEO_CONTROLRATETYPE; + + +/** + * Structure for configuring bitrate mode of a codec. + * + * STRUCT MEMBERS: + * nSize : Size of the struct in bytes + * nVersion : OMX spec version info + * nPortIndex : Port that this struct applies to + * eControlRate : Control rate type enum + * nTargetBitrate : Target bitrate to encode with + */ +typedef struct OMX_VIDEO_PARAM_BITRATETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_CONTROLRATETYPE eControlRate; + OMX_U32 nTargetBitrate; +} OMX_VIDEO_PARAM_BITRATETYPE; + + +/** + * Enumeration of possible motion vector (MV) types + */ +typedef enum OMX_VIDEO_MOTIONVECTORTYPE { + OMX_Video_MotionVectorPixel, + OMX_Video_MotionVectorHalfPel, + OMX_Video_MotionVectorQuarterPel, + OMX_Video_MotionVectorEighthPel, + OMX_Video_MotionVectorKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_Video_MotionVectorVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_Video_MotionVectorMax = 0x7FFFFFFF +} OMX_VIDEO_MOTIONVECTORTYPE; + + +/** + * Structure for configuring the number of motion vectors used as well + * as their accuracy. + * + * STRUCT MEMBERS: + * nSize : Size of the struct in bytes + * nVersion : OMX spec version info + * nPortIndex : port that this structure applies to + * eAccuracy : Enumerated MV accuracy + * bUnrestrictedMVs : Allow unrestricted MVs + * bFourMV : Allow use of 4 MVs + * sXSearchRange : Search range in horizontal direction for MVs + * sYSearchRange : Search range in vertical direction for MVs + */ +typedef struct OMX_VIDEO_PARAM_MOTIONVECTORTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_MOTIONVECTORTYPE eAccuracy; + OMX_BOOL bUnrestrictedMVs; + OMX_BOOL bFourMV; + OMX_S32 sXSearchRange; + OMX_S32 sYSearchRange; +} OMX_VIDEO_PARAM_MOTIONVECTORTYPE; + + +/** + * Enumeration of possible methods to use for Intra Refresh + */ +typedef enum OMX_VIDEO_INTRAREFRESHTYPE { + OMX_VIDEO_IntraRefreshCyclic, + OMX_VIDEO_IntraRefreshAdaptive, + OMX_VIDEO_IntraRefreshBoth, + OMX_VIDEO_IntraRefreshKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_IntraRefreshVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_IntraRefreshMax = 0x7FFFFFFF +} OMX_VIDEO_INTRAREFRESHTYPE; + + +/** + * Structure for configuring intra refresh mode + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eRefreshMode : Cyclic, Adaptive, or Both + * nAirMBs : Number of intra macroblocks to refresh in a frame when + * AIR is enabled + * nAirRef : Number of times a motion marked macroblock has to be + * intra coded + * nCirMBs : Number of consecutive macroblocks to be coded as "intra" + * when CIR is enabled + */ +typedef struct OMX_VIDEO_PARAM_INTRAREFRESHTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_INTRAREFRESHTYPE eRefreshMode; + OMX_U32 nAirMBs; + OMX_U32 nAirRef; + OMX_U32 nCirMBs; +} OMX_VIDEO_PARAM_INTRAREFRESHTYPE; + + +/** + * Structure for enabling various error correction methods for video + * compression. + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * bEnableHEC : Enable/disable header extension codes (HEC) + * bEnableResync : Enable/disable resynchronization markers + * nResynchMarkerSpacing : Resynch markers interval (in bits) to be + * applied in the stream + * bEnableDataPartitioning : Enable/disable data partitioning + * bEnableRVLC : Enable/disable reversible variable length + * coding + */ +typedef struct OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnableHEC; + OMX_BOOL bEnableResync; + OMX_U32 nResynchMarkerSpacing; + OMX_BOOL bEnableDataPartitioning; + OMX_BOOL bEnableRVLC; +} OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE; + + +/** + * Configuration of variable block-size motion compensation (VBSMC) + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * b16x16 : Enable inter block search 16x16 + * b16x8 : Enable inter block search 16x8 + * b8x16 : Enable inter block search 8x16 + * b8x8 : Enable inter block search 8x8 + * b8x4 : Enable inter block search 8x4 + * b4x8 : Enable inter block search 4x8 + * b4x4 : Enable inter block search 4x4 + */ +typedef struct OMX_VIDEO_PARAM_VBSMCTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL b16x16; + OMX_BOOL b16x8; + OMX_BOOL b8x16; + OMX_BOOL b8x8; + OMX_BOOL b8x4; + OMX_BOOL b4x8; + OMX_BOOL b4x4; +} OMX_VIDEO_PARAM_VBSMCTYPE; + + +/** + * H.263 profile types, each profile indicates support for various + * performance bounds and different annexes. + * + * ENUMS: + * Baseline : Baseline Profile: H.263 (V1), no optional modes + * H320 Coding : H.320 Coding Efficiency Backward Compatibility + * Profile: H.263+ (V2), includes annexes I, J, L.4 + * and T + * BackwardCompatible : Backward Compatibility Profile: H.263 (V1), + * includes annex F + * ISWV2 : Interactive Streaming Wireless Profile: H.263+ + * (V2), includes annexes I, J, K and T + * ISWV3 : Interactive Streaming Wireless Profile: H.263++ + * (V3), includes profile 3 and annexes V and W.6.3.8 + * HighCompression : Conversational High Compression Profile: H.263++ + * (V3), includes profiles 1 & 2 and annexes D and U + * Internet : Conversational Internet Profile: H.263++ (V3), + * includes profile 5 and annex K + * Interlace : Conversational Interlace Profile: H.263++ (V3), + * includes profile 5 and annex W.6.3.11 + * HighLatency : High Latency Profile: H.263++ (V3), includes + * profile 6 and annexes O.1 and P.5 + */ +typedef enum OMX_VIDEO_H263PROFILETYPE { + OMX_VIDEO_H263ProfileBaseline = 0x01, + OMX_VIDEO_H263ProfileH320Coding = 0x02, + OMX_VIDEO_H263ProfileBackwardCompatible = 0x04, + OMX_VIDEO_H263ProfileISWV2 = 0x08, + OMX_VIDEO_H263ProfileISWV3 = 0x10, + OMX_VIDEO_H263ProfileHighCompression = 0x20, + OMX_VIDEO_H263ProfileInternet = 0x40, + OMX_VIDEO_H263ProfileInterlace = 0x80, + OMX_VIDEO_H263ProfileHighLatency = 0x100, + OMX_VIDEO_H263ProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_H263ProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_H263ProfileMax = 0x7FFFFFFF +} OMX_VIDEO_H263PROFILETYPE; + + +/** + * H.263 level types, each level indicates support for various frame sizes, + * bit rates, decoder frame rates. + */ +typedef enum OMX_VIDEO_H263LEVELTYPE { + OMX_VIDEO_H263Level10 = 0x01, + OMX_VIDEO_H263Level20 = 0x02, + OMX_VIDEO_H263Level30 = 0x04, + OMX_VIDEO_H263Level40 = 0x08, + OMX_VIDEO_H263Level45 = 0x10, + OMX_VIDEO_H263Level50 = 0x20, + OMX_VIDEO_H263Level60 = 0x40, + OMX_VIDEO_H263Level70 = 0x80, + OMX_VIDEO_H263LevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_H263LevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_H263LevelMax = 0x7FFFFFFF +} OMX_VIDEO_H263LEVELTYPE; + + +/** + * Specifies the picture type. These values should be OR'd to signal all + * pictures types which are allowed. + * + * ENUMS: + * Generic Picture Types: I, P and B + * H.263 Specific Picture Types: SI and SP + * H.264 Specific Picture Types: EI and EP + * MPEG-4 Specific Picture Types: S + */ +typedef enum OMX_VIDEO_PICTURETYPE { + OMX_VIDEO_PictureTypeI = 0x01, + OMX_VIDEO_PictureTypeP = 0x02, + OMX_VIDEO_PictureTypeB = 0x04, + OMX_VIDEO_PictureTypeSI = 0x08, + OMX_VIDEO_PictureTypeSP = 0x10, + OMX_VIDEO_PictureTypeEI = 0x11, + OMX_VIDEO_PictureTypeEP = 0x12, + OMX_VIDEO_PictureTypeS = 0x14, + OMX_VIDEO_PictureTypeKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_PictureTypeVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_PictureTypeMax = 0x7FFFFFFF +} OMX_VIDEO_PICTURETYPE; + + +/** + * H.263 Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nPFrames : Number of P frames between each I frame + * nBFrames : Number of B frames between each I frame + * eProfile : H.263 profile(s) to use + * eLevel : H.263 level(s) to use + * bPLUSPTYPEAllowed : Indicating that it is allowed to use PLUSPTYPE + * (specified in the 1998 version of H.263) to + * indicate custom picture sizes or clock + * frequencies + * nAllowedPictureTypes : Specifies the picture types allowed in the + * bitstream + * bForceRoundingTypeToZero : value of the RTYPE bit (bit 6 of MPPTYPE) is + * not constrained. It is recommended to change + * the value of the RTYPE bit for each reference + * picture in error-free communication + * nPictureHeaderRepetition : Specifies the frequency of picture header + * repetition + * nGOBHeaderInterval : Specifies the interval of non-empty GOB + * headers in units of GOBs + */ +typedef struct OMX_VIDEO_PARAM_H263TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nPFrames; + OMX_U32 nBFrames; + OMX_VIDEO_H263PROFILETYPE eProfile; + OMX_VIDEO_H263LEVELTYPE eLevel; + OMX_BOOL bPLUSPTYPEAllowed; + OMX_U32 nAllowedPictureTypes; + OMX_BOOL bForceRoundingTypeToZero; + OMX_U32 nPictureHeaderRepetition; + OMX_U32 nGOBHeaderInterval; +} OMX_VIDEO_PARAM_H263TYPE; + + +/** + * MPEG-2 profile types, each profile indicates support for various + * performance bounds and different annexes. + */ +typedef enum OMX_VIDEO_MPEG2PROFILETYPE { + OMX_VIDEO_MPEG2ProfileSimple = 0, /**< Simple Profile */ + OMX_VIDEO_MPEG2ProfileMain, /**< Main Profile */ + OMX_VIDEO_MPEG2Profile422, /**< 4:2:2 Profile */ + OMX_VIDEO_MPEG2ProfileSNR, /**< SNR Profile */ + OMX_VIDEO_MPEG2ProfileSpatial, /**< Spatial Profile */ + OMX_VIDEO_MPEG2ProfileHigh, /**< High Profile */ + OMX_VIDEO_MPEG2ProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_MPEG2ProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_MPEG2ProfileMax = 0x7FFFFFFF +} OMX_VIDEO_MPEG2PROFILETYPE; + + +/** + * MPEG-2 level types, each level indicates support for various frame + * sizes, bit rates, decoder frame rates. No need + */ +typedef enum OMX_VIDEO_MPEG2LEVELTYPE { + OMX_VIDEO_MPEG2LevelLL = 0, /**< Low Level */ + OMX_VIDEO_MPEG2LevelML, /**< Main Level */ + OMX_VIDEO_MPEG2LevelH14, /**< High 1440 */ + OMX_VIDEO_MPEG2LevelHL, /**< High Level */ + OMX_VIDEO_MPEG2LevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_MPEG2LevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_MPEG2LevelMax = 0x7FFFFFFF +} OMX_VIDEO_MPEG2LEVELTYPE; + + +/** + * MPEG-2 params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nPFrames : Number of P frames between each I frame + * nBFrames : Number of B frames between each I frame + * eProfile : MPEG-2 profile(s) to use + * eLevel : MPEG-2 levels(s) to use + */ +typedef struct OMX_VIDEO_PARAM_MPEG2TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nPFrames; + OMX_U32 nBFrames; + OMX_VIDEO_MPEG2PROFILETYPE eProfile; + OMX_VIDEO_MPEG2LEVELTYPE eLevel; +} OMX_VIDEO_PARAM_MPEG2TYPE; + + +/** + * MPEG-4 profile types, each profile indicates support for various + * performance bounds and different annexes. + * + * ENUMS: + * - Simple Profile, Levels 1-3 + * - Simple Scalable Profile, Levels 1-2 + * - Core Profile, Levels 1-2 + * - Main Profile, Levels 2-4 + * - N-bit Profile, Level 2 + * - Scalable Texture Profile, Level 1 + * - Simple Face Animation Profile, Levels 1-2 + * - Simple Face and Body Animation (FBA) Profile, Levels 1-2 + * - Basic Animated Texture Profile, Levels 1-2 + * - Hybrid Profile, Levels 1-2 + * - Advanced Real Time Simple Profiles, Levels 1-4 + * - Core Scalable Profile, Levels 1-3 + * - Advanced Coding Efficiency Profile, Levels 1-4 + * - Advanced Core Profile, Levels 1-2 + * - Advanced Scalable Texture, Levels 2-3 + */ +typedef enum OMX_VIDEO_MPEG4PROFILETYPE { + OMX_VIDEO_MPEG4ProfileSimple = 0x01, + OMX_VIDEO_MPEG4ProfileSimpleScalable = 0x02, + OMX_VIDEO_MPEG4ProfileCore = 0x04, + OMX_VIDEO_MPEG4ProfileMain = 0x08, + OMX_VIDEO_MPEG4ProfileNbit = 0x10, + OMX_VIDEO_MPEG4ProfileScalableTexture = 0x20, + OMX_VIDEO_MPEG4ProfileSimpleFace = 0x40, + OMX_VIDEO_MPEG4ProfileSimpleFBA = 0x80, + OMX_VIDEO_MPEG4ProfileBasicAnimated = 0x100, + OMX_VIDEO_MPEG4ProfileHybrid = 0x200, + OMX_VIDEO_MPEG4ProfileAdvancedRealTime = 0x400, + OMX_VIDEO_MPEG4ProfileCoreScalable = 0x800, + OMX_VIDEO_MPEG4ProfileAdvancedCoding = 0x1000, + OMX_VIDEO_MPEG4ProfileAdvancedCore = 0x2000, + OMX_VIDEO_MPEG4ProfileAdvancedScalable = 0x4000, + OMX_VIDEO_MPEG4ProfileAdvancedSimple = 0x8000, + OMX_VIDEO_MPEG4ProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_MPEG4ProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_MPEG4ProfileMax = 0x7FFFFFFF +} OMX_VIDEO_MPEG4PROFILETYPE; + + +/** + * MPEG-4 level types, each level indicates support for various frame + * sizes, bit rates, decoder frame rates. No need + */ +typedef enum OMX_VIDEO_MPEG4LEVELTYPE { + OMX_VIDEO_MPEG4Level0 = 0x01, /**< Level 0 */ + OMX_VIDEO_MPEG4Level0b = 0x02, /**< Level 0b */ + OMX_VIDEO_MPEG4Level1 = 0x04, /**< Level 1 */ + OMX_VIDEO_MPEG4Level2 = 0x08, /**< Level 2 */ + OMX_VIDEO_MPEG4Level3 = 0x10, /**< Level 3 */ + OMX_VIDEO_MPEG4Level4 = 0x20, /**< Level 4 */ + OMX_VIDEO_MPEG4Level4a = 0x40, /**< Level 4a */ + OMX_VIDEO_MPEG4Level5 = 0x80, /**< Level 5 */ + OMX_VIDEO_MPEG4LevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_MPEG4LevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_MPEG4LevelMax = 0x7FFFFFFF +} OMX_VIDEO_MPEG4LEVELTYPE; + + +/** + * MPEG-4 configuration. This structure handles configuration options + * which are specific to MPEG4 algorithms + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nSliceHeaderSpacing : Number of macroblocks between slice header (H263+ + * Annex K). Put zero if not used + * bSVH : Enable Short Video Header mode + * bGov : Flag to enable GOV + * nPFrames : Number of P frames between each I frame (also called + * GOV period) + * nBFrames : Number of B frames between each I frame + * nIDCVLCThreshold : Value of intra DC VLC threshold + * bACPred : Flag to use ac prediction + * nMaxPacketSize : Maximum size of packet in bytes. + * nTimeIncRes : Used to pass VOP time increment resolution for MPEG4. + * Interpreted as described in MPEG4 standard. + * eProfile : MPEG-4 profile(s) to use. + * eLevel : MPEG-4 level(s) to use. + * nAllowedPictureTypes : Specifies the picture types allowed in the bitstream + * nHeaderExtension : Specifies the number of consecutive video packet + * headers within a VOP + * bReversibleVLC : Specifies whether reversible variable length coding + * is in use + */ +typedef struct OMX_VIDEO_PARAM_MPEG4TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nSliceHeaderSpacing; + OMX_BOOL bSVH; + OMX_BOOL bGov; + OMX_U32 nPFrames; + OMX_U32 nBFrames; + OMX_U32 nIDCVLCThreshold; + OMX_BOOL bACPred; + OMX_U32 nMaxPacketSize; + OMX_U32 nTimeIncRes; + OMX_VIDEO_MPEG4PROFILETYPE eProfile; + OMX_VIDEO_MPEG4LEVELTYPE eLevel; + OMX_U32 nAllowedPictureTypes; + OMX_U32 nHeaderExtension; + OMX_BOOL bReversibleVLC; +} OMX_VIDEO_PARAM_MPEG4TYPE; + + +/** + * WMV Versions + */ +typedef enum OMX_VIDEO_WMVFORMATTYPE { + OMX_VIDEO_WMVFormatUnused = 0x01, /**< Format unused or unknown */ + OMX_VIDEO_WMVFormat7 = 0x02, /**< Windows Media Video format 7 */ + OMX_VIDEO_WMVFormat8 = 0x04, /**< Windows Media Video format 8 */ + OMX_VIDEO_WMVFormat9 = 0x08, /**< Windows Media Video format 9 */ + OMX_VIDEO_WMFFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_WMFFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_WMVFormatMax = 0x7FFFFFFF +} OMX_VIDEO_WMVFORMATTYPE; + + +/** + * WMV Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFormat : Version of WMV stream / data + */ +typedef struct OMX_VIDEO_PARAM_WMVTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_WMVFORMATTYPE eFormat; +} OMX_VIDEO_PARAM_WMVTYPE; + + +/** + * Real Video Version + */ +typedef enum OMX_VIDEO_RVFORMATTYPE { + OMX_VIDEO_RVFormatUnused = 0, /**< Format unused or unknown */ + OMX_VIDEO_RVFormat8, /**< Real Video format 8 */ + OMX_VIDEO_RVFormat9, /**< Real Video format 9 */ + OMX_VIDEO_RVFormatG2, /**< Real Video Format G2 */ + OMX_VIDEO_RVFormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_RVFormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_RVFormatMax = 0x7FFFFFFF +} OMX_VIDEO_RVFORMATTYPE; + + +/** + * Real Video Params + * + * STUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * eFormat : Version of RV stream / data + * nBitsPerPixel : Bits per pixel coded in the frame + * nPaddedWidth : Padded width in pixel of a video frame + * nPaddedHeight : Padded Height in pixels of a video frame + * nFrameRate : Rate of video in frames per second + * nBitstreamFlags : Flags which internal information about the bitstream + * nBitstreamVersion : Bitstream version + * nMaxEncodeFrameSize: Max encoded frame size + * bEnablePostFilter : Turn on/off post filter + * bEnableTemporalInterpolation : Turn on/off temporal interpolation + * bEnableLatencyMode : When enabled, the decoder does not display a decoded + * frame until it has detected that no enhancement layer + * frames or dependent B frames will be coming. This + * detection usually occurs when a subsequent non-B + * frame is encountered + */ +typedef struct OMX_VIDEO_PARAM_RVTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_RVFORMATTYPE eFormat; + OMX_U16 nBitsPerPixel; + OMX_U16 nPaddedWidth; + OMX_U16 nPaddedHeight; + OMX_U32 nFrameRate; + OMX_U32 nBitstreamFlags; + OMX_U32 nBitstreamVersion; + OMX_U32 nMaxEncodeFrameSize; + OMX_BOOL bEnablePostFilter; + OMX_BOOL bEnableTemporalInterpolation; + OMX_BOOL bEnableLatencyMode; +} OMX_VIDEO_PARAM_RVTYPE; + + +/** + * AVC profile types, each profile indicates support for various + * performance bounds and different annexes. + */ +typedef enum OMX_VIDEO_AVCPROFILETYPE { + OMX_VIDEO_AVCProfileBaseline = 0x01, /**< Baseline profile */ + OMX_VIDEO_AVCProfileMain = 0x02, /**< Main profile */ + OMX_VIDEO_AVCProfileExtended = 0x04, /**< Extended profile */ + OMX_VIDEO_AVCProfileHigh = 0x08, /**< High profile */ + OMX_VIDEO_AVCProfileHigh10 = 0x10, /**< High 10 profile */ + OMX_VIDEO_AVCProfileHigh422 = 0x20, /**< High 4:2:2 profile */ + OMX_VIDEO_AVCProfileHigh444 = 0x40, /**< High 4:4:4 profile */ + OMX_VIDEO_AVCProfileKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_AVCProfileVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_AVCProfileMax = 0x7FFFFFFF +} OMX_VIDEO_AVCPROFILETYPE; + + +/** + * AVC level types, each level indicates support for various frame sizes, + * bit rates, decoder frame rates. No need + */ +typedef enum OMX_VIDEO_AVCLEVELTYPE { + OMX_VIDEO_AVCLevel1 = 0x01, /**< Level 1 */ + OMX_VIDEO_AVCLevel1b = 0x02, /**< Level 1b */ + OMX_VIDEO_AVCLevel11 = 0x04, /**< Level 1.1 */ + OMX_VIDEO_AVCLevel12 = 0x08, /**< Level 1.2 */ + OMX_VIDEO_AVCLevel13 = 0x10, /**< Level 1.3 */ + OMX_VIDEO_AVCLevel2 = 0x20, /**< Level 2 */ + OMX_VIDEO_AVCLevel21 = 0x40, /**< Level 2.1 */ + OMX_VIDEO_AVCLevel22 = 0x80, /**< Level 2.2 */ + OMX_VIDEO_AVCLevel3 = 0x100, /**< Level 3 */ + OMX_VIDEO_AVCLevel31 = 0x200, /**< Level 3.1 */ + OMX_VIDEO_AVCLevel32 = 0x400, /**< Level 3.2 */ + OMX_VIDEO_AVCLevel4 = 0x800, /**< Level 4 */ + OMX_VIDEO_AVCLevel41 = 0x1000, /**< Level 4.1 */ + OMX_VIDEO_AVCLevel42 = 0x2000, /**< Level 4.2 */ + OMX_VIDEO_AVCLevel5 = 0x4000, /**< Level 5 */ + OMX_VIDEO_AVCLevel51 = 0x8000, /**< Level 5.1 */ + OMX_VIDEO_AVCLevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_AVCLevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_AVCLevelMax = 0x7FFFFFFF +} OMX_VIDEO_AVCLEVELTYPE; + + +/** + * AVC loop filter modes + * + * OMX_VIDEO_AVCLoopFilterEnable : Enable + * OMX_VIDEO_AVCLoopFilterDisable : Disable + * OMX_VIDEO_AVCLoopFilterDisableSliceBoundary : Disabled on slice boundaries + */ +typedef enum OMX_VIDEO_AVCLOOPFILTERTYPE { + OMX_VIDEO_AVCLoopFilterEnable = 0, + OMX_VIDEO_AVCLoopFilterDisable, + OMX_VIDEO_AVCLoopFilterDisableSliceBoundary, + OMX_VIDEO_AVCLoopFilterKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_AVCLoopFilterVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_AVCLoopFilterMax = 0x7FFFFFFF +} OMX_VIDEO_AVCLOOPFILTERTYPE; + + +/** + * AVC params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nSliceHeaderSpacing : Number of macroblocks between slice header, put + * zero if not used + * nPFrames : Number of P frames between each I frame + * nBFrames : Number of B frames between each I frame + * bUseHadamard : Enable/disable Hadamard transform + * nRefFrames : Max number of reference frames to use for inter + * motion search (1-16) + * nRefIdxTrailing : Pic param set ref frame index (index into ref + * frame buffer of trailing frames list), B frame + * support + * nRefIdxForward : Pic param set ref frame index (index into ref + * frame buffer of forward frames list), B frame + * support + * bEnableUEP : Enable/disable unequal error protection. This + * is only valid of data partitioning is enabled. + * bEnableFMO : Enable/disable flexible macroblock ordering + * bEnableASO : Enable/disable arbitrary slice ordering + * bEnableRS : Enable/disable sending of redundant slices + * eProfile : AVC profile(s) to use + * eLevel : AVC level(s) to use + * nAllowedPictureTypes : Specifies the picture types allowed in the + * bitstream + * bFrameMBsOnly : specifies that every coded picture of the + * coded video sequence is a coded frame + * containing only frame macroblocks + * bMBAFF : Enable/disable switching between frame and + * field macroblocks within a picture + * bEntropyCodingCABAC : Entropy decoding method to be applied for the + * syntax elements for which two descriptors appear + * in the syntax tables + * bWeightedPPrediction : Enable/disable weighted prediction shall not + * be applied to P and SP slices + * nWeightedBipredicitonMode : Default weighted prediction is applied to B + * slices + * bconstIpred : Enable/disable intra prediction + * bDirect8x8Inference : Specifies the method used in the derivation + * process for luma motion vectors for B_Skip, + * B_Direct_16x16 and B_Direct_8x8 as specified + * in subclause 8.4.1.2 of the AVC spec + * bDirectSpatialTemporal : Flag indicating spatial or temporal direct + * mode used in B slice coding (related to + * bDirect8x8Inference) . Spatial direct mode is + * more common and should be the default. + * nCabacInitIdx : Index used to init CABAC contexts + * eLoopFilterMode : Enable/disable loop filter + */ +typedef struct OMX_VIDEO_PARAM_AVCTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nSliceHeaderSpacing; + OMX_U32 nPFrames; + OMX_U32 nBFrames; + OMX_BOOL bUseHadamard; + OMX_U32 nRefFrames; + OMX_U32 nRefIdx10ActiveMinus1; + OMX_U32 nRefIdx11ActiveMinus1; + OMX_BOOL bEnableUEP; + OMX_BOOL bEnableFMO; + OMX_BOOL bEnableASO; + OMX_BOOL bEnableRS; + OMX_VIDEO_AVCPROFILETYPE eProfile; + OMX_VIDEO_AVCLEVELTYPE eLevel; + OMX_U32 nAllowedPictureTypes; + OMX_BOOL bFrameMBsOnly; + OMX_BOOL bMBAFF; + OMX_BOOL bEntropyCodingCABAC; + OMX_BOOL bWeightedPPrediction; + OMX_U32 nWeightedBipredicitonMode; + OMX_BOOL bconstIpred ; + OMX_BOOL bDirect8x8Inference; + OMX_BOOL bDirectSpatialTemporal; + OMX_U32 nCabacInitIdc; + OMX_VIDEO_AVCLOOPFILTERTYPE eLoopFilterMode; +} OMX_VIDEO_PARAM_AVCTYPE; + +typedef struct OMX_VIDEO_PARAM_PROFILELEVELTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 eProfile; /**< type is OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE, + or OMX_VIDEO_MPEG4PROFILETYPE depending on context */ + OMX_U32 eLevel; /**< type is OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE, + or OMX_VIDEO_MPEG4PROFILETYPE depending on context */ + OMX_U32 nProfileIndex; /**< Used to query for individual profile support information, + This parameter is valid only for + OMX_IndexParamVideoProfileLevelQuerySupported index, + For all other indices this parameter is to be ignored. */ +} OMX_VIDEO_PARAM_PROFILELEVELTYPE; + +/** + * Structure for dynamically configuring bitrate mode of a codec. + * + * STRUCT MEMBERS: + * nSize : Size of the struct in bytes + * nVersion : OMX spec version info + * nPortIndex : Port that this struct applies to + * nEncodeBitrate : Target average bitrate to be generated in bps + */ +typedef struct OMX_VIDEO_CONFIG_BITRATETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nEncodeBitrate; +} OMX_VIDEO_CONFIG_BITRATETYPE; + +/** + * Defines Encoder Frame Rate setting + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * xEncodeFramerate : Encoding framerate represented in Q16 format + */ +typedef struct OMX_CONFIG_FRAMERATETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 xEncodeFramerate; /* Q16 format */ +} OMX_CONFIG_FRAMERATETYPE; + +typedef struct OMX_CONFIG_INTRAREFRESHVOPTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL IntraRefreshVOP; +} OMX_CONFIG_INTRAREFRESHVOPTYPE; + +typedef struct OMX_CONFIG_MACROBLOCKERRORMAPTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nErrMapSize; /* Size of the Error Map in bytes */ + OMX_U8 ErrMap[1]; /* Error map hint */ +} OMX_CONFIG_MACROBLOCKERRORMAPTYPE; + +typedef struct OMX_CONFIG_MBERRORREPORTINGTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnabled; +} OMX_CONFIG_MBERRORREPORTINGTYPE; + +typedef struct OMX_PARAM_MACROBLOCKSTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nMacroblocks; +} OMX_PARAM_MACROBLOCKSTYPE; + +/** + * AVC Slice Mode modes + * + * OMX_VIDEO_SLICEMODE_AVCDefault : Normal frame encoding, one slice per frame + * OMX_VIDEO_SLICEMODE_AVCMBSlice : NAL mode, number of MBs per frame + * OMX_VIDEO_SLICEMODE_AVCByteSlice : NAL mode, number of bytes per frame + */ +typedef enum OMX_VIDEO_AVCSLICEMODETYPE { + OMX_VIDEO_SLICEMODE_AVCDefault = 0, + OMX_VIDEO_SLICEMODE_AVCMBSlice, + OMX_VIDEO_SLICEMODE_AVCByteSlice, + OMX_VIDEO_SLICEMODE_AVCKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ + OMX_VIDEO_SLICEMODE_AVCVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */ + OMX_VIDEO_SLICEMODE_AVCLevelMax = 0x7FFFFFFF +} OMX_VIDEO_AVCSLICEMODETYPE; + +/** + * AVC FMO Slice Mode Params + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nNumSliceGroups : Specifies the number of slice groups + * nSliceGroupMapType : Specifies the type of slice groups + * eSliceMode : Specifies the type of slice + */ +typedef struct OMX_VIDEO_PARAM_AVCSLICEFMO { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U8 nNumSliceGroups; + OMX_U8 nSliceGroupMapType; + OMX_VIDEO_AVCSLICEMODETYPE eSliceMode; +} OMX_VIDEO_PARAM_AVCSLICEFMO; + +/** + * AVC IDR Period Configs + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nIDRPeriod : Specifies periodicity of IDR frames + * nPFrames : Specifies internal of coding Intra frames + */ +typedef struct OMX_VIDEO_CONFIG_AVCINTRAPERIOD { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nIDRPeriod; + OMX_U32 nPFrames; +} OMX_VIDEO_CONFIG_AVCINTRAPERIOD; + +/** + * AVC NAL Size Configs + * + * STRUCT MEMBERS: + * nSize : Size of the structure in bytes + * nVersion : OMX specification version information + * nPortIndex : Port that this structure applies to + * nNaluBytes : Specifies the NAL unit size + */ +typedef struct OMX_VIDEO_CONFIG_NALSIZE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nNaluBytes; +} OMX_VIDEO_CONFIG_NALSIZE; + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +/* File EOF */ + diff --git a/openmax/include/khronos/OMX_VideoExt.h b/openmax/include/khronos/OMX_VideoExt.h new file mode 100644 index 0000000..c5a338a --- /dev/null +++ b/openmax/include/khronos/OMX_VideoExt.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2010 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject + * to the following conditions: + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/** OMX_VideoExt.h - OpenMax IL version 1.1.2 + * The OMX_VideoExt header file contains extensions to the + * definitions used by both the application and the component to + * access video items. + */ + +#ifndef OMX_VideoExt_h +#define OMX_VideoExt_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Each OMX header shall include all required header files to allow the + * header to compile without errors. The includes below are required + * for this header file to compile successfully + */ +#include + +/** NALU Formats */ +typedef enum OMX_NALUFORMATSTYPE { + OMX_NaluFormatStartCodes = 1, + OMX_NaluFormatOneNaluPerBuffer = 2, + OMX_NaluFormatOneByteInterleaveLength = 4, + OMX_NaluFormatTwoByteInterleaveLength = 8, + OMX_NaluFormatFourByteInterleaveLength = 16, + OMX_NaluFormatCodingMax = 0x7FFFFFFF +} OMX_NALUFORMATSTYPE; + +/** NAL Stream Format */ +typedef struct OMX_NALSTREAMFORMATTYPE{ + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_NALUFORMATSTYPE eNaluFormat; +} OMX_NALSTREAMFORMATTYPE; + +/** Enum for standard video codingtype extensions */ +typedef enum OMX_VIDEO_CODINGEXTTYPE { + OMX_VIDEO_ExtCodingUnused = OMX_VIDEO_CodingKhronosExtensions, + OMX_VIDEO_CodingVP8, /**< VP8/WebM */ +} OMX_VIDEO_CODINGEXTTYPE; + +/** VP8 profiles */ +typedef enum OMX_VIDEO_VP8PROFILETYPE { + OMX_VIDEO_VP8ProfileMain = 0x01, + OMX_VIDEO_VP8ProfileUnknown = 0x6EFFFFFF, + OMX_VIDEO_VP8ProfileMax = 0x7FFFFFFF +} OMX_VIDEO_VP8PROFILETYPE; + +/** VP8 levels */ +typedef enum OMX_VIDEO_VP8LEVELTYPE { + OMX_VIDEO_VP8Level_Version0 = 0x01, + OMX_VIDEO_VP8Level_Version1 = 0x02, + OMX_VIDEO_VP8Level_Version2 = 0x04, + OMX_VIDEO_VP8Level_Version3 = 0x08, + OMX_VIDEO_VP8LevelUnknown = 0x6EFFFFFF, + OMX_VIDEO_VP8LevelMax = 0x7FFFFFFF +} OMX_VIDEO_VP8LEVELTYPE; + +/** VP8 Param */ +typedef struct OMX_VIDEO_PARAM_VP8TYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_VP8PROFILETYPE eProfile; + OMX_VIDEO_VP8LEVELTYPE eLevel; + OMX_U32 nDCTPartitions; + OMX_BOOL bErrorResilientMode; +} OMX_VIDEO_PARAM_VP8TYPE; + +/** Structure for configuring VP8 reference frames */ +typedef struct OMX_VIDEO_VP8REFERENCEFRAMETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bPreviousFrameRefresh; + OMX_BOOL bGoldenFrameRefresh; + OMX_BOOL bAlternateFrameRefresh; + OMX_BOOL bUsePreviousFrame; + OMX_BOOL bUseGoldenFrame; + OMX_BOOL bUseAlternateFrame; +} OMX_VIDEO_VP8REFERENCEFRAMETYPE; + +/** Structure for querying VP8 reference frame type */ +typedef struct OMX_VIDEO_VP8REFERENCEFRAMEINFOTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bIsIntraFrame; + OMX_BOOL bIsGoldenOrAlternateFrame; +} OMX_VIDEO_VP8REFERENCEFRAMEINFOTYPE; + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OMX_VideoExt_h */ +/* File EOF */ diff --git a/openmax/osal/Android.mk b/openmax/osal/Android.mk new file mode 100644 index 0000000..823ad36 --- /dev/null +++ b/openmax/osal/Android.mk @@ -0,0 +1,225 @@ +LOCAL_PATH := $(call my-dir) + +ifeq ($(BOARD_USE_SKYPE_HD), true) + +################################# +#### libExynosOMX_SkypeHD_Enc ### +################################# +include $(CLEAR_VARS) + +LOCAL_CFLAGS := +LOCAL_MODULE_TAGS := optional + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libExynosOMX_SkypeHD_Enc +LOCAL_PROPRIETARY_MODULE := true +LOCAL_CFLAGS += -DUSE_VENDOR_IMAGE + +LOCAL_CFLAGS += -DUSE_SKYPE_HD +LOCAL_CFLAGS += -DBUILD_ENC + +LOCAL_SRC_FILES := Exynos_OSAL_SkypeHD.c + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/enc \ + $(EXYNOS_OMX_COMPONENT)/video/enc/h264 \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_STATIC_LIBRARY) + +################################# +#### libExynosOMX_SkypeHD_Dec ### +################################# +include $(CLEAR_VARS) + +LOCAL_CFLAGS := +LOCAL_MODULE_TAGS := optional + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libExynosOMX_SkypeHD_Dec +LOCAL_PROPRIETARY_MODULE := true +LOCAL_CFLAGS += -DUSE_VENDOR_IMAGE + +LOCAL_CFLAGS += -DUSE_SKYPE_HD +LOCAL_CFLAGS += -DBUILD_DEC +LOCAL_SRC_FILES := Exynos_OSAL_SkypeHD.c + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/dec \ + $(EXYNOS_OMX_COMPONENT)/video/dec/h264 \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_STATIC_LIBRARY) +endif # for Skype HD + + +########################## +#### libExynosOMX_OSAL ### +########################## +include $(CLEAR_VARS) + +LOCAL_CFLAGS := +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + Exynos_OSAL_Event.c \ + Exynos_OSAL_Queue.c \ + Exynos_OSAL_ETC.c \ + Exynos_OSAL_Mutex.c \ + Exynos_OSAL_Thread.c \ + Exynos_OSAL_Memory.c \ + Exynos_OSAL_Semaphore.c \ + Exynos_OSAL_Library.c \ + Exynos_OSAL_Log.c \ + Exynos_OSAL_SharedMemory.c + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libExynosOMX_OSAL +LOCAL_PROPRIETARY_MODULE := true +LOCAL_CFLAGS += -DUSE_VENDOR_IMAGE + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_CSC_HW), true) +LOCAL_CFLAGS += -DUSE_CSC_HW +endif + +ifeq ($(BOARD_USE_NON_CACHED_GRAPHICBUFFER), true) +LOCAL_CFLAGS += -DUSE_NON_CACHED_GRAPHICBUFFER +endif + +ifdef BOARD_MFC_CHROMA_VALIGN +LOCAL_CFLAGS += -DCHROMA_VALIGN=$(BOARD_MFC_CHROMA_VALIGN) +else +LOCAL_CFLAGS += -DCHROMA_VALIGN=1 +endif + +ifeq ($(BOARD_USE_WA_ION_BUF_REF), true) +LOCAL_CFLAGS += -DUSE_WA_ION_BUF_REF +endif + +ifeq ($(BOARD_USES_EXYNOS_GRALLOC_VERSION), 3) +LOCAL_CFLAGS += -DUSE_WA_ION_BUF_REF +endif + +LOCAL_STATIC_LIBRARIES := libExynosVideoApi + +LOCAL_SHARED_LIBRARIES := \ + libc \ + libcutils \ + libutils \ + liblog \ + libion \ + libhardware \ + libhidlbase \ + libui \ + libexynosgraphicbuffer \ + libion_exynos \ + libepicoperator + +LOCAL_C_INCLUDES := \ + $(EXYNOS_OMX_TOP)/core \ + $(EXYNOS_OMX_INC)/exynos \ + $(EXYNOS_OMX_TOP)/osal \ + $(EXYNOS_OMX_COMPONENT)/common \ + $(EXYNOS_OMX_COMPONENT)/video/dec \ + $(EXYNOS_OMX_COMPONENT)/video/enc \ + $(EXYNOS_VIDEO_CODEC)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + $(TOP)/hardware/samsung_slsi/exynos/libion/include \ + $(TOP)/system/core/libsystem/include/ + +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_SRC_FILES += \ + Exynos_OSAL_Android.cpp \ + Exynos_OSAL_ImageConverter.cpp + +LOCAL_STATIC_LIBRARIES += libVendorVideoApi + +ifeq ($(BOARD_USES_EXYNOS_DATASPACE_FEATURE), true) +LOCAL_CFLAGS += -DUSE_BT709_SUPPORT +endif + +ifeq ($(BOARD_USES_EXYNOS_GRALLOC_VERSION), 0) +LOCAL_CFLAGS += -DGRALLOC_VERSION0 +LOCAL_CFLAGS += -DUSE_PRIV_FORMAT +else +LOCAL_CFLAGS += -DUSE_PRIV_USAGE +endif +endif + +ifeq ($(BOARD_USE_SKYPE_HD), true) +LOCAL_CFLAGS += -DUSE_SKYPE_HD +endif + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_CFLAGS += -DUSE_KHRONOS_OMX_HEADER +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/khronos +else +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_HEADER_LIBRARIES := media_plugin_headers +LOCAL_CFLAGS += -DUSE_ANDROID +endif +endif + +ifeq ($(BOARD_USE_FULL_ST2094_40), true) +LOCAL_CFLAGS += -DUSE_FULL_ST2094_40 +endif + +ifdef BOARD_EXYNOS_S10B_FORMAT_ALIGN +LOCAL_CFLAGS += -DS10B_FORMAT_8B_ALIGNMENT=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN) +endif + +ifeq ($(BOARD_HAS_SCALER_ALIGN_RESTRICTION), true) +LOCAL_CFLAGS += -DMSCL_EXT_SIZE=512 +else +LOCAL_CFLAGS += -DMSCL_EXT_SIZE=0 +endif + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label + +include $(BUILD_STATIC_LIBRARY) diff --git a/openmax/osal/Exynos_OSAL_Android.cpp b/openmax/osal/Exynos_OSAL_Android.cpp new file mode 100644 index 0000000..7351a57 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Android.cpp @@ -0,0 +1,5018 @@ +/* + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Android.cpp + * @brief + * @author Seungbeom Kim (sbcrux.kim@samsung.com) + * @author Hyeyeon Chung (hyeon.chung@samsung.com) + * @author Yunji Kim (yunji.kim@samsung.com) + * @author Jinsung Yang (jsgood.yang@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "csc.h" +#include "ExynosGraphicBuffer.h" +#include + +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Macros.h" +#include "Exynos_OSAL_Platform.h" +#include "Exynos_OSAL_ETC.h" +#include "exynos_format.h" + +#include "ExynosVideoApi.h" +#include "VendorVideoAPI.h" +#include + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "Exynos_OSAL_Android" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +using namespace android; + +using namespace ::vendor::graphics; +using namespace ::vendor::graphics::ion; + +#define OMX_GRALLOC_USAGE_HW_VIDEO (ExynosGraphicBufferUsage::VIDEO_PRIVATE_DATA) +#define OMX_GRALLOC_USAGE_HW_VIDEO_DEC ((uint64_t)BufferUsage::VIDEO_DECODER) // decoder(prod) +#define OMX_GRALLOC_USAGE_HW_VIDEO_ENC ((uint64_t)BufferUsage::VIDEO_ENCODER) // encoder(cons) +#define OMX_GRALLOC_USAGE_DISP ((uint64_t)BufferUsage::GPU_TEXTURE) // decoder(prod) +#define OMX_GRALLOC_USAGE_UVA ((uint64_t)(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN)) +#define OMX_GRALLOC_USAGE_LOCK (OMX_GRALLOC_USAGE_UVA | OMX_GRALLOC_USAGE_HW_VIDEO) +#define OMX_GRALLOC_USAGE_PROTECTED ((uint64_t)BufferUsage::PROTECTED) + +#ifdef __cplusplus +extern "C" { +#endif + +#define FD_NUM 1 +#define EXT_DATA_NUM 2 /* alloc len, stream len for HDCP */ + +typedef struct _EXYNOS_OMX_SHARED_BUFFER { + void *bufferHandle; + unsigned long long bufferFd; + unsigned long long bufferFd1; + unsigned long long bufferFd2; + + ion_user_handle_t ionHandle; + ion_user_handle_t ionHandle1; + ion_user_handle_t ionHandle2; + + OMX_U32 cnt; +} EXYNOS_OMX_SHARED_BUFFER; + +typedef struct _EXYNOS_OMX_REF_HANDLE { + OMX_HANDLETYPE hMutex; + EXYNOS_OMX_SHARED_BUFFER SharedBuffer[MAX_BUFFER_REF]; +} EXYNOS_OMX_REF_HANDLE; + +// for performance +typedef struct _PERFORMANCE_HANDLE { + bool bIsEncoder; + void *pEpic; +} PERFORMANCE_HANDLE; +static int lockCnt = 0; + +#ifndef USE_WA_ION_BUF_REF +static int getIonFd() +{ + return get_ion_fd(); //gralloc4/libexynosgraphicbuffer/ion_helper.cpp +} +#endif + +static OMX_ERRORTYPE setBufferProcessTypeForDecoder(EXYNOS_OMX_BASEPORT *pExynosPort) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + FunctionIn(); + + if (pExynosPort == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((pExynosPort->bufferProcessType & BUFFER_COPY) && + (pExynosPort->eMetaDataType != METADATA_TYPE_DISABLED)) { + int i; + if (pExynosPort->supportFormat == NULL) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] supported format is empty", __FUNCTION__); + goto EXIT; + } + + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + /* check to support NV12T format */ + for (i = 0; pExynosPort->supportFormat[i] != OMX_COLOR_FormatUnused; i++) { + /* prefer to use NV12T */ + if (pExynosPort->supportFormat[i] == (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled) { + pExynosPort->portDefinition.format.video.eColorFormat = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled; + break; + } + } + + if (pExynosPort->bufferProcessType & BUFFER_COPY_FORCE) + pExynosPort->bufferProcessType = (EXYNOS_OMX_BUFFERPROCESS_TYPE)(BUFFER_COPY_FORCE | BUFFER_SHARE); + else + pExynosPort->bufferProcessType = BUFFER_SHARE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] output buffer mode(%x), format(%x)", + __FUNCTION__, pExynosPort->bufferProcessType, + pExynosPort->portDefinition.format.video.eColorFormat); + } + +EXIT: + FunctionOut(); + + return ret; +} + +static void resetBufferProcessTypeForDecoder(EXYNOS_OMX_BASEPORT *pExynosPort) +{ + FunctionIn(); + + if (pExynosPort == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (pExynosPort->bufferProcessType & BUFFER_COPY_FORCE) + pExynosPort->bufferProcessType = (EXYNOS_OMX_BUFFERPROCESS_TYPE)(BUFFER_COPY_FORCE | BUFFER_COPY); + else + pExynosPort->bufferProcessType = BUFFER_COPY; + + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; + +EXIT: + FunctionOut(); + + return; +} + +static OMX_COLOR_FORMATTYPE getBufferFormat(OMX_IN OMX_PTR handle) +{ + FunctionIn(); + + OMX_COLOR_FORMATTYPE ret = OMX_COLOR_FormatUnused; + ExynosGraphicBufferMeta graphicBuffer((buffer_handle_t)handle); + + ret = Exynos_OSAL_HAL2OMXColorFormat(graphicBuffer.format); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] HAL(0x%x), OMX(0x%x)", __FUNCTION__, graphicBuffer.format, ret); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE getDataSpaceFromAspects(OMX_PTR param) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + DescribeColorAspectsParams *pInfo = (DescribeColorAspectsParams *)param; + android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; + + FunctionIn(); + + dataSpace = android::ColorUtils::getDataSpaceForColorAspects(pInfo->sAspects, false); + + if (dataSpace == HAL_DATASPACE_UNKNOWN) { + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } else { + switch ((int)dataSpace) { + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_HLG | HAL_DATASPACE_STANDARD_BT2020): + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT2020): + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_ST2084 | HAL_DATASPACE_STANDARD_BT2020): + case HAL_DATASPACE_BT2020: /* HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT2020 */ + case HAL_DATASPACE_BT2020_PQ: /* HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_ST2084 | HAL_DATASPACE_STANDARD_BT2020 */ + case (HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT709): + case HAL_DATASPACE_BT709: + case HAL_DATASPACE_V0_BT709: /* HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT709 */ + case (HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_625): + case HAL_DATASPACE_BT601_625: + case HAL_DATASPACE_V0_BT601_625: /* HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_625 */ + case (HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_525): + case HAL_DATASPACE_BT601_525: + case HAL_DATASPACE_V0_BT601_525: /* HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_525 */ + case (HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED): + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED): + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] guidance for the dataSpace is (0x%x) ", __FUNCTION__, dataSpace); + pInfo->nDataSpace = dataSpace; + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] dataSpace(0x%x) is not supported", __FUNCTION__, dataSpace); + ret = OMX_ErrorUnsupportedSetting; + break; + } + } + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE getColorAspectsFromDataSpace(OMX_PTR param) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + DescribeColorAspectsParams *pInfo = (DescribeColorAspectsParams *)param; + + int range, standard, transfer; + unsigned int dataspace; + + FunctionIn(); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] dataSpace(0x%x), pixelformat(0x%x)", __FUNCTION__, pInfo->nDataSpace, pInfo->nPixelFormat); + + switch (pInfo->nDataSpace) { + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_HLG | HAL_DATASPACE_STANDARD_BT2020): + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT2020): + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_ST2084 | HAL_DATASPACE_STANDARD_BT2020): + case (HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_625): + case (HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_525): + case HAL_DATASPACE_BT709: + case HAL_DATASPACE_V0_BT709: + case HAL_DATASPACE_BT2020: + case HAL_DATASPACE_BT2020_PQ: + case HAL_DATASPACE_BT601_625: + case HAL_DATASPACE_V0_BT601_625: + case HAL_DATASPACE_BT601_525: + case HAL_DATASPACE_V0_BT601_525: + dataspace = (unsigned int)pInfo->nDataSpace; + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] dataSpace(0x%x) is not supported", __FUNCTION__, pInfo->nDataSpace); + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + switch (pInfo->nPixelFormat) { + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P: /* I420 */ + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN: + case HAL_PIXEL_FORMAT_YV12: /* YV12 */ + case HAL_PIXEL_FORMAT_EXYNOS_YV12_M: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP: /* NV12 */ + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: + case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M: /* NV21 */ + case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL: + case HAL_PIXEL_FORMAT_BGRA_8888: /* BGRA */ + case HAL_PIXEL_FORMAT_RGBA_8888: /* RGBA */ + case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: /* NV21 : HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M */ + /* W/A for MCD : upper limitation of 8bit is SDR(BT.709) */ + if ((dataspace & HAL_DATASPACE_STANDARD_BT2020) == HAL_DATASPACE_STANDARD_BT2020) { + dataspace = HAL_DATASPACE_BT709; + } + break; + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M: /* P010 */ + /* W/A for MCD : lower limitation of 10bit is HDR(BT.2020) */ + if ((dataspace & HAL_DATASPACE_STANDARD_BT2020) != HAL_DATASPACE_STANDARD_BT2020) { + unsigned int mask = 0xFFFFFFFF ^ (0b111111 << HAL_DATASPACE_STANDARD_SHIFT); + dataspace = (dataspace & mask) | HAL_DATASPACE_STANDARD_BT2020; + } + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] pixelFormat(0x%x) is not supported", __FUNCTION__, pInfo->nPixelFormat); + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + switch (dataspace) { + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_HLG | HAL_DATASPACE_STANDARD_BT2020): + pInfo->sAspects.mRange = ColorAspects::RangeLimited; + pInfo->sAspects.mPrimaries = ColorAspects::PrimariesBT2020; + pInfo->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020; + pInfo->sAspects.mTransfer = ColorAspects::TransferHLG; + break; + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT2020): + pInfo->sAspects.mRange = ColorAspects::RangeLimited; + pInfo->sAspects.mPrimaries = ColorAspects::PrimariesBT2020; + pInfo->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020; + pInfo->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; + break; + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_ST2084 | HAL_DATASPACE_STANDARD_BT2020): + pInfo->sAspects.mRange = ColorAspects::RangeLimited; + pInfo->sAspects.mPrimaries = ColorAspects::PrimariesBT2020; + pInfo->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020; + pInfo->sAspects.mTransfer = ColorAspects::TransferST2084; + break; + case (HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_625): + pInfo->sAspects.mRange = ColorAspects::RangeFull; + pInfo->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625; + pInfo->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; + pInfo->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; + break; + case (HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_525): + pInfo->sAspects.mRange = ColorAspects::RangeFull; + pInfo->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_525; + pInfo->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; + pInfo->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; + break; + case HAL_DATASPACE_BT709: + case HAL_DATASPACE_V0_BT709: + pInfo->sAspects.mRange = ColorAspects::RangeLimited; + pInfo->sAspects.mPrimaries = ColorAspects::PrimariesBT709_5; + pInfo->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT709_5; + pInfo->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; + break; + case HAL_DATASPACE_BT2020: + pInfo->sAspects.mRange = ColorAspects::RangeFull; + pInfo->sAspects.mPrimaries = ColorAspects::PrimariesBT2020; + pInfo->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020; + pInfo->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; + break; + case HAL_DATASPACE_BT2020_PQ: + pInfo->sAspects.mRange = ColorAspects::RangeFull; + pInfo->sAspects.mPrimaries = ColorAspects::PrimariesBT2020; + pInfo->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020; + pInfo->sAspects.mTransfer = ColorAspects::TransferST2084; + break; + case HAL_DATASPACE_BT601_625: + case HAL_DATASPACE_V0_BT601_625: + pInfo->sAspects.mRange = ColorAspects::RangeLimited; + pInfo->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625; + pInfo->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; + pInfo->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; + break; + case HAL_DATASPACE_BT601_525: + case HAL_DATASPACE_V0_BT601_525: + pInfo->sAspects.mRange = ColorAspects::RangeLimited; + pInfo->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_525; + pInfo->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; + pInfo->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] dataSpace(0x%x) is not supported", __FUNCTION__, pInfo->nDataSpace); + ret = OMX_ErrorUnsupportedSetting; + break; + }; + +EXIT: + FunctionOut(); + + return ret; +} + +void getColorAspectsPreferBitstream( + EXYNOS_OMX_VIDEO_COLORASPECTS *pBSCA, + EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA, + void *pParam) +{ + FunctionIn(); + + if ((pBSCA == NULL) || (pFWCA == NULL) || (pParam == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid argument", __FUNCTION__); + return; + } + + DescribeColorAspectsParams *pParams = (DescribeColorAspectsParams *)pParam; + + pParams->sAspects.mRange = (enum ColorAspects::Range)pBSCA->nRangeType; + if (pBSCA->nRangeType == RANGE_UNSPECIFIED) + pParams->sAspects.mRange = (enum ColorAspects::Range)pFWCA->nRangeType; + + switch ((ExynosPrimariesType)pBSCA->nPrimaryType) { + case PRIMARIES_RESERVED: + case PRIMARIES_UNSPECIFIED: + pParams->sAspects.mPrimaries = (enum ColorAspects::Primaries)pFWCA->nPrimaryType; + break; + case PRIMARIES_BT709_5: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesBT709_5; + break; + case PRIMARIES_BT601_6_625: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625; + break; + case PRIMARIES_BT601_6_525: + case PRIMARIES_SMPTE_240M: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_525; + break; + case PRIMARIES_BT2020: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesBT2020; + break; + case PRIMARIES_BT470_6M: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesBT470_6M; + break; + case PRIMARIES_GENERIC_FILM: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesGenericFilm; + break; + default: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesOther; + break; + } + + switch ((ExynosTransferType)pBSCA->nTransferType) { + case TRANSFER_RESERVED: + case TRANSFER_UNSPECIFIED: + pParams->sAspects.mTransfer = (enum ColorAspects::Transfer)pFWCA->nTransferType; + break; + case TRANSFER_BT709: + case TRANSFER_SMPTE_170M: + case TRANSFER_BT2020_1: + case TRANSFER_BT2020_2: + pParams->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; + break; + case TRANSFER_ST2084: + pParams->sAspects.mTransfer = ColorAspects::TransferST2084; + break; + /* unsupported value */ + case TRANSFER_GAMMA_22: + pParams->sAspects.mTransfer = ColorAspects::TransferGamma22; + break; + case TRANSFER_GAMMA_28: + pParams->sAspects.mTransfer = ColorAspects::TransferGamma28; + break; + case TRANSFER_SMPTE_240M: + pParams->sAspects.mTransfer = ColorAspects::TransferSMPTE240M; + break; + case TRANSFER_LINEAR: + pParams->sAspects.mTransfer = ColorAspects::TransferLinear; + break; + case TRANSFER_XvYCC: + pParams->sAspects.mTransfer = ColorAspects::TransferXvYCC; + break; + case TRANSFER_BT1361: + pParams->sAspects.mTransfer = ColorAspects::TransferBT1361; + break; + case TRANSFER_SRGB: + pParams->sAspects.mTransfer = ColorAspects::TransferSRGB; + break; + case TRANSFER_ST428: + pParams->sAspects.mTransfer = ColorAspects::TransferST428; + break; + case TRANSFER_HLG: + pParams->sAspects.mTransfer = ColorAspects::TransferHLG; + break; + default: + pParams->sAspects.mTransfer = ColorAspects::TransferOther; + break; + } + + switch ((ExynosMatrixCoeffType)pBSCA->nCoeffType) { + case MATRIX_COEFF_IDENTITY: + case MATRIX_COEFF_RESERVED: + case MATRIX_COEFF_UNSPECIFIED: + pParams->sAspects.mMatrixCoeffs = (enum ColorAspects::MatrixCoeffs)pFWCA->nCoeffType; + break; + case MATRIX_COEFF_REC709: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT709_5; + break; + case MATRIX_COEFF_SMPTE170M: + case MATRIX_COEFF_470_SYSTEM_BG: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; + break; + case MATRIX_COEFF_SMPTE240M: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixSMPTE240M; + break; + case MATRIX_COEFF_BT2020: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020; + break; + case MATRIX_COEFF_BT2020_CONSTANT: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020Constant; + break; + case MATRIX_COEFF_470_SYSTEM_M: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT470_6M; + break; + default: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixOther; + break; + } + + FunctionOut(); + + return; +} + +void getColorAspectsPreferFramework( + EXYNOS_OMX_VIDEO_COLORASPECTS *pBSCA, + EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA, + void *pParam) +{ + FunctionIn(); + + if ((pBSCA == NULL) || (pFWCA == NULL) || (pParam == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid argument", __FUNCTION__); + return; + } + + DescribeColorAspectsParams *pParams = (DescribeColorAspectsParams *)pParam; + + pParams->sAspects.mRange = (enum ColorAspects::Range)pFWCA->nRangeType; + if (pParams->sAspects.mRange == ColorAspects::RangeUnspecified) { + switch ((ExynosRangeType)pBSCA->nRangeType) { + case RANGE_FULL: + pParams->sAspects.mRange = ColorAspects::RangeFull; + break; + case RANGE_LIMITED: + pParams->sAspects.mRange = ColorAspects::RangeLimited; + break; + default: + pParams->sAspects.mRange = ColorAspects::RangeUnspecified; + break; + } + } + + pParams->sAspects.mPrimaries = (enum ColorAspects::Primaries)pFWCA->nPrimaryType; + if (pParams->sAspects.mPrimaries == ColorAspects::PrimariesUnspecified) { + switch ((ExynosPrimariesType)pBSCA->nPrimaryType) { + case PRIMARIES_RESERVED: + case PRIMARIES_UNSPECIFIED: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesUnspecified; + break; + case PRIMARIES_BT709_5: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesBT709_5; + break; + case PRIMARIES_BT601_6_625: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_625; + break; + case PRIMARIES_BT601_6_525: + case PRIMARIES_SMPTE_240M: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesBT601_6_525; + break; + case PRIMARIES_BT2020: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesBT2020; + break; + /* unsupported value */ + case PRIMARIES_BT470_6M: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesBT470_6M; + break; + case PRIMARIES_GENERIC_FILM: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesGenericFilm; + break; + default: + pParams->sAspects.mPrimaries = ColorAspects::PrimariesOther; + break; + } + } + + pParams->sAspects.mTransfer = (enum ColorAspects::Transfer)pFWCA->nTransferType; + if (pParams->sAspects.mTransfer == ColorAspects::TransferUnspecified) { + switch ((ExynosTransferType)pBSCA->nTransferType) { + case TRANSFER_RESERVED: + case TRANSFER_UNSPECIFIED: + pParams->sAspects.mTransfer = ColorAspects::TransferUnspecified; + break; + case TRANSFER_BT709: + case TRANSFER_SMPTE_170M: + case TRANSFER_BT2020_1: + case TRANSFER_BT2020_2: + pParams->sAspects.mTransfer = ColorAspects::TransferSMPTE170M; + break; + case TRANSFER_ST2084: + pParams->sAspects.mTransfer = ColorAspects::TransferST2084; + break; + /* unsupported value */ + case TRANSFER_GAMMA_22: + pParams->sAspects.mTransfer = ColorAspects::TransferGamma22; + break; + case TRANSFER_GAMMA_28: + pParams->sAspects.mTransfer = ColorAspects::TransferGamma28; + break; + case TRANSFER_SMPTE_240M: + pParams->sAspects.mTransfer = ColorAspects::TransferSMPTE240M; + break; + case TRANSFER_LINEAR: + pParams->sAspects.mTransfer = ColorAspects::TransferLinear; + break; + case TRANSFER_XvYCC: + pParams->sAspects.mTransfer = ColorAspects::TransferXvYCC; + break; + case TRANSFER_BT1361: + pParams->sAspects.mTransfer = ColorAspects::TransferBT1361; + break; + case TRANSFER_SRGB: + pParams->sAspects.mTransfer = ColorAspects::TransferSRGB; + break; + case TRANSFER_ST428: + pParams->sAspects.mTransfer = ColorAspects::TransferST428; + break; + case TRANSFER_HLG: + pParams->sAspects.mTransfer = ColorAspects::TransferHLG; + break; + default: + pParams->sAspects.mTransfer = ColorAspects::TransferOther; + break; + } + } + + pParams->sAspects.mMatrixCoeffs = (enum ColorAspects::MatrixCoeffs)pFWCA->nCoeffType; + if (pParams->sAspects.mMatrixCoeffs == ColorAspects::MatrixUnspecified) { + switch ((ExynosMatrixCoeffType)pBSCA->nCoeffType) { + case MATRIX_COEFF_IDENTITY: + case MATRIX_COEFF_UNSPECIFIED: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixUnspecified; + break; + case MATRIX_COEFF_REC709: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT709_5; + break; + case MATRIX_COEFF_SMPTE170M: + case MATRIX_COEFF_470_SYSTEM_BG: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT601_6; + break; + case MATRIX_COEFF_SMPTE240M: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixSMPTE240M; + break; + case MATRIX_COEFF_BT2020: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020; + break; + case MATRIX_COEFF_BT2020_CONSTANT: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixBT2020Constant; + break; + case MATRIX_COEFF_RESERVED: + /* unsupported value */ + case MATRIX_COEFF_470_SYSTEM_M: + default: + pParams->sAspects.mMatrixCoeffs = ColorAspects::MatrixOther; + break; + } + } + + FunctionOut(); + + return; +} + +OMX_ERRORTYPE Exynos_OSAL_UpdateDataSpaceFromAspects(EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA) { + OMX_ERRORTYPE ret = OMX_ErrorNone; + android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN; + DescribeColorAspectsParams colorInfo; + EXYNOS_OMX_VIDEO_COLORASPECTS BSCA; + + Exynos_OSAL_Memset(&BSCA, 0, sizeof(EXYNOS_OMX_VIDEO_COLORASPECTS)); + getColorAspectsPreferFramework(&BSCA, pFWCA, (void *)&colorInfo); + + ret = getDataSpaceFromAspects(&colorInfo); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%s] failed to get dataspace", __FUNCTION__); + goto EXIT; + } + + pFWCA->nDataSpace = colorInfo.nDataSpace; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] dataspace changed to 0x%x from 0x0", __FUNCTION__, colorInfo.nDataSpace); +EXIT: + return ret; +} + +void Exynos_OSAL_GetColorAspectsForBitstream( + EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA, + EXYNOS_OMX_VIDEO_COLORASPECTS *pBSCA) +{ + FunctionIn(); + + if ((pFWCA == NULL) || (pBSCA == NULL)) { + return; + } + + switch (pFWCA->nRangeType) { + case ColorAspects::RangeFull: + pBSCA->nRangeType = RANGE_FULL; + break; + case ColorAspects::RangeLimited: + pBSCA->nRangeType = RANGE_LIMITED; + break; + default: + pBSCA->nRangeType = RANGE_UNSPECIFIED; + break; + } + + switch (pFWCA->nPrimaryType) { + case ColorAspects::PrimariesBT709_5: + pBSCA->nPrimaryType = PRIMARIES_BT709_5; + break; + case ColorAspects::PrimariesUnspecified: + pBSCA->nPrimaryType = PRIMARIES_UNSPECIFIED; + break; + case ColorAspects::PrimariesBT470_6M: + pBSCA->nPrimaryType = PRIMARIES_BT470_6M; + break; + case ColorAspects::PrimariesBT601_6_625: + pBSCA->nPrimaryType = PRIMARIES_BT601_6_625; + break; + case ColorAspects::PrimariesBT601_6_525: + pBSCA->nPrimaryType = PRIMARIES_BT601_6_525; + break; + /* not declared in ColorAspects + case ColorAspects::PrimariesSMPTE240M: + pBSCA->nPrimaryType = PRIMARIES_SMPTE_240M; + break; + */ + case ColorAspects::PrimariesGenericFilm: + pBSCA->nPrimaryType = PRIMARIES_GENERIC_FILM; + break; + case ColorAspects::PrimariesBT2020: + pBSCA->nPrimaryType = PRIMARIES_BT2020; + break; + default: + pBSCA->nPrimaryType = PRIMARIES_RESERVED; + break; + } + + switch (pFWCA->nTransferType) { + case ColorAspects::TransferSMPTE170M: + pBSCA->nTransferType = TRANSFER_SMPTE_170M; /* same as 1, 6, 14, 15 */ + break; + case ColorAspects::TransferUnspecified: + pBSCA->nTransferType = TRANSFER_UNSPECIFIED; + break; + case ColorAspects::TransferGamma22: + pBSCA->nTransferType = TRANSFER_GAMMA_22; + break; + case ColorAspects::TransferGamma28: + pBSCA->nTransferType = TRANSFER_GAMMA_28; + break; + case ColorAspects::TransferSMPTE240M: + pBSCA->nTransferType = TRANSFER_SMPTE_240M; + break; + case ColorAspects::TransferLinear: + pBSCA->nTransferType = TRANSFER_LINEAR; + break; + case ColorAspects::TransferXvYCC: + pBSCA->nTransferType = TRANSFER_XvYCC; + break; + case ColorAspects::TransferBT1361: + pBSCA->nTransferType = TRANSFER_BT1361; + break; + case ColorAspects::TransferSRGB: + pBSCA->nTransferType = TRANSFER_SRGB; + break; + case ColorAspects::TransferST2084: + pBSCA->nTransferType = TRANSFER_ST2084; + break; + case ColorAspects::TransferST428: + pBSCA->nTransferType = TRANSFER_ST428; + break; + case ColorAspects::TransferHLG: + pBSCA->nTransferType = TRANSFER_HLG; + break; + default: + pBSCA->nTransferType = TRANSFER_RESERVED; + break; + } + + switch (pFWCA->nCoeffType) { + case ColorAspects::MatrixBT709_5: + pBSCA->nCoeffType = MATRIX_COEFF_REC709; + break; + case ColorAspects::MatrixUnspecified: + pBSCA->nCoeffType = MATRIX_COEFF_UNSPECIFIED; + break; + case ColorAspects::MatrixBT470_6M: + pBSCA->nCoeffType = MATRIX_COEFF_470_SYSTEM_M; + break; + case ColorAspects::MatrixBT601_6: + pBSCA->nCoeffType = MATRIX_COEFF_SMPTE170M; + break; + case ColorAspects::MatrixSMPTE240M: + pBSCA->nCoeffType = MATRIX_COEFF_SMPTE240M; + break; + case ColorAspects::MatrixBT2020: + pBSCA->nCoeffType = MATRIX_COEFF_BT2020; + break; + case ColorAspects::MatrixBT2020Constant: + pBSCA->nCoeffType = MATRIX_COEFF_BT2020_CONSTANT; + break; + default: + pBSCA->nCoeffType = MATRIX_COEFF_IDENTITY; + break; + } + + FunctionOut(); + + return; +} + +void Exynos_OSAL_UpdateDataSpaceFromBitstream(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) { + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pInputPort = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + DescribeColorAspectsParams colorInfo; + + if (pExynosComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + Exynos_OSAL_Memset(&colorInfo, 0, sizeof(DescribeColorAspectsParams)); + + getColorAspectsPreferBitstream(&pInputPort->ColorAspects, &pOutputPort->ColorAspects, &colorInfo); + + ret = getDataSpaceFromAspects(&colorInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pOutputPort->ColorAspects.nDataSpace = colorInfo.nDataSpace; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] dataspace is updated 0x%x from bitstream", pExynosComponent, __FUNCTION__, colorInfo.nDataSpace); + +EXIT: + return; +} + +void Exynos_OSAL_UpdateDataspaceToGraphicMeta(OMX_PTR pBuf, int nDataSpace) { + VideoGrallocMetadata *pMetaData = (VideoGrallocMetadata *)pBuf; + + if (pMetaData == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (nDataSpace == HAL_DATASPACE_UNKNOWN) + goto EXIT; + + if (ExynosGraphicBufferMeta::set_dataspace(pMetaData->pHandle, (android_dataspace_t)nDataSpace) < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] failed to set dataspace to graphic buffer", __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] dataspace(0x%x)", __FUNCTION__, nDataSpace); + +EXIT: + return; +} + +void Exynos_OSAL_ColorSpaceToColorAspects( + int colorSpace, + EXYNOS_OMX_VIDEO_COLORASPECTS *colorAspects) +{ + if (colorAspects == NULL) { + return; + } + + switch (colorSpace) { + case CSC_EQ_COLORSPACE_REC709: + colorAspects->nPrimaryType = ColorAspects::PrimariesBT709_5; + colorAspects->nTransferType = ColorAspects::TransferSMPTE170M; + colorAspects->nCoeffType = ColorAspects::MatrixBT709_5; + break; + case CSC_EQ_COLORSPACE_BT2020: + colorAspects->nPrimaryType = ColorAspects::PrimariesBT2020; + colorAspects->nTransferType = ColorAspects::TransferSMPTE170M; + colorAspects->nCoeffType = ColorAspects::MatrixBT2020; + break; + case CSC_EQ_COLORSPACE_SMPTE170M: + default: + colorAspects->nPrimaryType = ColorAspects::PrimariesBT601_6_625; + colorAspects->nTransferType = ColorAspects::TransferSMPTE170M; + colorAspects->nCoeffType = ColorAspects::MatrixBT601_6; + break; + } + + return; +} + +OMX_ERRORTYPE setHDR10PlusInfoForFramework( + OMX_COMPONENTTYPE *pOMXComponent, + void *pHDRDynamicInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + DescribeHDR10PlusInfoParams *pHDR10PlusInfo = NULL; /* HDR10+ info for getConfig from framework */ + ExynosHdrDynamicInfo *pMetaHDRDynamic = NULL; + OMX_U8 *pTempBuffer = NULL; + int size; + + FunctionIn(); + + if (pHDRDynamicInfo == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMetaHDRDynamic = (ExynosHdrDynamicInfo *)pHDRDynamicInfo; + + pTempBuffer = (OMX_U8 *)Exynos_OSAL_Malloc(MAX_HDR10PLUS_SIZE); + if (pTempBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pTempBuffer, 0, MAX_HDR10PLUS_SIZE); + + size = Exynos_dynamic_meta_to_itu_t_t35(pMetaHDRDynamic, (char *)pTempBuffer); + + if (size > 0) { + pHDR10PlusInfo = (DescribeHDR10PlusInfoParams *)Exynos_OSAL_Malloc(sizeof(DescribeHDR10PlusInfoParams) - 1 + size); + if (pHDR10PlusInfo == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pTempBuffer); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Memset(pHDR10PlusInfo, 0, (sizeof(DescribeHDR10PlusInfoParams) - 1 + size)); + InitOMXParams(pHDR10PlusInfo, sizeof(DescribeHDR10PlusInfoParams)); + + pHDR10PlusInfo->nParamSizeUsed = size; + Exynos_OSAL_Memcpy(pHDR10PlusInfo->nValue, pTempBuffer, size); + Exynos_OSAL_Free(pTempBuffer); + + if (Exynos_OSAL_Queue(&pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].HdrDynamicInfoQ, (void *)pHDR10PlusInfo) != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Queue HDR10+ info", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pHDR10PlusInfo); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] send event(OMX_EventConfigUpdate)", + pExynosComponent, __FUNCTION__); + /** Send Port Settings changed call back **/ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + OMX_EventConfigUpdate, /* The command was completed */ + OMX_DirOutput, /* This is the port index */ + OMX_IndexConfigVideoHdr10PlusInfo, + NULL); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Dynamic meta to itu_t_t35 is failed (size: %d)", pExynosComponent, __FUNCTION__, size); + Exynos_OSAL_Free(pTempBuffer); + ret = OMX_ErrorUndefined; + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE setHDR10PlusInfoForVendorPath( + OMX_COMPONENTTYPE *pOMXComponent, + void *pExynosHDR10PlusInfo, + void *pHDRDynamicInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + DescribeHDR10PlusInfoParams *pHDR10PlusInfo = NULL; /* HDR10+ info for getConfig from framework */ + + FunctionIn(); + + if (pHDRDynamicInfo == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHDR10PlusInfo = (DescribeHDR10PlusInfoParams *)pHDRDynamicInfo; + + if (Exynos_parsing_user_data_registered_itu_t_t35((ExynosHdrDynamicInfo *)pExynosHDR10PlusInfo, (void *)pHDR10PlusInfo->nValue) != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to parsing itu_t_t35", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE lockBuffer( + OMX_IN OMX_PTR handle, + OMX_IN OMX_U32 width, + OMX_IN OMX_U32 height, + OMX_IN OMX_COLOR_FORMATTYPE format, + OMX_OUT OMX_U32 *pStride, + OMX_OUT EXYNOS_OMX_MULTIPLANE_BUFFER *pBufferInfo) +{ + FunctionIn(); + + OMX_ERRORTYPE ret = OMX_ErrorNone; + buffer_handle_t bufferHandle = (buffer_handle_t)handle; + hardware::hidl_handle acquireFenceHandle; + + static ExynosGraphicBufferMapper &mapper(ExynosGraphicBufferMapper::get()); + ExynosGraphicBufferMeta graphicBuffer(bufferHandle); + Rect bounds(width, height); + + if ((handle == NULL) || + (pStride == NULL) || + (pBufferInfo == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] handle: 0x%x, format = %x", __FUNCTION__, handle, graphicBuffer.format); + + if (format == OMX_COLOR_FormatAndroidOpaque) + format = getBufferFormat(handle); + + switch ((int)format) { + case OMX_COLOR_Format32BitRGBA8888: + case OMX_COLOR_Format32bitBGRA8888: + case OMX_COLOR_Format32bitARGB8888: + { + void *vaddr = NULL; + + auto err = mapper.lock64(bufferHandle, OMX_GRALLOC_USAGE_LOCK, bounds, &vaddr); + + if (err != ::android::NO_ERROR) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to mapper.lock()", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pBufferInfo->addr[0] = vaddr; + pBufferInfo->addr[1] = NULL; + } + break; + case OMX_SEC_COLOR_FormatNV21Linear: + case OMX_SEC_COLOR_FormatYVU420Planar: + { + android_ycbcr outLayout; + Exynos_OSAL_Memset(&outLayout, 0, sizeof(outLayout)); + + auto err = mapper.lockYCbCr64(bufferHandle, OMX_GRALLOC_USAGE_LOCK, bounds, &outLayout); + + if (err != ::android::NO_ERROR) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to mapper.lock()", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pBufferInfo->addr[0] = outLayout.y; + pBufferInfo->addr[1] = outLayout.cr; + } + break; + default: + { + android_ycbcr outLayout; + Exynos_OSAL_Memset(&outLayout, 0, sizeof(outLayout)); + + auto err = mapper.lockYCbCr64(bufferHandle, OMX_GRALLOC_USAGE_LOCK, bounds, &outLayout); + + if (err != ::android::NO_ERROR) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to mapper.lock()", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pBufferInfo->addr[0] = outLayout.y; + pBufferInfo->addr[1] = outLayout.cb; + } + break; + } + + pBufferInfo->addr[2] = graphicBuffer.get_video_metadata(bufferHandle); + + lockCnt++; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] lockCnt:%d", __FUNCTION__, lockCnt); + + pBufferInfo->fd[0] = graphicBuffer.fd; + pBufferInfo->fd[1] = graphicBuffer.fd1; + pBufferInfo->fd[2] = graphicBuffer.fd2; + +#ifndef GRALLOC_VERSION0 + if ((graphicBuffer.producer_usage & OMX_GRALLOC_USAGE_PROTECTED) || + (graphicBuffer.consumer_usage & OMX_GRALLOC_USAGE_PROTECTED)) +#else + if (priv_hnd->flags & OMX_GRALLOC_USAGE_PROTECTED) +#endif + { + /* in case of DRM, VAs of ycbcr are invalid */ + pBufferInfo->addr[0] = INT_TO_PTR(graphicBuffer.fd); + pBufferInfo->addr[1] = INT_TO_PTR(graphicBuffer.fd1); + + if ((pBufferInfo->addr[2] == NULL) && (graphicBuffer.fd2 > 0)) /* except for private data buffer */ + pBufferInfo->addr[2] = INT_TO_PTR(graphicBuffer.fd2); + } + + *pStride = (OMX_U32)graphicBuffer.stride; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] buffer locked: handle(%p), FD(%u, %u, %u)", + __FUNCTION__, handle, pBufferInfo->fd[0], pBufferInfo->fd[1], pBufferInfo->fd[2]); + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE unlockBuffer(OMX_IN OMX_PTR handle) +{ + FunctionIn(); + + OMX_ERRORTYPE ret = OMX_ErrorNone; + buffer_handle_t bufferHandle = (buffer_handle_t) handle; + + auto buffer = const_cast(bufferHandle); + int releaseFence = -1; + + static GraphicBufferMapper &mapper(GraphicBufferMapper::get()); + + if (handle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] handle is NULL", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] handle: 0x%x", __FUNCTION__, handle); + + { + auto err = mapper.unlock(bufferHandle); + if (err != ::android::NO_ERROR) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to mapper.lock()", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + lockCnt--; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] lockCnt:%d", __FUNCTION__, lockCnt); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] buffer unlocked: handle(%p)", __FUNCTION__, handle); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_LockMetaData( + OMX_IN OMX_PTR pBuffer, + OMX_IN EXYNOS_OMX_LOCK_RANGE range, + OMX_OUT OMX_U32 *pStride, + OMX_OUT EXYNOS_OMX_MULTIPLANE_BUFFER *pBufferInfo, + OMX_IN EXYNOS_METADATA_TYPE eMetaType) +{ + FunctionIn(); + + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_PTR pBuf = NULL; + + if (eMetaType == METADATA_TYPE_GRAPHIC) { + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + + ret = Exynos_OSAL_GetInfoFromMetaData(pBuffer, &bufferInfo, eMetaType); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s]: Failed to Exynos_OSAL_GetInfoFromMetaData (err:0x%x)", + __FUNCTION__, ret); + goto EXIT; + } + + pBuf = bufferInfo.addr[0]; + } else { + pBuf = pBuffer; + } + + ret = lockBuffer(pBuf, range.nWidth, range.nHeight, range.eColorFormat, pStride, pBufferInfo); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s]: Failed to lockBuffer (err:0x%x)", __FUNCTION__, ret); + goto EXIT; + } + + pBufferInfo->eColorFormat = getBufferFormat(pBuf); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_UnlockMetaData( + OMX_IN OMX_PTR pBuffer, + OMX_IN EXYNOS_METADATA_TYPE eMetaType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_PTR pBuf = NULL; + + FunctionIn(); + + if (eMetaType == METADATA_TYPE_GRAPHIC) { + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + + ret = Exynos_OSAL_GetInfoFromMetaData(pBuffer, &bufferInfo, eMetaType); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s]: Failed to Exynos_OSAL_GetInfoFromMetaData (err:0x%x)", + __FUNCTION__, ret); + goto EXIT; + } + + pBuf = bufferInfo.addr[0]; + } else { + pBuf = pBuffer; + } + + ret = unlockBuffer(pBuf); + if (ret != OMX_ErrorNone) + goto EXIT; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_HANDLETYPE Exynos_OSAL_RefCount_Create() +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_REF_HANDLE *phREF = NULL; + + int i = 0; + + FunctionIn(); + + phREF = (EXYNOS_OMX_REF_HANDLE *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_REF_HANDLE)); + if (phREF == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to allocate ref. handle", __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Memset(phREF, 0, sizeof(EXYNOS_OMX_REF_HANDLE)); + + ret = Exynos_OSAL_MutexCreate(&phREF->hMutex); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_MutexCreate", __FUNCTION__); + Exynos_OSAL_Free(phREF); + phREF = NULL; + } + +EXIT: + FunctionOut(); + + return ((OMX_HANDLETYPE)phREF); +} + +OMX_ERRORTYPE Exynos_OSAL_RefCount_Reset(OMX_HANDLETYPE hREF) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_REF_HANDLE *phREF = (EXYNOS_OMX_REF_HANDLE *)hREF; + + int i = 0; + + FunctionIn(); + + if (phREF == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_MutexLock(phREF->hMutex); + +#ifdef USE_WA_ION_BUF_REF + for (i = 0; i < MAX_BUFFER_REF; i++) { + if (phREF->SharedBuffer[i].cnt > 0) { + if (phREF->SharedBuffer[i].ionHandle != -1) + close(phREF->SharedBuffer[i].ionHandle); + + if (phREF->SharedBuffer[i].ionHandle1 != -1) + close(phREF->SharedBuffer[i].ionHandle1); + + if (phREF->SharedBuffer[i].ionHandle2 != -1) + close(phREF->SharedBuffer[i].ionHandle2); + + phREF->SharedBuffer[i].cnt = 0; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] SharedBuffer[%d] : fd:%llu dupfd:%llu cnt:%d", __FUNCTION__, + i, phREF->SharedBuffer[i].bufferFd, + phREF->SharedBuffer[i].ionHandle, phREF->SharedBuffer[i].cnt); + + phREF->SharedBuffer[i].bufferHandle = NULL; + + phREF->SharedBuffer[i].bufferFd = 0; + phREF->SharedBuffer[i].bufferFd1 = 0; + phREF->SharedBuffer[i].bufferFd2 = 0; + + phREF->SharedBuffer[i].ionHandle = -1; + phREF->SharedBuffer[i].ionHandle1 = -1; + phREF->SharedBuffer[i].ionHandle2 = -1; + } + } +#else + for (i = 0; i < MAX_BUFFER_REF; i++) { + if (phREF->SharedBuffer[i].bufferFd > 0) { + while (phREF->SharedBuffer[i].cnt > 0) { + if (phREF->SharedBuffer[i].ionHandle != -1) + exynos_ion_free_handle(getIonFd(), phREF->SharedBuffer[i].ionHandle); + + if (phREF->SharedBuffer[i].ionHandle1 != -1) + exynos_ion_free_handle(getIonFd(), phREF->SharedBuffer[i].ionHandle1); + + if (phREF->SharedBuffer[i].ionHandle2 != -1) + exynos_ion_free_handle(getIonFd(), phREF->SharedBuffer[i].ionHandle2); + + phREF->SharedBuffer[i].cnt--; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] SharedBuffer[%d] : fd:%llu cnt:%d", __FUNCTION__, + i, phREF->SharedBuffer[i].bufferFd, phREF->SharedBuffer[i].cnt); + } + + phREF->SharedBuffer[i].bufferHandle = NULL; + + phREF->SharedBuffer[i].bufferFd = 0; + phREF->SharedBuffer[i].bufferFd1 = 0; + phREF->SharedBuffer[i].bufferFd2 = 0; + + phREF->SharedBuffer[i].ionHandle = -1; + phREF->SharedBuffer[i].ionHandle1 = -1; + phREF->SharedBuffer[i].ionHandle2 = -1; + + phREF->SharedBuffer[i].cnt = 0; + } + } +#endif + + Exynos_OSAL_MutexUnlock(phREF->hMutex); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_RefCount_Terminate(OMX_HANDLETYPE hREF) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_REF_HANDLE *phREF = (EXYNOS_OMX_REF_HANDLE *)hREF; + + FunctionIn(); + + if (phREF == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_RefCount_Reset(phREF); + + ret = Exynos_OSAL_MutexTerminate(phREF->hMutex); + if (ret != OMX_ErrorNone) + goto EXIT; + + Exynos_OSAL_Free(phREF); + phREF = NULL; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_RefCount_Increase( + OMX_HANDLETYPE hREF, + OMX_PTR pBuffer, + EXYNOS_OMX_BASEPORT *pExynosPort) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_REF_HANDLE *phREF = (EXYNOS_OMX_REF_HANDLE *)hREF; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + buffer_handle_t bufferHandle = NULL; + + ExynosGraphicBufferMeta graphicBuffer(bufferHandle); + + ion_user_handle_t ionHandle = -1; + ion_user_handle_t ionHandle1 = -1; + ion_user_handle_t ionHandle2 = -1; + int i, nPlaneCnt; + + FunctionIn(); + + if ((phREF == NULL) || + (pBuffer == NULL) || + (pExynosPort == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC_HANDLE) { + bufferHandle = (buffer_handle_t)pBuffer; + } else { + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + + ret = Exynos_OSAL_GetInfoFromMetaData(pBuffer, &bufferInfo, pExynosPort->eMetaDataType); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s]: Failed to Exynos_OSAL_GetInfoFromMetaData (err:0x%x)", + __FUNCTION__, ret); + goto EXIT; + } + + bufferHandle = (buffer_handle_t)bufferInfo.addr[0]; + } + + eColorFormat = Exynos_OSAL_HAL2OMXColorFormat(graphicBuffer.format); + if (eColorFormat == OMX_COLOR_FormatUnused) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] HAL format(0x%x) is invalid", __FUNCTION__, graphicBuffer.format); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nPlaneCnt = Exynos_OSAL_GetPlaneCount(eColorFormat, pExynosPort->ePlaneType); + + Exynos_OSAL_MutexLock(phREF->hMutex); + +#ifdef USE_WA_ION_BUF_REF + for (i = 0; i < MAX_BUFFER_REF; i++) { + if (phREF->SharedBuffer[i].bufferHandle == bufferHandle) { + phREF->SharedBuffer[i].cnt++; + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] handle(%p) : fd:%llu dupfd:%d cnt:%d", __FUNCTION__, + phREF->SharedBuffer[i].bufferHandle, phREF->SharedBuffer[i].bufferFd, + phREF->SharedBuffer[i].ionHandle, phREF->SharedBuffer[i].cnt); + goto EXIT; + } + } + + if ((graphicBuffer.fd > 0) && + (nPlaneCnt >= 1)) { + ionHandle = dup(graphicBuffer.fd); + if (ionHandle < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to dup(fd:%d)", __FUNCTION__, graphicBuffer.fd); + ionHandle = -1; + } + } + + if ((graphicBuffer.fd1 > 0) && + (nPlaneCnt >= 2)) { + ionHandle1 = dup(graphicBuffer.fd1); + if (ionHandle1 < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to dup(fd:%d)", __FUNCTION__, graphicBuffer.fd1); + ionHandle1 = -1; + } + } + + if ((graphicBuffer.fd2 > 0) && + (nPlaneCnt == 3)) { + ionHandle2 = dup(graphicBuffer.fd2); + if (ionHandle2 < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to dup(fd:%d)", __FUNCTION__, graphicBuffer.fd2); + ionHandle2 = -1; + } + } + + for (i = 0; i < MAX_BUFFER_REF; i++) { + if (phREF->SharedBuffer[i].bufferFd == 0) { + phREF->SharedBuffer[i].bufferHandle = (void *)bufferHandle; /* mark that component owns it */ + + phREF->SharedBuffer[i].bufferFd = (unsigned long long)(graphicBuffer.fd > 0)? graphicBuffer.fd:0; + phREF->SharedBuffer[i].bufferFd1 = (unsigned long long)(graphicBuffer.fd1 > 0)? graphicBuffer.fd1:0; + phREF->SharedBuffer[i].bufferFd2 = (unsigned long long)(graphicBuffer.fd2 > 0)? graphicBuffer.fd2:0; + + phREF->SharedBuffer[i].ionHandle = ionHandle; + phREF->SharedBuffer[i].ionHandle1 = ionHandle1; + phREF->SharedBuffer[i].ionHandle2 = ionHandle2; + phREF->SharedBuffer[i].cnt = 1; + break; + } + } + + if (i >= MAX_BUFFER_REF) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(phREF->hMutex); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] handle(%p) : fd:%llu dupfd:%d cnt:%d", __FUNCTION__, + phREF->SharedBuffer[i].bufferHandle, phREF->SharedBuffer[i].bufferFd, + phREF->SharedBuffer[i].ionHandle, phREF->SharedBuffer[i].cnt); +#else + if ((graphicBuffer.fd > 0) && + (nPlaneCnt >= 1)) { + if (exynos_ion_import_handle(getIonFd(), graphicBuffer.fd, &ionHandle) < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to exynos_ion_import_handle(client:%d, fd:%d)", __FUNCTION__, getIonFd(), graphicBuffer.fd); + ionHandle = -1; + } + } + + if ((graphicBuffer.fd1 > 0) && + (nPlaneCnt >= 2)) { + if (exynos_ion_import_handle(getIonFd(), graphicBuffer.fd1, &ionHandle1) < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to exynos_ion_import_handle(client:%d, fd1:%d)", __FUNCTION__, getIonFd(), graphicBuffer.fd1); + ionHandle1 = -1; + } + } + + if ((graphicBuffer.fd2 > 0) && + (nPlaneCnt == 3)) { + if (exynos_ion_import_handle(getIonFd(), graphicBuffer.fd2, &ionHandle2) < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to exynos_ion_import_handle(client:%d, fd2:%d)", __FUNCTION__, getIonFd(), graphicBuffer.fd2); + ionHandle2 = -1; + } + } + + for (i = 0; i < MAX_BUFFER_REF; i++) { + if (phREF->SharedBuffer[i].bufferFd == (unsigned long long)graphicBuffer.fd) { + phREF->SharedBuffer[i].cnt++; + break; + } + } + + if (i >= MAX_BUFFER_REF) { + for (i = 0; i < MAX_BUFFER_REF; i++) { + if (phREF->SharedBuffer[i].bufferFd == 0) { + phREF->SharedBuffer[i].bufferHandle = (void *)bufferHandle; + + phREF->SharedBuffer[i].bufferFd = (unsigned long long)(graphicBuffer.fd > 0)? graphicBuffer.fd:0; + phREF->SharedBuffer[i].bufferFd1 = (unsigned long long)(graphicBuffer.fd1 > 0)? graphicBuffer.fd1:0; + phREF->SharedBuffer[i].bufferFd2 = (unsigned long long)(graphicBuffer.fd2 > 0)? graphicBuffer.fd2:0; + + phREF->SharedBuffer[i].ionHandle = ionHandle; + phREF->SharedBuffer[i].ionHandle1 = ionHandle1; + phREF->SharedBuffer[i].ionHandle2 = ionHandle2; + phREF->SharedBuffer[i].cnt++; + break; + } + } + } + + if (i >= MAX_BUFFER_REF) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(phREF->hMutex); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] handle(%p) : fd:%llu cnt:%d", __FUNCTION__, + phREF->SharedBuffer[i].bufferHandle, phREF->SharedBuffer[i].bufferFd, phREF->SharedBuffer[i].cnt); +#endif + + Exynos_OSAL_MutexUnlock(phREF->hMutex); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_RefCount_Decrease( + OMX_HANDLETYPE hREF, + OMX_PTR pBuffer, + ReleaseDPB dpbFD[VIDEO_BUFFER_MAX_NUM], + EXYNOS_OMX_BASEPORT *pExynosPort) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_REF_HANDLE *phREF = (EXYNOS_OMX_REF_HANDLE *)hREF; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + buffer_handle_t bufferHandle = NULL; + + int i, j; + + FunctionIn(); + + if ((phREF == NULL) || + (pBuffer == NULL) || + (dpbFD == NULL) || + (pExynosPort == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC_HANDLE) { + bufferHandle = (buffer_handle_t)pBuffer; + } else { + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + + ret = Exynos_OSAL_GetInfoFromMetaData(pBuffer, &bufferInfo, pExynosPort->eMetaDataType); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s]: Failed to Exynos_OSAL_GetInfoFromMetaData (err:0x%x)", + __FUNCTION__, ret); + goto EXIT; + } + + bufferHandle = (buffer_handle_t)bufferInfo.addr[0]; + } + + Exynos_OSAL_MutexLock(phREF->hMutex); + +#ifdef USE_WA_ION_BUF_REF + for (i = 0; i < MAX_BUFFER_REF; i++) { + /* unmark that component owns it */ + if (phREF->SharedBuffer[i].bufferHandle == bufferHandle) { + phREF->SharedBuffer[i].bufferHandle = NULL; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] handle(%p)", __FUNCTION__, bufferHandle); + break; + } + } + + for (i = 0; i < VIDEO_BUFFER_MAX_NUM; i++) { + if (dpbFD[i].fd < 0) { + break; + } + + for (j = 0; j < MAX_BUFFER_REF; j++) { + if ((phREF->SharedBuffer[j].bufferFd == (unsigned long long)dpbFD[i].fd) && + (phREF->SharedBuffer[j].bufferHandle == NULL)) { + + phREF->SharedBuffer[j].cnt--; + + if (phREF->SharedBuffer[j].cnt == 0) { + if (phREF->SharedBuffer[j].ionHandle != -1) + close(phREF->SharedBuffer[j].ionHandle); + + if (phREF->SharedBuffer[j].ionHandle1 != -1) + close(phREF->SharedBuffer[j].ionHandle1); + + if (phREF->SharedBuffer[j].ionHandle2 != -1) + close(phREF->SharedBuffer[j].ionHandle2); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] fd:%d dupfd:%d cnt:%d", __FUNCTION__, + dpbFD[i].fd, phREF->SharedBuffer[j].ionHandle, phREF->SharedBuffer[j].cnt); + + phREF->SharedBuffer[j].bufferFd = 0; + phREF->SharedBuffer[j].bufferFd1 = 0; + phREF->SharedBuffer[j].bufferFd2 = 0; + phREF->SharedBuffer[j].ionHandle = -1; + phREF->SharedBuffer[j].ionHandle1 = -1; + phREF->SharedBuffer[j].ionHandle2 = -1; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] fd:%d dupfd:%d cnt:%d", __FUNCTION__, + dpbFD[i].fd, phREF->SharedBuffer[j].ionHandle, phREF->SharedBuffer[j].cnt); + } + } + } + } +#else + for (i = 0; i < VIDEO_BUFFER_MAX_NUM; i++) { + if (dpbFD[i].fd < 0) { + break; + } + + for (j = 0; j < MAX_BUFFER_REF; j++) { + if (phREF->SharedBuffer[j].bufferFd == (unsigned long long)dpbFD[i].fd) { + if (phREF->SharedBuffer[j].ionHandle != -1) + exynos_ion_free_handle(getIonFd(), phREF->SharedBuffer[j].ionHandle); + + if (phREF->SharedBuffer[j].ionHandle1 != -1) + exynos_ion_free_handle(getIonFd(), phREF->SharedBuffer[j].ionHandle1); + + if (phREF->SharedBuffer[j].ionHandle2 != -1) + exynos_ion_free_handle(getIonFd(), phREF->SharedBuffer[j].ionHandle2); + + phREF->SharedBuffer[j].cnt--; + + if (phREF->SharedBuffer[j].cnt == 0) { + phREF->SharedBuffer[j].bufferFd = 0; + phREF->SharedBuffer[j].bufferFd1 = 0; + phREF->SharedBuffer[j].bufferFd2 = 0; + phREF->SharedBuffer[j].ionHandle = -1; + phREF->SharedBuffer[j].ionHandle1 = -1; + phREF->SharedBuffer[j].ionHandle2 = -1; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] fd:%d cnt:%d", __FUNCTION__, + dpbFD[i].fd, phREF->SharedBuffer[j].cnt); + break; + } + } + } +#endif + + if (i >= MAX_BUFFER_REF) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(phREF->hMutex); + goto EXIT; + } + + Exynos_OSAL_MutexUnlock(phREF->hMutex); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_GetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexParamPortDefinition: /* DEC, ENC */ + { + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pPortDef->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if ((pExynosPort->eMetaDataType != METADATA_TYPE_DISABLED) && + (pExynosPort->eMetaDataType != METADATA_TYPE_HANDLE)) { + pPortDef->nBufferSize = MAX_METADATA_BUFFER_SIZE; + } + } + break; + case OMX_IndexParamGetAndroidNativeBuffer: /* DEC */ + { + GetAndroidNativeBufferUsageParams *pANBParams = (GetAndroidNativeBufferUsageParams *)pComponentParameterStructure; + OMX_U32 portIndex = pANBParams->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pANBParams, sizeof(GetAndroidNativeBufferUsageParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + /* NOTE: OMX_IndexParamGetAndroidNativeBuffer returns original 'nUsage' without any + * modifications since currently not defined what the 'nUsage' is for. + */ + pANBParams->nUsage |= OMX_GRALLOC_USAGE_DISP; +#ifndef USE_NON_CACHED_GRAPHICBUFFER + pANBParams->nUsage |= OMX_GRALLOC_USAGE_UVA; +#endif + +#ifdef USE_PRIV_USAGE + pANBParams->nUsage |= OMX_GRALLOC_USAGE_HW_VIDEO_DEC; +#endif + + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) { // secure decoder component + /* never knows actual image size before parsing a header info + * could not guarantee DRC(Dynamic Resolution Chnage) case */ + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + unsigned int HD_SIZE = 1280 * 720 * 3 / 2; /* 720p */ + + if ((pExynosPort->portDefinition.format.video.nFrameWidth * + pExynosPort->portDefinition.format.video.nFrameHeight * 3 / 2) > HD_SIZE) { /* over than 720p */ + } + } + } + break; + case OMX_IndexParamDescribeColorFormat: + { + DescribeColorFormatParams *pDCFParams = (DescribeColorFormatParams *)pComponentParameterStructure; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 nStride = pExynosPort->portDefinition.format.video.nStride; + OMX_U32 nSliceHeight = pExynosPort->portDefinition.format.video.nSliceHeight; + OMX_U32 yStride = ALIGN(pExynosPort->portDefinition.format.video.nFrameWidth, 16); + OMX_U32 cStride = ALIGN(pExynosPort->portDefinition.format.video.nFrameWidth / 2, 16); + + ret = Exynos_OMX_Check_SizeVersion(pDCFParams, sizeof(DescribeColorFormatParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pExynosComponent->codecType != HW_VIDEO_DEC_CODEC) { + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] requested on secure codec", pExynosComponent, __FUNCTION__); + else + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] supported in only decoder ", pExynosComponent, __FUNCTION__); + + goto EXIT; + } + + MediaImage &image = pDCFParams->sMediaImage; + image.mType = android::MediaImage::MEDIA_IMAGE_TYPE_YUV; + image.mNumPlanes = 3; + image.mBitDepth = 8; + image.mWidth = pExynosPort->portDefinition.format.video.nFrameWidth; + image.mHeight = pExynosPort->portDefinition.format.video.nFrameHeight; + + image.mPlane[image.Y].mOffset = 0; + image.mPlane[image.Y].mColInc = 1; + image.mPlane[image.Y].mRowInc = nStride; + image.mPlane[image.Y].mHorizSubsampling = 1; + image.mPlane[image.Y].mVertSubsampling = 1; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Describe ColorFormat x%x", + pExynosComponent, __FUNCTION__, pDCFParams->eColorFormat); + + if (pExynosPort->eMetaDataType != METADATA_TYPE_DISABLED) { + /* in case of graphic buffer */ + switch ((int)pDCFParams->eColorFormat) { + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN: + case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B: + { + image.mPlane[image.U].mOffset = 0; + image.mPlane[image.U].mColInc = 2; + image.mPlane[image.U].mRowInc = nStride; + image.mPlane[image.U].mHorizSubsampling = 2; + image.mPlane[image.U].mVertSubsampling = 2; + image.mPlane[image.V].mOffset = 0; + image.mPlane[image.V].mColInc = 2; + image.mPlane[image.V].mRowInc = nStride; + image.mPlane[image.V].mHorizSubsampling = 2; + image.mPlane[image.V].mVertSubsampling = 2; + } + break; + default: + { + image.mType = android::MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; + image.mNumPlanes = 0; + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] (0x%x) is not supported Meta mode(0x%x)", + pExynosComponent, __FUNCTION__, pDCFParams->eColorFormat, pExynosPort->eMetaDataType); + } + break; + } + } else { + /* in case of byte buffer */ + switch ((int)pDCFParams->eColorFormat) { + case OMX_COLOR_FormatYUV420SemiPlanar: + { + image.mPlane[image.U].mOffset = nStride * nSliceHeight; + image.mPlane[image.U].mColInc = 2; + image.mPlane[image.U].mRowInc = nStride; + image.mPlane[image.U].mHorizSubsampling = 2; + image.mPlane[image.U].mVertSubsampling = 2; + image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + 1; + image.mPlane[image.V].mColInc = 2; + image.mPlane[image.V].mRowInc = nStride; + image.mPlane[image.V].mHorizSubsampling = 2; + image.mPlane[image.V].mVertSubsampling = 2; + } + break; + case OMX_SEC_COLOR_FormatNV21Linear: + { + image.mPlane[image.V].mOffset = nStride * nSliceHeight; + image.mPlane[image.V].mColInc = 2; + image.mPlane[image.V].mRowInc = nStride; + image.mPlane[image.V].mHorizSubsampling = 2; + image.mPlane[image.V].mVertSubsampling = 2; + image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset + 1; + image.mPlane[image.U].mColInc = 2; + image.mPlane[image.U].mRowInc = nStride; + image.mPlane[image.U].mHorizSubsampling = 2; + image.mPlane[image.U].mVertSubsampling = 2; + } + break; + case OMX_SEC_COLOR_FormatYVU420Planar: + { + image.mPlane[image.Y].mRowInc = yStride; + image.mPlane[image.V].mOffset = yStride * nSliceHeight; + image.mPlane[image.V].mColInc = 1; + image.mPlane[image.V].mRowInc = cStride; + image.mPlane[image.V].mHorizSubsampling = 2; + image.mPlane[image.V].mVertSubsampling = 2; + image.mPlane[image.U].mOffset = image.mPlane[image.V].mOffset + + (cStride * nSliceHeight / 2); + image.mPlane[image.U].mColInc = 1; + image.mPlane[image.U].mRowInc = cStride; + image.mPlane[image.U].mHorizSubsampling = 2; + image.mPlane[image.U].mVertSubsampling = 2; + } + break; + case OMX_COLOR_FormatYUV420Planar: + { + image.mPlane[image.U].mOffset = nStride * nSliceHeight; + image.mPlane[image.U].mColInc = 1; + image.mPlane[image.U].mRowInc = nStride / 2; + image.mPlane[image.U].mHorizSubsampling = 2; + image.mPlane[image.U].mVertSubsampling = 2; + image.mPlane[image.V].mOffset = image.mPlane[image.U].mOffset + + (nStride * nSliceHeight / 4); + image.mPlane[image.V].mColInc = 1; + image.mPlane[image.V].mRowInc = nStride / 2; + image.mPlane[image.V].mHorizSubsampling = 2; + image.mPlane[image.V].mVertSubsampling = 2; + } + break; + default: + { + image.mType = android::MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN; + image.mNumPlanes = 0; + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] (0x%x) is not supported", + pExynosComponent, __FUNCTION__, pDCFParams->eColorFormat); + } + break; + } + } + } + break; + case OMX_IndexParamConsumerUsageBits: /* ENC */ + { + OMX_U32 *pUsageBits = (OMX_U32 *)pComponentParameterStructure; + + switch ((int)pExynosComponent->codecType) { + case HW_VIDEO_ENC_CODEC: + (*pUsageBits) = OMX_GRALLOC_USAGE_HW_VIDEO_ENC; + break; + case HW_VIDEO_ENC_SECURE_CODEC: + (*pUsageBits) = OMX_GRALLOC_USAGE_HW_VIDEO_ENC | OMX_GRALLOC_USAGE_PROTECTED; + break; + default: + (*pUsageBits) = 0; + ret = OMX_ErrorUnsupportedIndex; + break; + } + } + break; + default: + { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_SetParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexParamEnableAndroidBuffers: + { + EnableAndroidNativeBuffersParams *pANBParams = (EnableAndroidNativeBuffersParams *)pComponentParameterStructure; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 portIndex = pANBParams->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pANBParams, sizeof(EnableAndroidNativeBuffersParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][ANB] %s port: metadata(%x), ANB(%d)", + pExynosComponent, __FUNCTION__, + (portIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosPort->eMetaDataType, pANBParams->enable); + + /* + * adaptive playback(ANB + META): kPortModeDynamicANWBuffer + * usegraphicbuffer(ANB) : kPortModePresetANWBuffer + */ + if ((portIndex == OUTPUT_PORT_INDEX) && + ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC))) { + + if ((pANBParams->enable == OMX_TRUE) && + (pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + /* enable */ + pExynosPort->eMetaDataType = METADATA_TYPE_GRAPHIC_HANDLE; + + ret = setBufferProcessTypeForDecoder(pExynosPort); + if (ret != OMX_ErrorNone) + goto EXIT; + } else if (pANBParams->enable == OMX_FALSE) { + if (pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC) + pExynosPort->eMetaDataType = METADATA_TYPE_DATA; + else if (pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC_HANDLE) + pExynosPort->eMetaDataType = METADATA_TYPE_DISABLED; + + /* disable */ + resetBufferProcessTypeForDecoder(pExynosPort); + } + } + + /* screen recording(ANB + META) : kPortModeDynamicANWBuffer */ + if ((portIndex == INPUT_PORT_INDEX) && + ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC))) { + + if ((pANBParams->enable == OMX_TRUE) && + (pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED)) { + pExynosPort->eMetaDataType = METADATA_TYPE_GRAPHIC_HANDLE; + } else if (pANBParams->enable == OMX_FALSE) { + if (pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC) + pExynosPort->eMetaDataType = METADATA_TYPE_DATA; + else if (pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC_HANDLE) + pExynosPort->eMetaDataType = METADATA_TYPE_DISABLED; + } + } + } + break; + case OMX_IndexParamStoreMetaDataBuffer: + { + StoreMetaDataInBuffersParams *pMetaParams = (StoreMetaDataInBuffersParams *)pComponentParameterStructure; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 portIndex = pMetaParams->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pMetaParams, sizeof(StoreMetaDataInBuffersParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC)) { + if (portIndex == INPUT_PORT_INDEX) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][META] %s port: metadata mode(%x) -> %s", + pExynosComponent, __FUNCTION__, + (portIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosPort->eMetaDataType, + (pMetaParams->bStoreMetaData == OMX_TRUE)? "enable":"disable"); + + if (pMetaParams->bStoreMetaData == OMX_TRUE) { + if (pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED) { + /* + * scenario : camera recording (camerasource or nativehandlesource) + * mode : kPortModeDynamicNativeHandle + * data : type, native_handle_t + */ + pExynosPort->eMetaDataType = METADATA_TYPE_DATA; + } else if (pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC_HANDLE) { + /* + * scenario : adaptive playback, screen recording + * mode : kPortModeDynamicANWBuffer + * data : type, buffer_handle_t + */ + pExynosPort->eMetaDataType = METADATA_TYPE_GRAPHIC; + } + } + + if (pMetaParams->bStoreMetaData == OMX_FALSE) { + if (pExynosPort->eMetaDataType == METADATA_TYPE_DATA) + pExynosPort->eMetaDataType = METADATA_TYPE_DISABLED; + else if (pExynosPort->eMetaDataType == METADATA_TYPE_GRAPHIC) + pExynosPort->eMetaDataType = METADATA_TYPE_GRAPHIC_HANDLE; + } + } + break; + case OMX_IndexParamAllocateNativeHandle: + { + EnableAndroidNativeBuffersParams *pANBParams = (EnableAndroidNativeBuffersParams *)pComponentParameterStructure; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 portIndex = pANBParams->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pANBParams, sizeof(EnableAndroidNativeBuffersParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (portIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][NativeHandle] %s port: metadata(%x), NativeHandle(%d)", + pExynosComponent, __FUNCTION__, + (portIndex == INPUT_PORT_INDEX)? "input":"output", + pExynosPort->eMetaDataType, pANBParams->enable); + + /* ideally, hope that StoreMedataBuffer should be called before requesting AllocateNativeHandle. + * but, frameworks just call AllocateNativeHandle. + */ + if ((pExynosPort->eMetaDataType == METADATA_TYPE_DISABLED) && + (pANBParams->enable == OMX_TRUE)) { + /* + * scenario : drm playback, WFD w/ HDCP + * mode : kPortModePresetSecureBuffer + * data : native_handle_t + */ + pExynosPort->bufferProcessType = BUFFER_SHARE; + pExynosPort->eMetaDataType = METADATA_TYPE_HANDLE; + } else if ((pANBParams->enable == OMX_FALSE) && + (pExynosPort->eMetaDataType == METADATA_TYPE_HANDLE)) { + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->eMetaDataType = METADATA_TYPE_DISABLED; + } + } + break; + case OMX_IndexParamAndroidNatvieBufferConsumerUsage: + { + OMX_PARAM_U32TYPE *pConsumerUsageBits = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 portIndex = pConsumerUsageBits->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pConsumerUsageBits, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pConsumerUsageBits->nPortIndex != OUTPUT_PORT_INDEX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid port index", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + if (pConsumerUsageBits->nU32 & BufferUsage::CPU_READ_OFTEN) + pExynosPort->bForceUseNonCompFormat = OMX_TRUE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s][ANB] Consumer usage bits : 0x%x", + pExynosComponent, __FUNCTION__, pConsumerUsageBits->nU32); + goto EXIT; + } + break; + + default: + { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] unsupported index (%d)", + pExynosComponent, __FUNCTION__, nIndex); + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_GetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_INOUT OMX_PTR pComponentConfigStructure) { + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoHdrStaticInfo: + { + DescribeHDRStaticInfoParams *pParams = (DescribeHDRStaticInfoParams *)pComponentConfigStructure; + EXYNOS_OMX_VIDEO_HDRSTATICINFO *pHDRStaticInfo = NULL; + OMX_U32 nPortIndex = pParams->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pParams, sizeof(DescribeHDRStaticInfoParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC)) { + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + } else if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + if (nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + } + + pHDRStaticInfo = &pExynosComponent->pExynosPort[nPortIndex].HDRStaticInfo; + + pParams->sInfo.sType1.mR.x = pHDRStaticInfo->red.x; + pParams->sInfo.sType1.mR.y = pHDRStaticInfo->red.y; + pParams->sInfo.sType1.mG.x = pHDRStaticInfo->green.x; + pParams->sInfo.sType1.mG.y = pHDRStaticInfo->green.y; + pParams->sInfo.sType1.mB.x = pHDRStaticInfo->blue.x; + pParams->sInfo.sType1.mB.y = pHDRStaticInfo->blue.y; + pParams->sInfo.sType1.mW.x = pHDRStaticInfo->white.x; + pParams->sInfo.sType1.mW.y = pHDRStaticInfo->white.y; + + pParams->sInfo.sType1.mMaxDisplayLuminance = pHDRStaticInfo->nMaxDisplayLuminance / 10000; /* for framework standard : cd/m^2 */ + pParams->sInfo.sType1.mMinDisplayLuminance = pHDRStaticInfo->nMinDisplayLuminance; + + pParams->sInfo.sType1.mMaxContentLightLevel = pHDRStaticInfo->nMaxContentLight; + pParams->sInfo.sType1.mMaxFrameAverageLightLevel = pHDRStaticInfo->nMaxPicAverageLight; + } + break; + case OMX_IndexConfigVideoColorAspects: + { + DescribeColorAspectsParams *pParams = (DescribeColorAspectsParams *)pComponentConfigStructure; + EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA = NULL; /* framework */ + EXYNOS_OMX_VIDEO_COLORASPECTS *pBSCA = NULL; /* bitstream */ + OMX_U32 nPortIndex = pParams->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pParams, sizeof(DescribeColorAspectsParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + /* get ColorAspects info from DataSpace and pixel format */ + if (pParams->bDataSpaceChanged == OMX_TRUE) { + /* it will query to encoders. + * it allows vendors to use extended dataspace and to support change at runtime. + */ + if ((pExynosComponent->codecType != HW_VIDEO_ENC_CODEC) && + (pExynosComponent->codecType != HW_VIDEO_ENC_SECURE_CODEC)) { + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + ret = getColorAspectsFromDataSpace(pParams); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Updated ColorAspects: format(0x%x), datasapce(0x%x), R(0x%x), P(0x%x), M(0x%x), T(0x%x), ret(0x%x)", + pExynosComponent, __FUNCTION__, + pParams->nPixelFormat, pParams->nDataSpace, + pParams->sAspects.mRange, + pParams->sAspects.mPrimaries, + pParams->sAspects.mMatrixCoeffs, + pParams->sAspects.mTransfer, + ret); + goto EXIT; + } + + /* return supportable dataSpace */ + if (pParams->bRequestingDataSpace == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Given ColorAspects: format(0x%x), datasapce(0x%x), R(0x%x), P(0x%x), M(0x%x), T(0x%x), ret(0x%x)", + pExynosComponent, __FUNCTION__, + pParams->nPixelFormat, pParams->nDataSpace, + pParams->sAspects.mRange, + pParams->sAspects.mPrimaries, + pParams->sAspects.mMatrixCoeffs, + pParams->sAspects.mTransfer, + ret); + + ret = getDataSpaceFromAspects(pParams); + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Guidance for DataSpace: datasapce(0x%x), ret(0x%x)", pExynosComponent, __FUNCTION__, + pParams->nDataSpace, ret); + + if ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC)) { + if ((nPortIndex != OUTPUT_PORT_INDEX) || + (ret != OMX_ErrorNone)) { + goto EXIT; + } + + /* update dataspace only frameworks requests dataspace */ + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].ColorAspects.nDataSpace = pParams->nDataSpace; + } + goto EXIT; + } + + if ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC)) { + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pFWCA = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].ColorAspects; + pBSCA = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX].ColorAspects; + + if (Exynos_OSAL_Strstr(pExynosComponent->componentName, "VP9") || + Exynos_OSAL_Strstr(pExynosComponent->componentName, "vp9")) { + /* In case of VP9, should rely on information in webm container */ + getColorAspectsPreferFramework(pBSCA, pFWCA, (void *)pParams); + } else { + /* generally, rely on information in bitstream */ + getColorAspectsPreferBitstream(pBSCA, pFWCA, (void *)pParams); + } + } else if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + if (nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pFWCA = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX].ColorAspects; + pBSCA = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].ColorAspects; + + /* there isn't bitstream */ + getColorAspectsPreferFramework(pBSCA, pFWCA, (void *)pParams); + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] ColorAspects: pixelformat(0x%x), datasapce(0x%x), R(0x%x), P(0x%x), M(0x%x), T(0x%x), ret(0x%x)", + pExynosComponent, __FUNCTION__, + pParams->nPixelFormat, pParams->nDataSpace, + pParams->sAspects.mRange, + pParams->sAspects.mPrimaries, + pParams->sAspects.mMatrixCoeffs, + pParams->sAspects.mTransfer, + ret); + } + break; + case OMX_IndexConfigVideoHdr10PlusInfo: + { + DescribeHDR10PlusInfoParams *pParams = (DescribeHDR10PlusInfoParams *)pComponentConfigStructure; + DescribeHDR10PlusInfoParams *pOutParams = NULL; + OMX_U32 nPortIndex = pParams->nPortIndex; + int i; + + if ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC)) { +#if 0 + /* TO DO: Framework should set port index to OUTPUT */ + if (nPortIndex != OUTPUT_PORT_INDEX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid port index", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } +#endif + } else if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + if (nPortIndex != INPUT_PORT_INDEX) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid port index", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + } + + if (Exynos_OSAL_GetElemNum(&pExynosComponent->pExynosPort[nPortIndex].HdrDynamicInfoQ) > 0) { + pOutParams = (DescribeHDR10PlusInfoParams *)Exynos_OSAL_Dequeue(&pExynosComponent->pExynosPort[nPortIndex].HdrDynamicInfoQ); + if (pOutParams == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Dequeue HDR10+ info", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Memcpy(pParams->nValue, pOutParams->nValue, pOutParams->nParamSizeUsed); + pParams->nParamSizeUsed = pOutParams->nParamSizeUsed; + + for (i = 0; i < MAX_BUFFER_REF; i++) { + if ((pOutParams == pExynosComponent->HDR10plusList[i].pHDR10PlusInfo) && + (pExynosComponent->HDR10plusList[i].bOccupied == OMX_TRUE)) { + pExynosComponent->HDR10plusList[i].bOccupied = OMX_FALSE; + pExynosComponent->HDR10plusList[i].nTag = -1; + pExynosComponent->HDR10plusList[i].pHDR10PlusInfo = NULL; + + break; + } + } + + Exynos_OSAL_Free(pOutParams); + } + } + break; + default: + { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_SetConfig( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure) { + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] index = 0x%x", pExynosComponent, __FUNCTION__, nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoHdrStaticInfo: + { + DescribeHDRStaticInfoParams *pParams = (DescribeHDRStaticInfoParams *)pComponentConfigStructure; + EXYNOS_OMX_VIDEO_HDRSTATICINFO *pHDRStaticInfo = NULL; + OMX_U32 nPortIndex = pParams->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pParams, sizeof(DescribeHDRStaticInfoParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC)) { + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + } else if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + if (nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + } + + pHDRStaticInfo = &pExynosComponent->pExynosPort[nPortIndex].HDRStaticInfo; + + pHDRStaticInfo->red.x = pParams->sInfo.sType1.mR.x; + pHDRStaticInfo->red.y = pParams->sInfo.sType1.mR.y; + pHDRStaticInfo->green.x = pParams->sInfo.sType1.mG.x; + pHDRStaticInfo->green.y = pParams->sInfo.sType1.mG.y; + pHDRStaticInfo->blue.x = pParams->sInfo.sType1.mB.x; + pHDRStaticInfo->blue.y = pParams->sInfo.sType1.mB.y; + pHDRStaticInfo->white.x = pParams->sInfo.sType1.mW.x; + pHDRStaticInfo->white.y = pParams->sInfo.sType1.mW.y; + + pHDRStaticInfo->nMaxDisplayLuminance = pParams->sInfo.sType1.mMaxDisplayLuminance * 10000; /* for h.264/265 standard : 0.0001cd/m^2 */ + pHDRStaticInfo->nMinDisplayLuminance = pParams->sInfo.sType1.mMinDisplayLuminance; + + pHDRStaticInfo->nMaxContentLight = pParams->sInfo.sType1.mMaxContentLightLevel; + pHDRStaticInfo->nMaxPicAverageLight = pParams->sInfo.sType1.mMaxFrameAverageLightLevel; + } + break; + case OMX_IndexConfigVideoColorAspects: + { + DescribeColorAspectsParams *pParams = (DescribeColorAspectsParams *)pComponentConfigStructure; + EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA = NULL; /* framework */ + OMX_U32 nPortIndex = pParams->nPortIndex; + + ret = Exynos_OMX_Check_SizeVersion(pParams, sizeof(DescribeColorAspectsParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC)) { + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + } else if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + if (nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + } + + pFWCA = &pExynosComponent->pExynosPort[nPortIndex].ColorAspects; + + pFWCA->nRangeType = (OMX_U32)pParams->sAspects.mRange; + pFWCA->nDataSpace = (OMX_U32)pParams->nDataSpace; + pFWCA->nPrimaryType = (OMX_U32)pParams->sAspects.mPrimaries; + pFWCA->nTransferType = (OMX_U32)pParams->sAspects.mTransfer; + pFWCA->nCoeffType = (OMX_U32)pParams->sAspects.mMatrixCoeffs; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] ColorAspects: pixelformat(0x%x), datasapce(0x%x), R(0x%x), P(0x%x), M(0x%x), T(0x%x)", + pExynosComponent, __FUNCTION__, + pParams->nPixelFormat, pParams->nDataSpace, + pParams->sAspects.mRange, + pParams->sAspects.mPrimaries, + pParams->sAspects.mMatrixCoeffs, + pParams->sAspects.mTransfer); + } + break; + case OMX_IndexConfigVideoHdr10PlusInfo: + { + DescribeHDR10PlusInfoParams *pParams = (DescribeHDR10PlusInfoParams *)pComponentConfigStructure; + DescribeHDR10PlusInfoParams *pInParams = NULL; + OMX_U32 nPortIndex = pParams->nPortIndex; + + if ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC)) { +#if 0 + /* TO DO: Framework should set port index to OUTPUT */ + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } +#endif + if (pExynosComponent->pExynosPort->portDefinition.format.video.eCompressionFormat == (OMX_VIDEO_CODINGTYPE)OMX_VIDEO_CodingHEVC) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Ignore this config for in-band HDR10+ metadata", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } else if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + if (nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + if (pExynosComponent->pExynosPort->portDefinition.format.video.eCompressionFormat == OMX_VIDEO_CodingVP9) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Ignore this config for out-band HDR10+ metadata", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + + if ((pParams->nParamSize > MAX_HDR10PLUS_SIZE) || + (pParams->nParamSize < 1)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] invalid parameter (nParamSize: %d)", pExynosComponent, __FUNCTION__, pParams->nParamSize); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pInParams = (DescribeHDR10PlusInfoParams *)Exynos_OSAL_Malloc(pParams->nSize); + if (pInParams == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to malloc", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Memcpy(pInParams, pParams, pParams->nSize); + + if (Exynos_OSAL_Queue(&pExynosComponent->HDR10plusConfigQ, (void *)pInParams) != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Queue HDR10+ info", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pInParams); + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + break; + default: + { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +/* + * meta data contains the following data format. + * 1) METADATA_TYPE_DATA + * -------------------------------------------------------------------- + * | type | payload | + * -------------------------------------------------------------------- + * | kMetadataBufferTypeCameraSource | FDs | [ENC] in(Camera) + * -------------------------------------------------------------------- + * | kMetadataBufferTypeNativeHandleSource | native_handle_t * | [ENC] in(Camera)/out(WFD) + * -------------------------------------------------------------------- + * + * 2) METADATA_TYPE_HANDLE + * -------------------------------------------------------------------- + * | native_handle_t * | [DEC] in(Secure) + * -------------------------------------------------------------------- + * + * 3) METADATA_TYPE_GRAPHIC (LockMetaData/UnlockMetaData -> GetInfoFromMetaData + lockBuffer/unlockBuffer) + * -------------------------------------------------------------------- + * | kMetadataBufferTypeGrallocSource | buffer_handle_t | [DEC] out, [ENC] in(Camera:Opaque) + * -------------------------------------------------------------------- + * + * 4) METADATA_TYPE_GRAPHIC_HANDLE (LockMetaData/UnlockMetaData -> lockBuffer/unlockBuffer) + * -------------------------------------------------------------------- + * | buffer_handle_t | [DEC] out + * -------------------------------------------------------------------- + */ +OMX_ERRORTYPE Exynos_OSAL_GetInfoFromMetaData( + OMX_IN OMX_PTR pBuffer, + OMX_OUT EXYNOS_OMX_MULTIPLANE_BUFFER *pBufferInfo, + OMX_IN EXYNOS_METADATA_TYPE eMetaDataType) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + int i; + + FunctionIn(); + + if ((pBuffer == NULL) || + (pBufferInfo == NULL) || + (eMetaDataType == METADATA_TYPE_DISABLED)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Memset(pBufferInfo, 0, sizeof(EXYNOS_OMX_MULTIPLANE_BUFFER)); + + switch (eMetaDataType) { + case METADATA_TYPE_DATA: + { + MetadataBufferType type; + + /* MetadataBufferType */ + Exynos_OSAL_Memcpy(&type, (MetadataBufferType *)pBuffer, sizeof(MetadataBufferType)); + + if (type == kMetadataBufferTypeCameraSource) { + void *pAddress = NULL; + + /* FD of Y */ + Exynos_OSAL_Memcpy(&pAddress, ((char *)pBuffer) + sizeof(MetadataBufferType), sizeof(void *)); + pBufferInfo->fd[0] = (unsigned long)pAddress; + + /* FD of CbCr */ + Exynos_OSAL_Memcpy(&pAddress, ((char *)pBuffer) + sizeof(MetadataBufferType) + sizeof(void *), sizeof(void *)); + pBufferInfo->fd[1] = (unsigned long)pAddress; + + if ((pBufferInfo->fd[0] == 0) || + (pBufferInfo->fd[1] == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] CameraSource: invalid value(%x, %x)", + __FUNCTION__, pBufferInfo->fd[0], pBufferInfo->fd[1]); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] METADATA_DATA(CameraSource): %u %u", __FUNCTION__, pBufferInfo->fd[0], pBufferInfo->fd[1]); + } else if (type == kMetadataBufferTypeNativeHandleSource) { + VideoNativeHandleMetadata *pMetaData = (VideoNativeHandleMetadata *)pBuffer; + native_handle_t *pNativeHandle = NULL; + + if (pMetaData->pHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] NativeHandleSource: handle is NULL", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pNativeHandle = pMetaData->pHandle; + if (pNativeHandle->version != sizeof(native_handle_t)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] NativeHandleSource: version is invalid", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + // TODO : check numFds + for (i = 0; i < pNativeHandle->numFds; i++) { + pBufferInfo->fd[i] = (unsigned long)(pNativeHandle->data[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] METADATA_DATA(NativeHandle): %u", __FUNCTION__, pBufferInfo->fd[i]); + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] type(0x%x) is not supported on METADATA_TYPE_DATA", + __FUNCTION__, type); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + case METADATA_TYPE_HANDLE: + { + native_handle_t *pNativeHandle = (native_handle_t *)pBuffer; + int i; + + if (pNativeHandle->version != sizeof(native_handle_t)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] version is invalid on METADATA_TYPE_HANDLE", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + for (i = 0; i < pNativeHandle->numFds; i++) { + pBufferInfo->fd[i] = (unsigned long)(pNativeHandle->data[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] METADATA_HANDLE: %u", __FUNCTION__, pBufferInfo->fd[i]); + } + } + break; + case METADATA_TYPE_GRAPHIC: + { + /* just returns buffer_handle_t */ + MetadataBufferType type; + VideoGrallocMetadata *pMetaData = (VideoGrallocMetadata *)pBuffer; + + /* MetadataBufferType */ + Exynos_OSAL_Memcpy(&type, (MetadataBufferType *)pBuffer, sizeof(MetadataBufferType)); + + if (type == kMetadataBufferTypeGrallocSource) { + if (pMetaData->pHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] GrallocSource: handle is NULL", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + /* buffer_handle_t */ + pBufferInfo->addr[0] = (OMX_PTR)(pMetaData->pHandle); + pBufferInfo->eColorFormat = getBufferFormat(pBufferInfo->addr[0]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] METADATA_GRAPHIC(GrallocSource): %u, foramt(0x%x)", + __FUNCTION__, pBufferInfo->addr[0], pBufferInfo->eColorFormat); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] type(0x%x) is not supported on METADATA_TYPE_DATA", + __FUNCTION__, type); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_PTR Exynos_OSAL_AllocMetaDataBuffer( + OMX_HANDLETYPE hSharedMemory, + EXYNOS_METADATA_TYPE eMetaDataType, + OMX_U32 nSizeBytes, + MEMORY_TYPE eMemoryType) +{ + native_handle_t *pNativeHandle = NULL; + + OMX_PTR pTempBuffer = NULL; + OMX_PTR pTempVirAdd = NULL; + unsigned long nTempFD = 0; + + FunctionIn(); + + if (eMetaDataType == METADATA_TYPE_HANDLE) { /* native_handle_t */ + pNativeHandle = native_handle_create(FD_NUM, EXT_DATA_NUM); + if (pNativeHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to native_handle_create", __FUNCTION__); + pTempBuffer = NULL; + goto EXIT; + } + + pTempVirAdd = Exynos_OSAL_SharedMemory_Alloc(hSharedMemory, nSizeBytes, eMemoryType); + if (pTempVirAdd == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_SharedMemory_Alloc(size:%d, type:0x%x)", + __FUNCTION__, nSizeBytes, eMemoryType); + native_handle_delete(pNativeHandle); + pNativeHandle = NULL; + pTempBuffer = NULL; + goto EXIT; + } + + nTempFD = Exynos_OSAL_SharedMemory_VirtToION(hSharedMemory, pTempVirAdd); + + pNativeHandle->data[0] = (int)nTempFD; /* fd */ + pNativeHandle->data[1] = (int)nSizeBytes; /* buffer size */ + pNativeHandle->data[2] = 0; /* stream length. WFD(Converter) uses this for HDCP */ + + pTempBuffer = (OMX_PTR)pNativeHandle; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] not implemented yet", __FUNCTION__); + pTempBuffer = NULL; + } + +EXIT: + FunctionOut(); + + return pTempBuffer; +} + +OMX_ERRORTYPE Exynos_OSAL_FreeMetaDataBuffer( + OMX_HANDLETYPE hSharedMemory, + EXYNOS_METADATA_TYPE eMetaDataType, + OMX_PTR pTempBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + unsigned long nTempFD = 0; + OMX_PTR pTempVirAdd = NULL; + + native_handle_t *pNativeHandle = NULL; + + FunctionIn(); + + if (eMetaDataType == METADATA_TYPE_HANDLE) { /* native_handle_t */ + pNativeHandle = (native_handle_t *)pTempBuffer; + + if (pNativeHandle->version != sizeof(native_handle_t)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] NativeHandleSource: version is invalid", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + nTempFD = (unsigned long)pNativeHandle->data[0]; + pTempVirAdd = Exynos_OSAL_SharedMemory_IONToVirt(hSharedMemory, nTempFD); + + Exynos_OSAL_SharedMemory_Free(hSharedMemory, pTempVirAdd); + + native_handle_delete(pNativeHandle); + pTempBuffer = pNativeHandle = NULL; + + ret = OMX_ErrorNone; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] not implemented yet", __FUNCTION__); + ret = OMX_ErrorNotImplemented; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_SetPrependSPSPPSToIDR( + OMX_PTR pComponentParameterStructure, + OMX_PTR pbPrependSpsPpsToIdr) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + PrependSPSPPSToIDRFramesParams *pParams = (PrependSPSPPSToIDRFramesParams *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pParams, sizeof(PrependSPSPPSToIDRFramesParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OMX_Check_SizeVersion(PrependSPSPPSToIDRFramesParams)", __FUNCTION__); + goto EXIT; + } + + (*((OMX_BOOL *)pbPrependSpsPpsToIdr)) = pParams->bEnable; + +EXIT: + return ret; +} + +OMX_U32 Exynos_OSAL_GetDisplayExtraBufferCount(void) +{ + char value[PROPERTY_VALUE_MAX] = {0, }; + + if (property_get("debug.hwc.otf", value, NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] DisplayExtraBufferCount is 3. The OTF exist", __FUNCTION__); + return 3; /* Display System has OTF */ + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] DisplayExtraBufferCount is 2. The OTF not exist", __FUNCTION__); + return 2; /* min count */ +} + +OMX_ERRORTYPE Exynos_OSAL_AddVendorExt( + OMX_HANDLETYPE hComponent, + OMX_STRING cExtName, + OMX_INDEXTYPE nIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_PTR *pVendorExts = NULL; + OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *pVendorExt = NULL; + + OMX_U32 i; + int nSlotIndex = -1; + + FunctionIn(); + + if ((hComponent == NULL) || + (cExtName == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVendorExts = pExynosComponent->vendorExts; + for (i = 0; i < MAX_VENDOR_EXT_NUM; i++) { + if (pVendorExts[i] == NULL) { + nSlotIndex = (int)i; + break; + } + } + + if (nSlotIndex < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s][%p] VendorExt(%s) is not added. there is no more empty slot", __FUNCTION__, pExynosComponent, cExtName); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + switch ((int)nIndex) { + case OMX_IndexConfigVideoQPRange: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) + ((6 - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE)); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexConfigVideoQPRange; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 6; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"I-minQP"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[1].cKey, (OMX_PTR)"I-maxQP"); + pVendorExt->param[1].eValueType = OMX_AndroidVendorValueInt32; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[2].cKey, (OMX_PTR)"P-minQP"); + pVendorExt->param[2].eValueType = OMX_AndroidVendorValueInt32; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[3].cKey, (OMX_PTR)"P-maxQP"); + pVendorExt->param[3].eValueType = OMX_AndroidVendorValueInt32; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[4].cKey, (OMX_PTR)"B-minQP"); + pVendorExt->param[4].eValueType = OMX_AndroidVendorValueInt32; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[5].cKey, (OMX_PTR)"B-maxQP"); + pVendorExt->param[5].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexParamNumberRefPframes: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexParamNumberRefPframes; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"number"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoEnableGPB: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexParamVideoEnableGPB; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"enable"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexExynosParamBufferCopy: + { + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexExynosParamBufferCopy; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"enable"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } + break; + case OMX_IndexParamVideoDropControl: + { + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexParamVideoDropControl; + pVendorExt->eDir = OMX_DirInput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"enable"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } + break; + case OMX_IndexParamVideoDisableDFR: + { + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexParamVideoDisableDFR; + pVendorExt->eDir = OMX_DirInput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"disable"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } + break; + case OMX_IndexParamVideoCompressedColorFormat: + { + if ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexParamVideoCompressedColorFormat; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"value"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoChromaQP: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) + ((2 - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE)); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexParamVideoChromaQP; + pVendorExt->eDir = OMX_DirInput; + pVendorExt->nParamCount = 2; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"cr"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[1].cKey, (OMX_PTR)"cb"); + pVendorExt->param[1].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoDisableHBEncoding: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexParamVideoDisableHBEncoding; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"disable"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; +#ifdef USE_SKYPE_HD + case OMX_IndexSkypeParamDriverVersion: + { + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeParamDriverVersion; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"number"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } + break; + case OMX_IndexSkypeParamLowLatency: + { + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeParamLowLatency; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"enable"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } + break; + case OMX_IndexSkypeParamEncoderMaxTemporalLayerCount: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) + ((2 - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE)); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeParamEncoderMaxTemporalLayerCount; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 2; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"max-p-count"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[1].cKey, (OMX_PTR)"max-b-count"); + pVendorExt->param[1].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeParamEncoderMaxLTR: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeParamEncoderMaxLTR; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"max-count"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeParamEncoderLTR: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeParamEncoderLTR; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"num-ltr-frames"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeParamEncoderPreprocess: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) + ((2 - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE)); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeParamEncoderPreprocess; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 2; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"max-downscale-factor"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[1].cKey, (OMX_PTR)"rotation"); + pVendorExt->param[1].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) + ((2 - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE)); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexParamVideoProfileLevelCurrent; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 2; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"profile"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[1].cKey, (OMX_PTR)"level"); + pVendorExt->param[1].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeParamEncoderSar: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) + ((2 - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE)); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeParamEncoderSar; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 2; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"width"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[1].cKey, (OMX_PTR)"height"); + pVendorExt->param[1].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoAvc: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexParamVideoAvc; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"spacing"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeConfigEncoderLTR: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) + ((2 - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE)); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeConfigEncoderLTR; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 2; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"mark-frame"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[1].cKey, (OMX_PTR)"use-frame"); + pVendorExt->param[1].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeConfigQP: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeConfigQP; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"value"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeConfigBasePid: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeConfigBasePid; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"value"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeParamEncoderInputControl: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeParamEncoderInputControl; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"enable"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeConfigEncoderInputTrigger: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeConfigEncoderInputTrigger; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"timestamp"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt64; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeParamVideoBitrate: + { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC)) { + + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE) + ((2 - 1) * sizeof(OMX_CONFIG_ANDROID_VENDOR_PARAMTYPE)); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexSkypeParamVideoBitrate; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 2; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"value"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[1].cKey, (OMX_PTR)"bitrate"); + pVendorExt->param[1].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; +#endif // USE_SKYPE_HD + case OMX_IndexExynosParamImageConvertMode: + { + if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) { + int nSize = sizeof(OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE); + + pVendorExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)Exynos_OSAL_Malloc(nSize); + if (pVendorExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s][%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__, pExynosComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + Exynos_OSAL_Memset(pVendorExt, 0, nSize); + + InitOMXParams(pVendorExt, nSize); + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->cName, (OMX_PTR)cExtName); + + pVendorExt->nIndex = (OMX_U32)OMX_IndexExynosParamImageConvertMode; + pVendorExt->eDir = OMX_DirOutput; + pVendorExt->nParamCount = 1; + + Exynos_OSAL_Strcpy((OMX_PTR)pVendorExt->param[0].cKey, (OMX_PTR)"value"); + pVendorExt->param[0].eValueType = OMX_AndroidVendorValueInt32; + + pVendorExts[nSlotIndex] = pVendorExt; + } else { + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + } + break; + default: + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s][%p] vendor extension(name:%s, index:0x%x) is added", + __FUNCTION__, pExynosComponent, cExtName, nIndex); + +EXIT: + FunctionOut(); + + return ret; +} + +void Exynos_OSAL_DelVendorExts(OMX_HANDLETYPE hComponent) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_PTR *pVendorExts = NULL; + OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *pVendorExt = NULL; + + OMX_U32 i; + + + FunctionIn(); + + if (hComponent == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) + goto EXIT; + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + pVendorExts = pExynosComponent->vendorExts; + + for (i = 0; i < MAX_VENDOR_EXT_NUM; i++) { + if (pVendorExts[i] != NULL) { + Exynos_OSAL_Free(pVendorExts[i]); + pVendorExts[i] = NULL; + } + } + +EXIT: + FunctionOut(); + + return; +} + +OMX_ERRORTYPE Exynos_OSAL_GetVendorExt( + OMX_HANDLETYPE hComponent, + OMX_PTR pConfig) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *pDstExt = NULL; + OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *pSrcExt = NULL; + + OMX_U32 i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pConfig == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pDstExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)pConfig; + + if ((pDstExt->nIndex >= MAX_VENDOR_EXT_NUM) || + (pExynosComponent->vendorExts[pDstExt->nIndex] == NULL)) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + + pSrcExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)pExynosComponent->vendorExts[pDstExt->nIndex]; + + ret = Exynos_OMX_Check_SizeVersion(pDstExt, pSrcExt->nSize); + if (ret != OMX_ErrorNone) { + if ((pDstExt->nSize < pSrcExt->nSize) || + (pDstExt->nParamSizeUsed < pSrcExt->nParamCount)) { + /* in order to inform number of required parameter */ + pDstExt->nParamCount = pSrcExt->nParamCount; + ret = OMX_ErrorNone; + } + + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s][%p] index:%d -> vendor extension(%s)", + __FUNCTION__, pExynosComponent, pDstExt->nIndex, pSrcExt->cName); + + switch ((int)pSrcExt->nIndex) { + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE QpRange; + + Exynos_OSAL_Memset(&QpRange, 0, sizeof(QpRange)); + InitOMXParams(&QpRange, sizeof(QpRange)); + + QpRange.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetConfig(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&QpRange); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + Exynos_OSAL_Memcpy(pDstExt->param[i].cKey, pSrcExt->param[i].cKey, sizeof(pSrcExt->param[i].cKey)); + pDstExt->param[i].eValueType = pSrcExt->param[i].eValueType; + pDstExt->param[i].bSet = OMX_TRUE; + } + + pDstExt->param[0].nInt32 = QpRange.qpRangeI.nMinQP; + pDstExt->param[1].nInt32 = QpRange.qpRangeI.nMaxQP; + pDstExt->param[2].nInt32 = QpRange.qpRangeP.nMinQP; + pDstExt->param[3].nInt32 = QpRange.qpRangeP.nMaxQP; + pDstExt->param[4].nInt32 = QpRange.qpRangeB.nMinQP; + pDstExt->param[5].nInt32 = QpRange.qpRangeB.nMaxQP; + } + } + break; + case OMX_IndexParamNumberRefPframes: + { + OMX_PARAM_U32TYPE NumberRefPframes; + + Exynos_OSAL_Memset(&NumberRefPframes, 0, sizeof(NumberRefPframes)); + InitOMXParams(&NumberRefPframes, sizeof(NumberRefPframes)); + + NumberRefPframes.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&NumberRefPframes); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = NumberRefPframes.nU32; + } + } + break; + case OMX_IndexParamVideoEnableGPB: + { + OMX_CONFIG_BOOLEANTYPE GPBEnable; + + Exynos_OSAL_Memset(&GPBEnable, 0, sizeof(GPBEnable)); + InitOMXParams(&GPBEnable, sizeof(GPBEnable)); + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&GPBEnable); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = GPBEnable.bEnabled; + } + } + break; + case OMX_IndexExynosParamBufferCopy: + { + OMX_PARAM_U32TYPE bufferCopy; + + Exynos_OSAL_Memset(&bufferCopy, 0, sizeof(bufferCopy)); + InitOMXParams(&bufferCopy, sizeof(bufferCopy)); + + bufferCopy.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&bufferCopy); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = bufferCopy.nU32; + } + } + break; + case OMX_IndexParamVideoDropControl: + { + OMX_CONFIG_BOOLEANTYPE dropControl; + + Exynos_OSAL_Memset(&dropControl, 0, sizeof(dropControl)); + InitOMXParams(&dropControl, sizeof(dropControl)); + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&dropControl); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = dropControl.bEnabled; + } + } + break; + case OMX_IndexParamVideoDisableDFR: + { + OMX_CONFIG_BOOLEANTYPE disableDFR; + + Exynos_OSAL_Memset(&disableDFR, 0, sizeof(disableDFR)); + InitOMXParams(&disableDFR, sizeof(disableDFR)); + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&disableDFR); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = disableDFR.bEnabled; + } + } + break; + case OMX_IndexParamVideoCompressedColorFormat: + { + OMX_PARAM_U32TYPE colorFormat; + + Exynos_OSAL_Memset(&colorFormat, 0, sizeof(colorFormat)); + InitOMXParams(&colorFormat, sizeof(colorFormat)); + + colorFormat.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&colorFormat); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = colorFormat.nU32; + } + } + break; + case OMX_IndexParamVideoChromaQP: + { + OMX_VIDEO_PARAM_CHROMA_QP_OFFSET chromaQPOffset; + + Exynos_OSAL_Memset(&chromaQPOffset, 0, sizeof(chromaQPOffset)); + InitOMXParams(&chromaQPOffset, sizeof(chromaQPOffset)); + + chromaQPOffset.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&chromaQPOffset); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + Exynos_OSAL_Memcpy(pDstExt->param[i].cKey, pSrcExt->param[i].cKey, sizeof(pSrcExt->param[i].cKey)); + pDstExt->param[i].eValueType = pSrcExt->param[i].eValueType; + pDstExt->param[i].bSet = OMX_TRUE; + } + pDstExt->param[0].nInt32 = chromaQPOffset.nCr; + pDstExt->param[1].nInt32 = chromaQPOffset.nCb; + } + } + break; + case OMX_IndexParamVideoDisableHBEncoding: + { + OMX_CONFIG_BOOLEANTYPE disableHBEncoding; + + Exynos_OSAL_Memset(&disableHBEncoding, 0, sizeof(disableHBEncoding)); + InitOMXParams(&disableHBEncoding, sizeof(disableHBEncoding)); + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&disableHBEncoding); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = disableHBEncoding.bEnabled; + } + } + break; +#ifdef USE_SKYPE_HD + case OMX_IndexSkypeParamDriverVersion: + { + OMX_VIDEO_PARAM_DRIVERVER DriverVer; + + Exynos_OSAL_Memset(&DriverVer, 0, sizeof(DriverVer)); + InitOMXParams(&DriverVer, sizeof(DriverVer)); + + DriverVer.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&DriverVer); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = (OMX_U32)DriverVer.nDriverVersion; + } + } + break; + case OMX_IndexSkypeParamLowLatency: + { + OMX_PARAM_U32TYPE lowLatency; + + Exynos_OSAL_Memset(&lowLatency, 0, sizeof(lowLatency)); + InitOMXParams(&lowLatency, sizeof(lowLatency)); + + lowLatency.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&lowLatency); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = lowLatency.nU32; + } + } + break; + case OMX_IndexSkypeParamEncoderMaxTemporalLayerCount: + { + OMX_PARAM_ENC_MAX_TEMPORALLAYER_COUNT temporalLayer; + + Exynos_OSAL_Memset(&temporalLayer, 0, sizeof(temporalLayer)); + InitOMXParams(&temporalLayer, sizeof(temporalLayer)); + + temporalLayer.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&temporalLayer); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + Exynos_OSAL_Memcpy(pDstExt->param[i].cKey, pSrcExt->param[i].cKey, sizeof(pSrcExt->param[i].cKey)); + pDstExt->param[i].eValueType = pSrcExt->param[i].eValueType; + pDstExt->param[i].bSet = OMX_TRUE; + } + + pDstExt->param[0].nInt32 = temporalLayer.nMaxCountP; + pDstExt->param[1].nInt32 = temporalLayer.nMaxCountB; + } + } + break; + case OMX_IndexSkypeParamEncoderMaxLTR: + { + OMX_PARAM_U32TYPE LTR; + + Exynos_OSAL_Memset(<R, 0, sizeof(LTR)); + InitOMXParams(<R, sizeof(LTR)); + + LTR.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)<R); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = LTR.nU32; + } + } + break; + case OMX_IndexSkypeParamEncoderLTR: + { + OMX_PARAM_U32TYPE LTR; + + Exynos_OSAL_Memset(<R, 0, sizeof(LTR)); + InitOMXParams(<R, sizeof(LTR)); + + LTR.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)<R); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = LTR.nU32; + } + } + break; + case OMX_IndexSkypeParamEncoderPreprocess: + { + OMX_PARAM_ENC_PREPROCESS preprocess; + + Exynos_OSAL_Memset(&preprocess, 0, sizeof(preprocess)); + InitOMXParams(&preprocess, sizeof(preprocess)); + + preprocess.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&preprocess); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + Exynos_OSAL_Memcpy(pDstExt->param[i].cKey, pSrcExt->param[i].cKey, sizeof(pSrcExt->param[i].cKey)); + pDstExt->param[i].eValueType = pSrcExt->param[i].eValueType; + pDstExt->param[i].bSet = OMX_TRUE; + } + + pDstExt->param[0].nInt32 = preprocess.nResize; + pDstExt->param[1].nInt32 = preprocess.nRotation; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE profilelevel; + + Exynos_OSAL_Memset(&profilelevel, 0, sizeof(profilelevel)); + InitOMXParams(&profilelevel, sizeof(profilelevel)); + + profilelevel.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&profilelevel); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + Exynos_OSAL_Memcpy(pDstExt->param[i].cKey, pSrcExt->param[i].cKey, sizeof(pSrcExt->param[i].cKey)); + pDstExt->param[i].eValueType = pSrcExt->param[i].eValueType; + pDstExt->param[i].bSet = OMX_TRUE; + } + + pDstExt->param[0].nInt32 = profilelevel.eProfile; + pDstExt->param[1].nInt32 = profilelevel.eLevel; + } + } + break; + case OMX_IndexSkypeParamEncoderSar: + { + OMX_PARAM_ENC_SAR sar; + + Exynos_OSAL_Memset(&sar, 0, sizeof(sar)); + InitOMXParams(&sar, sizeof(sar)); + + sar.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&sar); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + Exynos_OSAL_Memcpy(pDstExt->param[i].cKey, pSrcExt->param[i].cKey, sizeof(pSrcExt->param[i].cKey)); + pDstExt->param[i].eValueType = pSrcExt->param[i].eValueType; + pDstExt->param[i].bSet = OMX_TRUE; + } + + pDstExt->param[0].nInt32 = sar.nWidth; + pDstExt->param[1].nInt32 = sar.nHeight; + } + } + break; + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE avctype; + + Exynos_OSAL_Memset(&avctype, 0, sizeof(avctype)); + InitOMXParams(&avctype, sizeof(avctype)); + + avctype.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&avctype); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = avctype.nSliceHeaderSpacing; + } + } + break; + case OMX_IndexSkypeConfigEncoderLTR: /* GetConfig() is not supported */ + case OMX_IndexSkypeConfigQP: + case OMX_IndexSkypeParamEncoderInputControl: + case OMX_IndexSkypeConfigEncoderInputTrigger: + { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + Exynos_OSAL_Memcpy(pDstExt->param[i].cKey, pSrcExt->param[i].cKey, sizeof(pSrcExt->param[i].cKey)); + pDstExt->param[i].eValueType = pSrcExt->param[i].eValueType; + pDstExt->param[i].bSet = OMX_FALSE; + } + } + break; + case OMX_IndexSkypeConfigBasePid: + { + OMX_VIDEO_CONFIG_BASELAYERPID BaseLayerPid; + + Exynos_OSAL_Memset(&BaseLayerPid, 0, sizeof(BaseLayerPid)); + InitOMXParams(&BaseLayerPid, sizeof(BaseLayerPid)); + + BaseLayerPid.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetConfig(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&BaseLayerPid); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + Exynos_OSAL_Memcpy(pDstExt->param[0].cKey, pSrcExt->param[0].cKey, sizeof(pSrcExt->param[0].cKey)); + pDstExt->param[0].eValueType = pSrcExt->param[0].eValueType; + pDstExt->param[0].bSet = OMX_TRUE; + pDstExt->param[0].nInt32 = BaseLayerPid.nPID; + } + } + break; + case OMX_IndexSkypeParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE Bitrate; + + Exynos_OSAL_Memset(&Bitrate, 0, sizeof(Bitrate)); + InitOMXParams(&Bitrate, sizeof(Bitrate)); + + Bitrate.nPortIndex = pSrcExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pSrcExt->nIndex, (OMX_PTR)&Bitrate); + if (ret == OMX_ErrorNone) { + Exynos_OSAL_Memcpy(pDstExt->cName, pSrcExt->cName, sizeof(pDstExt->cName)); + pDstExt->eDir = pSrcExt->eDir; + pDstExt->nParamCount = pSrcExt->nParamCount; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + Exynos_OSAL_Memcpy(pDstExt->param[i].cKey, pSrcExt->param[i].cKey, sizeof(pSrcExt->param[i].cKey)); + pDstExt->param[i].eValueType = pSrcExt->param[i].eValueType; + pDstExt->param[i].bSet = OMX_TRUE; + } + + pDstExt->param[0].nInt32 = Bitrate.eControlRate; + pDstExt->param[1].nInt32 = Bitrate.nTargetBitrate; + } + } + break; +#endif // USE_SKYPE_HD + default: + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_SetVendorExt( + OMX_HANDLETYPE hComponent, + OMX_PTR pConfig) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *pDstExt = NULL; + OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *pSrcExt = NULL; + + OMX_U32 i; + + FunctionIn(); + + if ((hComponent == NULL) || + (pConfig == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + pSrcExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)pConfig; + + for (i = 0; i < MAX_VENDOR_EXT_NUM; i++) { + pDstExt = (OMX_CONFIG_ANDROID_VENDOR_EXTENSIONTYPE *)pExynosComponent->vendorExts[i]; + if (pDstExt == NULL) + break; + + if (!Exynos_OSAL_Strcmp(pDstExt->cName, pSrcExt->cName)) + break; + + pDstExt = NULL; + } + + if (pDstExt == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] vendor extension(name:%s) is not supported", + __FUNCTION__, pExynosComponent, pSrcExt->cName); + ret = OMX_ErrorUnsupportedSetting; + goto EXIT; + } + + ret = Exynos_OMX_Check_SizeVersion(pSrcExt, pDstExt->nSize); + if (ret != OMX_ErrorNone) + goto EXIT; + + if ((pSrcExt->eDir != pDstExt->eDir) || + (pSrcExt->nParamCount != pDstExt->nParamCount)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s][%p] vendor extension(%s)", + __FUNCTION__, pExynosComponent, pSrcExt->cName); + + switch ((int)pDstExt->nIndex) { + case OMX_IndexConfigVideoQPRange: + { + OMX_VIDEO_QPRANGETYPE QpRange; + + Exynos_OSAL_Memset(&QpRange, 0, sizeof(QpRange)); + InitOMXParams(&QpRange, sizeof(QpRange)); + + QpRange.nPortIndex = pDstExt->eDir; + + ret = pOMXComponent->GetConfig(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&QpRange); + if (ret != OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + if (pSrcExt->param[i].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"I-minQP")) { + QpRange.qpRangeI.nMinQP = pSrcExt->param[i].nInt32; + } else if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"I-maxQP")) { + QpRange.qpRangeI.nMaxQP = pSrcExt->param[i].nInt32; + } else if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"P-minQP")) { + QpRange.qpRangeP.nMinQP = pSrcExt->param[i].nInt32; + } else if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"P-maxQP")) { + QpRange.qpRangeP.nMaxQP = pSrcExt->param[i].nInt32; + } else if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"B-minQP")) { + QpRange.qpRangeB.nMinQP = pSrcExt->param[i].nInt32; + } else if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"B-maxQP")) { + QpRange.qpRangeB.nMaxQP = pSrcExt->param[i].nInt32; + } + } + } + + ret = pOMXComponent->SetConfig(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&QpRange); + } + break; + case OMX_IndexParamNumberRefPframes: + { + OMX_PARAM_U32TYPE NumberRefPframes; + + Exynos_OSAL_Memset(&NumberRefPframes, 0, sizeof(NumberRefPframes)); + InitOMXParams(&NumberRefPframes, sizeof(NumberRefPframes)); + + NumberRefPframes.nPortIndex = pDstExt->eDir; + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"number")) + NumberRefPframes.nU32 = pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&NumberRefPframes); + } + break; + case OMX_IndexParamVideoEnableGPB: + { + OMX_CONFIG_BOOLEANTYPE GPBEnable; + + Exynos_OSAL_Memset(&GPBEnable, 0, sizeof(GPBEnable)); + InitOMXParams(&GPBEnable, sizeof(GPBEnable)); + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"enable")) + GPBEnable.bEnabled = (OMX_BOOL)pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&GPBEnable); + } + break; + case OMX_IndexExynosParamBufferCopy: + { + OMX_PARAM_U32TYPE bufferCopy; + + Exynos_OSAL_Memset(&bufferCopy, 0, sizeof(bufferCopy)); + InitOMXParams(&bufferCopy, sizeof(bufferCopy)); + + bufferCopy.nPortIndex = pDstExt->eDir; + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"enable")) + bufferCopy.nU32 = pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&bufferCopy); + } + break; + case OMX_IndexParamVideoDropControl: + { + OMX_CONFIG_BOOLEANTYPE dropControl; + + Exynos_OSAL_Memset(&dropControl, 0, sizeof(dropControl)); + InitOMXParams(&dropControl, sizeof(dropControl)); + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"enable")) + dropControl.bEnabled = (OMX_BOOL)pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&dropControl); + } + break; + case OMX_IndexParamVideoDisableDFR: + { + OMX_CONFIG_BOOLEANTYPE disableDFR; + + Exynos_OSAL_Memset(&disableDFR, 0, sizeof(disableDFR)); + InitOMXParams(&disableDFR, sizeof(disableDFR)); + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"disable")) + disableDFR.bEnabled = (OMX_BOOL)pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&disableDFR); + } + break; + case OMX_IndexParamVideoCompressedColorFormat: + { + OMX_PARAM_U32TYPE colorFormat; + + Exynos_OSAL_Memset(&colorFormat, 0, sizeof(colorFormat)); + InitOMXParams(&colorFormat, sizeof(colorFormat)); + + colorFormat.nPortIndex = pDstExt->eDir; + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"value")) + colorFormat.nU32 = pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&colorFormat); + } + break; + case OMX_IndexParamVideoChromaQP: + { + OMX_VIDEO_PARAM_CHROMA_QP_OFFSET chromaQPOffset; + + Exynos_OSAL_Memset(&chromaQPOffset, 0, sizeof(chromaQPOffset)); + InitOMXParams(&chromaQPOffset, sizeof(chromaQPOffset)); + + chromaQPOffset.nPortIndex = pDstExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&chromaQPOffset); + if (ret!= OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + if (pSrcExt->param[i].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"cr")) { + chromaQPOffset.nCr = pSrcExt->param[i].nInt32; + } else if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"cb")) { + chromaQPOffset.nCb = pSrcExt->param[i].nInt32; + } + } + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&chromaQPOffset); + } + break; + case OMX_IndexParamVideoDisableHBEncoding: + { + OMX_CONFIG_BOOLEANTYPE disableHBEncoding; + + Exynos_OSAL_Memset(&disableHBEncoding, 0, sizeof(disableHBEncoding)); + InitOMXParams(&disableHBEncoding, sizeof(disableHBEncoding)); + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"disable")) + disableHBEncoding.bEnabled = (OMX_BOOL)pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&disableHBEncoding); + } + break; +#ifdef USE_SKYPE_HD + case OMX_IndexSkypeParamLowLatency: + { + OMX_PARAM_U32TYPE lowLatency; + + Exynos_OSAL_Memset(&lowLatency, 0, sizeof(lowLatency)); + InitOMXParams(&lowLatency, sizeof(lowLatency)); + + lowLatency.nPortIndex = pDstExt->eDir; + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"enable")) + lowLatency.nU32 = pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&lowLatency); + } + break; + case OMX_IndexSkypeParamEncoderLTR: + { + OMX_PARAM_U32TYPE LTR; + + Exynos_OSAL_Memset(<R, 0, sizeof(LTR)); + InitOMXParams(<R, sizeof(LTR)); + + LTR.nPortIndex = pDstExt->eDir; + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"num-ltr-frames")) + LTR.nU32 = pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)<R); + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE profilelevel; + + Exynos_OSAL_Memset(&profilelevel, 0, sizeof(profilelevel)); + InitOMXParams(&profilelevel, sizeof(profilelevel)); + + profilelevel.nPortIndex = pDstExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&profilelevel); + if (ret != OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + if (pSrcExt->param[i].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"profile")) { + profilelevel.eProfile = pSrcExt->param[i].nInt32; + } else if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"level")) { + profilelevel.eLevel = pSrcExt->param[i].nInt32; + } + } + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&profilelevel); + } + break; + case OMX_IndexSkypeParamEncoderSar: + { + OMX_PARAM_ENC_SAR sar; + + Exynos_OSAL_Memset(&sar, 0, sizeof(sar)); + InitOMXParams(&sar, sizeof(sar)); + + sar.nPortIndex = pDstExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&sar); + if (ret != OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + if (pSrcExt->param[i].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"width")) { + sar.nWidth = pSrcExt->param[i].nInt32; + } else if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"height")) { + sar.nHeight = pSrcExt->param[i].nInt32; + } + } + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&sar); + } + break; + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE avctype; + + Exynos_OSAL_Memset(&avctype, 0, sizeof(avctype)); + InitOMXParams(&avctype, sizeof(avctype)); + + avctype.nPortIndex = pDstExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&avctype); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"spacing")) + avctype.nSliceHeaderSpacing = pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&avctype); + } + break; + case OMX_IndexSkypeConfigEncoderLTR: + { + for (i = 0; i < pSrcExt->nParamCount; i++) { + if (pSrcExt->param[i].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"mark-frame")) { + OMX_VIDEO_CONFIG_MARKLTRFRAME markFrame; + + Exynos_OSAL_Memset(&markFrame, 0, sizeof(markFrame)); + InitOMXParams(&markFrame, sizeof(markFrame)); + + markFrame.nPortIndex = pDstExt->eDir; + markFrame.nLongTermFrmIdx = pSrcExt->param[i].nInt32; + + ret = pOMXComponent->SetConfig(hComponent, (OMX_INDEXTYPE)OMX_IndexSkypeConfigMarkLTRFrame, (OMX_PTR)&markFrame); + if (ret != OMX_ErrorNone) + goto EXIT; + } else if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"use-frame")) { + OMX_VIDEO_CONFIG_USELTRFRAME useFrame; + + Exynos_OSAL_Memset(&useFrame, 0, sizeof(useFrame)); + InitOMXParams(&useFrame, sizeof(useFrame)); + + useFrame.nPortIndex = pDstExt->eDir; + useFrame.nUsedLTRFrameBM = (OMX_U16)pSrcExt->param[i].nInt32; + + ret = pOMXComponent->SetConfig(hComponent, (OMX_INDEXTYPE)OMX_IndexSkypeConfigUseLTRFrame, (OMX_PTR)&useFrame); + if (ret != OMX_ErrorNone) + goto EXIT; + } + } + } + } + break; + case OMX_IndexSkypeConfigQP: + { + OMX_VIDEO_CONFIG_QP ConfigQP; + + Exynos_OSAL_Memset(&ConfigQP, 0, sizeof(ConfigQP)); + InitOMXParams(&ConfigQP, sizeof(ConfigQP)); + + ConfigQP.nPortIndex = pDstExt->eDir; + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"value")) + ConfigQP.nQP = (OMX_U32)pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetConfig(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&ConfigQP); + } + break; + case OMX_IndexSkypeConfigBasePid: + { + OMX_VIDEO_CONFIG_BASELAYERPID BaseLayerPid; + + Exynos_OSAL_Memset(&BaseLayerPid, 0, sizeof(BaseLayerPid)); + InitOMXParams(&BaseLayerPid, sizeof(BaseLayerPid)); + + BaseLayerPid.nPortIndex = pDstExt->eDir; + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"value")) + BaseLayerPid.nPID = pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetConfig(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&BaseLayerPid); + } + break; + case OMX_IndexSkypeParamEncoderInputControl: + { + OMX_PARAM_U32TYPE inputControl; + + Exynos_OSAL_Memset(&inputControl, 0, sizeof(inputControl)); + InitOMXParams(&inputControl, sizeof(inputControl)); + + if ((pSrcExt->eDir != pDstExt->eDir) || + (pSrcExt->nParamCount != pDstExt->nParamCount)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + inputControl.nPortIndex = pDstExt->eDir; + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"enable")) + inputControl.nU32 = pSrcExt->param[0].nInt32; + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&inputControl); + } + break; + case OMX_IndexSkypeConfigEncoderInputTrigger: + { + OMX_CONFIG_ENC_TRIGGER_TS triggerTS; + + Exynos_OSAL_Memset(&triggerTS, 0, sizeof(triggerTS)); + InitOMXParams(&triggerTS, sizeof(triggerTS)); + + triggerTS.nPortIndex = pDstExt->eDir; + + if (pSrcExt->param[0].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[0].cKey, (OMX_PTR)"timestamp")) + triggerTS.nTimestamp = pSrcExt->param[0].nInt64; + } + + ret = pOMXComponent->SetConfig(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&triggerTS); + } + break; + case OMX_IndexSkypeParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE Bitrate; + + Exynos_OSAL_Memset(&Bitrate, 0, sizeof(Bitrate)); + InitOMXParams(&Bitrate, sizeof(Bitrate)); + + Bitrate.nPortIndex = pDstExt->eDir; + + ret = pOMXComponent->GetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&Bitrate); + if (ret != OMX_ErrorNone) + goto EXIT; + + for (i = 0; i < pSrcExt->nParamCount; i++) { + if (pSrcExt->param[i].bSet == OMX_TRUE) { + if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"value")) { + Bitrate.eControlRate = (OMX_VIDEO_CONTROLRATETYPE)pSrcExt->param[i].nInt32; + } else if (!Exynos_OSAL_Strcmp((OMX_PTR)pSrcExt->param[i].cKey, (OMX_PTR)"bitrate")) { + Bitrate.nTargetBitrate = pSrcExt->param[i].nInt32; + } + } + } + + ret = pOMXComponent->SetParameter(hComponent, (OMX_INDEXTYPE)pDstExt->nIndex, (OMX_PTR)&Bitrate); + } + break; +#endif // USE_SKYPE_HD + default: + break; + } + +EXIT: + FunctionOut(); + + return ret; + +} + +OMX_HANDLETYPE Exynos_OSAL_CreatePerformanceHandle(OMX_BOOL bIsEncoder) { + PERFORMANCE_HANDLE *pPerfHandle = (PERFORMANCE_HANDLE*)malloc(sizeof(PERFORMANCE_HANDLE)); + if (pPerfHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] failed to allocate PERFORMANCE_HANDLE", __FUNCTION__); + return NULL; + } + + pPerfHandle->bIsEncoder = ((bIsEncoder == OMX_TRUE)? true:false); + + pPerfHandle->pEpic = createOperator((pPerfHandle->bIsEncoder)? eVideoEncoding:eVideoDecoding); + if (pPerfHandle->pEpic == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] Failed to create EpicOperator", __FUNCTION__); + free(pPerfHandle); + return NULL; + } + + if (!pPerfHandle->bIsEncoder) { + epic::IEpicOperator *pEpic = static_cast(pPerfHandle->pEpic); + if (pEpic != NULL) + pEpic->doAction(eAcquire, NULL); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] EpicOperator is acquired", __FUNCTION__); + } + + return pPerfHandle; +} + +void Exynos_OSAL_Performance(OMX_HANDLETYPE handle, int value, int fps) +{ + PERFORMANCE_HANDLE *pPerfHandle = (PERFORMANCE_HANDLE*)handle; + if (pPerfHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] PERFORMANCE_HANDLE is invalid", __FUNCTION__); + return; + } + + epic::IEpicOperator* pEpic = static_cast(pPerfHandle->pEpic); + if (pEpic == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] EpicOperator is invalid", __FUNCTION__); + return; + } + + if (pPerfHandle->bIsEncoder) { + static int timeslice = -1; /* uninitialized */ + + if (timeslice == -1) + timeslice = property_get_int32("ro.vendor.power.timeslice", 1000/* default: 1000ms */); + + int vectors[] = { 1, 2, 4, 5, 8, 10, 20, 40 }; + int threshold = vectors[0]; + int i = 0; + + for (i = 0; i < (int)(sizeof(vectors)/sizeof(vectors[0])); i++) { + if ((vectors[i] * 1000/*ms*/ / (fps? fps:1)) > timeslice) { + /* interval := (vectors[i] * (1000 / fps)ms) > timeslice + * it can not be available to inform a hint within timeslice + */ + break; + } + + threshold = vectors[i]; + } + + if ((value >= 0) && (value % threshold) == 0) { + pEpic->doAction(eAcquire, nullptr); + } + } +} + +void Exynos_OSAL_ReleasePerformanceHandle(OMX_HANDLETYPE handle) { + PERFORMANCE_HANDLE *pPerfHandle = (PERFORMANCE_HANDLE*)handle; + if (pPerfHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] PERFORMANCE_HANDLE is invalid", __FUNCTION__); + return; + } + + epic::IEpicOperator* pEpic = static_cast(pPerfHandle->pEpic); + if (pEpic == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] EpicOperator is invalid", __FUNCTION__); + free(pPerfHandle); + return; + } + + if (!pPerfHandle->bIsEncoder) { + pEpic->doAction(eRelease, NULL); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] EpicOperator is released", __FUNCTION__); + } + + free(pPerfHandle); + + return; +} + +#ifdef __cplusplus +} +#endif diff --git a/openmax/osal/Exynos_OSAL_Android.h b/openmax/osal/Exynos_OSAL_Android.h new file mode 100644 index 0000000..8e15344 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Android.h @@ -0,0 +1,79 @@ +/* + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Android.h + * @brief + * @author Seungbeom Kim (sbcrux.kim@samsung.com) + * @author Hyeyeon Chung (hyeon.chung@samsung.com) + * @author Yunji Kim (yunji.kim@samsung.com) + * @author Jinsung Yang (jsgood.yang@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef Exynos_OSAL_ANDROID +#define Exynos_OSAL_ANDROID + +#include "OMX_Types.h" +#include "OMX_Core.h" +#include "OMX_Index.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OSAL_SharedMemory.h" + +#include "ExynosVideoApi.h" + +#ifdef __cplusplus +extern "C" { +#endif +OMX_HANDLETYPE Exynos_OSAL_RefCount_Create(); +OMX_ERRORTYPE Exynos_OSAL_RefCount_Reset(OMX_HANDLETYPE hREF); +OMX_ERRORTYPE Exynos_OSAL_RefCount_Terminate(OMX_HANDLETYPE hREF); +OMX_ERRORTYPE Exynos_OSAL_RefCount_Increase(OMX_HANDLETYPE hREF, OMX_PTR pBuffer, EXYNOS_OMX_BASEPORT *pExynosPort); +OMX_ERRORTYPE Exynos_OSAL_RefCount_Decrease(OMX_HANDLETYPE hREF, OMX_PTR pBuffer, ReleaseDPB dpbFD[VIDEO_BUFFER_MAX_NUM], EXYNOS_OMX_BASEPORT *pExynosPort); + +OMX_ERRORTYPE Exynos_OSAL_SetPrependSPSPPSToIDR(OMX_PTR pComponentParameterStructure, + OMX_PTR pbPrependSpsPpsToIdr); + +OMX_U32 Exynos_OSAL_GetDisplayExtraBufferCount(void); + +void getColorAspectsPreferBitstream(EXYNOS_OMX_VIDEO_COLORASPECTS *pBSCA, EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA, void *pParam); +void getColorAspectsPreferFramework(EXYNOS_OMX_VIDEO_COLORASPECTS *pBSCA, EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA, void *pParam); + +void Exynos_OSAL_GetColorAspectsForBitstream(EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA, EXYNOS_OMX_VIDEO_COLORASPECTS *pBSCA); +void Exynos_OSAL_ColorSpaceToColorAspects(int colorSpace, EXYNOS_OMX_VIDEO_COLORASPECTS *colorAspects); + +OMX_ERRORTYPE setHDR10PlusInfoForFramework(OMX_COMPONENTTYPE *pOMXComponent, void *pHDRDynamicInfo); +OMX_ERRORTYPE setHDR10PlusInfoForVendorPath(OMX_COMPONENTTYPE *pOMXComponent, void *pExynosHDR10PlusInfo, void *pHDRDynamicInfo); + +OMX_ERRORTYPE Exynos_OSAL_AddVendorExt(OMX_HANDLETYPE hComponent, OMX_STRING cExtName, OMX_INDEXTYPE nIndex); +void Exynos_OSAL_DelVendorExts(OMX_HANDLETYPE hComponent); +OMX_ERRORTYPE Exynos_OSAL_GetVendorExt(OMX_HANDLETYPE hComponent, OMX_PTR pConfig); +OMX_ERRORTYPE Exynos_OSAL_SetVendorExt(OMX_HANDLETYPE hComponent, OMX_PTR pConfig); + +OMX_HANDLETYPE Exynos_OSAL_CreatePerformanceHandle(OMX_BOOL bIsEncoder); +void Exynos_OSAL_Performance(OMX_HANDLETYPE handle, int value, int fps); +void Exynos_OSAL_ReleasePerformanceHandle(OMX_HANDLETYPE handle); +OMX_ERRORTYPE Exynos_OSAL_UpdateDataSpaceFromAspects(EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA); +void Exynos_OSAL_UpdateDataSpaceFromBitstream(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +void Exynos_OSAL_UpdateDataspaceToGraphicMeta(OMX_PTR pBuf, int nDataSpace); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/osal/Exynos_OSAL_ETC.c b/openmax/osal/Exynos_OSAL_ETC.c new file mode 100644 index 0000000..84174e9 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_ETC.c @@ -0,0 +1,1445 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_ETC.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include +#ifdef USE_ANDROID +#include +#else +#include "graphics.h" +#endif + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OMX_Macros.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VIDEO_OSAL" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +#ifdef PERFORMANCE_DEBUG +#include +#include "Exynos_OSAL_Mutex.h" + +#define INPUT_PORT_INDEX 0 +#define OUTPUT_PORT_INDEX 1 +#endif + +#include "ExynosVideoApi.h" +#include "exynos_format.h" +#include "csc.h" + +#define CUSTOM_UHD_MFC_OUTPUT_BUFFER_SIZE (3840 * 2160 * 3 / 2 / 2) +#define CUSTOM_8K_MFC_OUTPUT_BUFFER_SIZE (7680 * 4320 * 3 / 2 / 4) + +static struct timeval perfStart[PERF_ID_MAX+1], perfStop[PERF_ID_MAX+1]; +static unsigned long perfTime[PERF_ID_MAX+1], totalPerfTime[PERF_ID_MAX+1]; +static unsigned int perfFrameCount[PERF_ID_MAX+1], perfOver30ms[PERF_ID_MAX+1]; + +size_t Exynos_OSAL_Strcpy(OMX_PTR dest, OMX_PTR src) +{ +#ifdef USE_ANDROID + size_t len = (size_t)(strlen((const char *)src) + 1); + + return strlcpy(dest, src, len); +#else + return strlen(strncpy(dest, src, strlen((const char *)src))); +#endif +} + +size_t Exynos_OSAL_Strncpy(OMX_PTR dest, OMX_PTR src, size_t num) +{ +#ifdef USE_ANDROID + return strlcpy(dest, src, (size_t)(num + 1)); +#else + return strlen(strncpy(dest, src, num)); +#endif +} + +OMX_S32 Exynos_OSAL_Strcmp(OMX_PTR str1, OMX_PTR str2) +{ + return strcmp(str1, str2); +} + +OMX_S32 Exynos_OSAL_Strncmp(OMX_PTR str1, OMX_PTR str2, size_t num) +{ + return strncmp(str1, str2, num); +} + +const char* Exynos_OSAL_Strstr(const char *str1, const char *str2) +{ + return strstr(str1, str2); +} + +size_t Exynos_OSAL_Strcat(OMX_PTR dest, OMX_PTR src) +{ +#ifdef USE_ANDROID + return strlcat(dest, src, (size_t)(strlen((const char *)dest) + strlen((const char *)src) + 1)); +#else + return strlen(strncat(dest, src, strlen((const char *)src))); +#endif +} + +size_t Exynos_OSAL_Strncat(OMX_PTR dest, OMX_PTR src, size_t num) +{ + size_t len = num; + +#ifdef USE_ANDROID + /* caution : num should be a size of dest buffer */ + return strlcat(dest, src, (size_t)(strlen((const char *)dest) + strlen((const char *)src) + 1)); +#else + return strlen(strncat(dest, src, len)); +#endif +} + +size_t Exynos_OSAL_Strlen(const char *str) +{ + return strlen(str); +} + +static OMX_S32 Exynos_OSAL_MeasureTime(struct timeval *start, struct timeval *stop) +{ + signed long sec, usec, time; + + sec = stop->tv_sec - start->tv_sec; + if (stop->tv_usec >= start->tv_usec) { + usec = (signed long)stop->tv_usec - (signed long)start->tv_usec; + } else { + usec = (signed long)stop->tv_usec + 1000000 - (signed long)start->tv_usec; + sec--; + } + + time = sec * 1000000 + (usec); + + return time; +} + +void Exynos_OSAL_PerfInit(PERF_ID_TYPE id) +{ + Exynos_OSAL_Memset(&perfStart[id], 0, sizeof(perfStart[id])); + Exynos_OSAL_Memset(&perfStop[id], 0, sizeof(perfStop[id])); + perfTime[id] = 0; + totalPerfTime[id] = 0; + perfFrameCount[id] = 0; + perfOver30ms[id] = 0; +} + +void Exynos_OSAL_PerfStart(PERF_ID_TYPE id) +{ + gettimeofday(&perfStart[id], NULL); +} + +void Exynos_OSAL_PerfStop(PERF_ID_TYPE id) +{ + gettimeofday(&perfStop[id], NULL); + + perfTime[id] = Exynos_OSAL_MeasureTime(&perfStart[id], &perfStop[id]); + totalPerfTime[id] += perfTime[id]; + perfFrameCount[id]++; + + if (perfTime[id] > 30000) + perfOver30ms[id]++; +} + +OMX_U32 Exynos_OSAL_PerfFrame(PERF_ID_TYPE id) +{ + return perfTime[id]; +} + +OMX_U32 Exynos_OSAL_PerfTotal(PERF_ID_TYPE id) +{ + return totalPerfTime[id]; +} + +OMX_U32 Exynos_OSAL_PerfFrameCount(PERF_ID_TYPE id) +{ + return perfFrameCount[id]; +} + +int Exynos_OSAL_PerfOver30ms(PERF_ID_TYPE id) +{ + return perfOver30ms[id]; +} + +void Exynos_OSAL_PerfPrint(OMX_STRING prefix, PERF_ID_TYPE id) +{ + OMX_U32 perfTotal; + int frameCount; + + frameCount = Exynos_OSAL_PerfFrameCount(id); + perfTotal = Exynos_OSAL_PerfTotal(id); + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%s][%s] Frame Count: %d", __FUNCTION__, prefix, frameCount); + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%s][%s] Avg Time: %.2f ms, Over 30ms: %d", + prefix, (float)perfTotal / (float)(frameCount * 1000), + Exynos_OSAL_PerfOver30ms(id)); +} + +unsigned int Exynos_OSAL_GetPlaneCount( + OMX_COLOR_FORMATTYPE eOMXFormat, + PLANE_TYPE ePlaneType) +{ + unsigned int nPlaneCnt = 0; + + switch ((int)eOMXFormat) { + case OMX_COLOR_FormatYCbYCr: + case OMX_COLOR_FormatYUV420Planar: + case OMX_SEC_COLOR_FormatYVU420Planar: + nPlaneCnt = 3; + break; + case OMX_COLOR_FormatYUV420SemiPlanar: + case OMX_SEC_COLOR_FormatS10bitYUV420SemiPlanar: + case OMX_COLOR_FormatYUV420Planar16: + case OMX_SEC_COLOR_FormatNV21Linear: + case OMX_SEC_COLOR_FormatS10bitYVU420SemiPlanar: + case OMX_SEC_COLOR_FormatNV12Tiled: + case OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC: + case OMX_SEC_COLOR_FormatYVU420SemiPlanarSBWC: + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC: + case OMX_SEC_COLOR_Format10bitYVU420SemiPlanarSBWC: + case OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC_L50: + case OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC_L75: + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L40: + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L60: + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L80: + nPlaneCnt = 2; + break; + case OMX_COLOR_Format32bitARGB8888: + case OMX_COLOR_Format32bitBGRA8888: + case OMX_COLOR_Format32BitRGBA8888: + nPlaneCnt = 1; + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported color format(0x%x).", __FUNCTION__, eOMXFormat); + nPlaneCnt = 0; + break; + } + + if ((ePlaneType & PLANE_SINGLE) && + (nPlaneCnt > 0)) { + nPlaneCnt = 1; + } + + return nPlaneCnt; +} + +void Exynos_OSAL_GetPlaneSize( + OMX_COLOR_FORMATTYPE eColorFormat, + PLANE_TYPE ePlaneType, + OMX_U32 nWidth, + OMX_U32 nHeight, + unsigned int nDataLen[MAX_BUFFER_PLANE], + unsigned int nAllocLen[MAX_BUFFER_PLANE]) +{ + switch ((int)eColorFormat) { + case OMX_COLOR_FormatYUV420Planar: + case (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420Planar: + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = (nWidth * nHeight) * 3 / 2; + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = (ALIGN(nWidth, 16) * ALIGN(nHeight, 16) + 256) + + (ALIGN((ALIGN(nWidth >> 1, 16) * ALIGN((ALIGN(nHeight, 16) >> 1), CHROMA_VALIGN) + 256), 16) * 2) + + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + } else { + nDataLen[0] = nWidth * nHeight; + nDataLen[1] = nDataLen[0] >> 2; + nDataLen[2] = nDataLen[1]; + + nAllocLen[0] = ALIGN(ALIGN(nWidth, 16) * ALIGN(nHeight, 16), 256) + 256 + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + nAllocLen[1] = ALIGN(ALIGN(nWidth >> 1, 16) * ALIGN((ALIGN(nHeight, 16) >> 1), CHROMA_VALIGN), 256) + 256 + + ((nWidth % 128)? (MSCL_EXT_SIZE / 2):0); /* Scaler Restriction */ + nAllocLen[2] = nAllocLen[1]; + } + break; + case OMX_COLOR_FormatYUV420SemiPlanar: + case (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV21Linear: + case (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled: + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = (nWidth * nHeight) * 3 / 2; + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = (ALIGN(nWidth, 16) * ALIGN(nHeight, 16) + 256) + + (ALIGN((ALIGN(nWidth, 16) * ALIGN((ALIGN(nHeight, 16) >> 1), CHROMA_VALIGN) + 256), 16)) + + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + } else { + nDataLen[0] = nWidth * nHeight; + nDataLen[1] = nDataLen[0] >> 1; + nDataLen[2] = 0; + + nAllocLen[0] = ALIGN(ALIGN(nWidth, 16) * ALIGN(nHeight, 16), 256) + 256 + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + nAllocLen[1] = ALIGN(ALIGN(nWidth, 16) * ALIGN((ALIGN(nHeight, 16) >> 1), CHROMA_VALIGN), 256) + 256 + + ((nWidth % 128)? (MSCL_EXT_SIZE / 2):0); /* Scaler Restriction */ + } + break; + case (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatS10bitYUV420SemiPlanar: + case (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatS10bitYVU420SemiPlanar: + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = (nWidth * nHeight) * 3 / 2; + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = ((ALIGN(nWidth, S10B_FORMAT_8B_ALIGNMENT) * ALIGN(nHeight, 16) + 256) + /* Y 8bit */ + (ALIGN(nWidth / 4, 16) * ALIGN(nHeight, 16) + 64)) + /* Y 2bit */ + ((ALIGN((ALIGN(nWidth, S10B_FORMAT_8B_ALIGNMENT) * ALIGN((ALIGN(nHeight, 16) >> 1), CHROMA_VALIGN) + 256), 16)) + /* CbCr 8bit */ + (ALIGN(nWidth / 4, 16) * ALIGN((ALIGN(nHeight, 16) >> 1), CHROMA_VALIGN) + 64)) + /* CbCr 2bit */ + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + } else { + nDataLen[0] = nWidth * nHeight; + nDataLen[1] = nWidth * (nHeight / 2); + nDataLen[2] = 0; + + nAllocLen[0] = ALIGN((ALIGN(nWidth, S10B_FORMAT_8B_ALIGNMENT) * ALIGN(nHeight, 16) + 256) + /* Y 8bit */ + (ALIGN(nWidth / 4, 16) * ALIGN(nHeight, 16) + 256), 256) + /* Y 2bit */ + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + nAllocLen[1] = ALIGN((ALIGN(nWidth, S10B_FORMAT_8B_ALIGNMENT) * ALIGN((ALIGN(nHeight, 16) >> 1), CHROMA_VALIGN) + 256) + /* CbCr 8bit */ + (ALIGN(nWidth / 4, 16) * ALIGN((ALIGN(nHeight, 16) >> 1), CHROMA_VALIGN) + 256), 256) + /* CbCr 2bit */ + ((nWidth % 128)? (MSCL_EXT_SIZE / 2):0); /* Scaler Restriction */ + } + break; + case OMX_COLOR_FormatYUV420Planar16: + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = ((nWidth * 2) * nHeight) * 3 / 2; + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = ((ALIGN(nWidth, 16) * 2) * ALIGN(nHeight, 16) + 256) + /* Y 10bit */ + (ALIGN(((ALIGN(nWidth, 16) * 2) * ALIGN((ALIGN(nHeight, 16) >> 1), CHROMA_VALIGN) + 256), 16)) + /* CbCr 10bit */ + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + } else { + nDataLen[0] = (nWidth * 2) * nHeight; + nDataLen[1] = nDataLen[0] >> 1; + nDataLen[2] = 0; + + nAllocLen[0] = ALIGN((ALIGN(nWidth, 16) * 2) * ALIGN(nHeight, 16), 256) + 256 + + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + nAllocLen[1] = ALIGN((ALIGN(nWidth, 16) * 2) * ALIGN((ALIGN(nHeight, 16) >> 1), CHROMA_VALIGN), 256) + 256 + + ((nWidth % 128)? (MSCL_EXT_SIZE / 2):0); /* Scaler Restriction */ + } + break; + case OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC: + case OMX_SEC_COLOR_FormatYVU420SemiPlanarSBWC: + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = 0; /* NOT SUPPROT */ + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = 0; + } else { + nAllocLen[0] = (SBWC_8B_Y_SIZE(nWidth, nHeight) + /* SBWC Y */ + SBWC_8B_Y_HEADER_SIZE(nWidth, nHeight)) + /* SBWC Y HEADER */ + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + nAllocLen[1] = (SBWC_8B_CBCR_SIZE(nWidth, nHeight) + /* SBWC CBCR */ + SBWC_8B_CBCR_HEADER_SIZE(nWidth, nHeight)) +/* SBWC CBCR HEADER */ + ((nWidth % 128)? (MSCL_EXT_SIZE / 2):0); /* Scaler Restriction */ + + nDataLen[0] = nAllocLen[0]; + nDataLen[1] = nAllocLen[1]; + nDataLen[2] = 0; + } + break; + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC: + case OMX_SEC_COLOR_Format10bitYVU420SemiPlanarSBWC: + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = 0; /* NOT SUPPORT */ + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = 0; + } else { + nAllocLen[0] = (SBWC_10B_Y_SIZE(nWidth, nHeight) + /* SBWC Y */ + SBWC_10B_Y_HEADER_SIZE(nWidth, nHeight)) + /* SBWC Y HEADER */ + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + nAllocLen[1] = (SBWC_10B_CBCR_SIZE(nWidth, nHeight) + /* SBWC CBCR */ + SBWC_10B_CBCR_HEADER_SIZE(nWidth, nHeight)) +/* SBWC CBCR HEADER */ + ((nWidth % 128)? (MSCL_EXT_SIZE / 2):0); /* Scaler Restriction */ + + nDataLen[0] = nAllocLen[0]; + nDataLen[1] = nAllocLen[1]; + nDataLen[2] = 0; + } + break; + case OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC_L50: + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = 0; /* NOT SUPPROT */ + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = 0; + } else { + nAllocLen[0] = SBWCL_8B_Y_SIZE(nWidth, nHeight, 50) + /* SBWC_L50 Y */ + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + nAllocLen[1] = SBWCL_8B_CBCR_SIZE(nWidth, nHeight, 50) +/* SBWC_L50 CBCR */ + ((nWidth % 128)? (MSCL_EXT_SIZE / 2):0); /* Scaler Restriction */ + + nDataLen[0] = nAllocLen[0]; + nDataLen[1] = nAllocLen[1]; + nDataLen[2] = 0; + } + break; + case OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC_L75: + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = 0; /* NOT SUPPROT */ + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = 0; + } else { + nAllocLen[0] = SBWCL_8B_Y_SIZE(nWidth, nHeight, 75) + /* SBWC_L75 Y */ + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + nAllocLen[1] = SBWCL_8B_CBCR_SIZE(nWidth, nHeight, 75) +/* SBWC_L75 CBCR */ + ((nWidth % 128)? (MSCL_EXT_SIZE / 2):0); /* Scaler Restriction */ + + nDataLen[0] = nAllocLen[0]; + nDataLen[1] = nAllocLen[1]; + nDataLen[2] = 0; + } + break; + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L40: + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = 0; /* NOT SUPPROT */ + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = 0; + } else { + nAllocLen[0] = SBWCL_10B_Y_SIZE(nWidth, nHeight, 40) + /* SBWC_L40 Y */ + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + nAllocLen[1] = SBWCL_10B_CBCR_SIZE(nWidth, nHeight, 40) +/* SBWC_L40 CBCR */ + ((nWidth % 128)? (MSCL_EXT_SIZE / 2):0); /* Scaler Restriction */ + + nDataLen[0] = nAllocLen[0]; + nDataLen[1] = nAllocLen[1]; + nDataLen[2] = 0; + } + + break; + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L60: + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = 0; /* NOT SUPPROT */ + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = 0; + } else { + nAllocLen[0] = SBWCL_10B_Y_SIZE(nWidth, nHeight, 60) + /* SBWC_L60 Y */ + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + nAllocLen[1] = SBWCL_10B_CBCR_SIZE(nWidth, nHeight, 60) +/* SBWC_L60 CBCR */ + ((nWidth % 128)? (MSCL_EXT_SIZE / 2):0); /* Scaler Restriction */ + + nDataLen[0] = nAllocLen[0]; + nDataLen[1] = nAllocLen[1]; + nDataLen[2] = 0; + } + break; + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L80: + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = 0; /* NOT SUPPROT */ + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = 0; + } else { + nAllocLen[0] = SBWCL_10B_Y_SIZE(nWidth, nHeight, 80) + /* SBWC_L80 Y */ + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + nAllocLen[1] = SBWCL_10B_CBCR_SIZE(nWidth, nHeight, 80) +/* SBWC_L80 CBCR */ + ((nWidth % 128)? (MSCL_EXT_SIZE / 2):0); /* Scaler Restriction */ + + nDataLen[0] = nAllocLen[0]; + nDataLen[1] = nAllocLen[1]; + nDataLen[2] = 0; + } + break; + case OMX_COLOR_Format32bitARGB8888: + case OMX_COLOR_Format32bitBGRA8888: + case OMX_COLOR_Format32BitRGBA8888: + nDataLen[0] = nWidth * nHeight * 4; + nDataLen[1] = 0; + nDataLen[2] = 0; + + nAllocLen[0] = ALIGN(ALIGN(nWidth, 16) * ALIGN(nHeight, 16) * 4, 256) + 256 + + ((nWidth % 128)? MSCL_EXT_SIZE:0); /* Scaler Restriction */ + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported color format(0x%x).", __FUNCTION__, eColorFormat); + break; + } +} + +OMX_U32 Exynos_OSAL_GetOutBufferSize(OMX_U32 nWidth, OMX_U32 nHeight, OMX_U32 nDefaultBufferSize) { + OMX_U32 nBufferSize = 0; + + FunctionIn(); + + nBufferSize = nDefaultBufferSize; + + if (((nWidth * nHeight) > 0) && ((nWidth * nHeight) < (3840 * 2160))) { + if (nBufferSize > CUSTOM_UHD_MFC_OUTPUT_BUFFER_SIZE) + nBufferSize = CUSTOM_UHD_MFC_OUTPUT_BUFFER_SIZE; + else + nBufferSize = (ALIGN(nWidth, 16) * ALIGN(nHeight, 16) * 3) / 2; + } else if (((nWidth * nHeight) >= (3840 * 2160)) && ((nWidth * nHeight) < (7680 * 4320))) { + if (nBufferSize > CUSTOM_8K_MFC_OUTPUT_BUFFER_SIZE) + nBufferSize = CUSTOM_8K_MFC_OUTPUT_BUFFER_SIZE; + else + nBufferSize = (ALIGN(nWidth, 16) * ALIGN(nHeight, 16) * 3) / 2 / 2; + } else if (((nWidth * nHeight) >= (7680 * 4320))) { + nBufferSize = (ALIGN(nWidth, 16) * ALIGN(nHeight, 16) * 3) / 2 / 4; + } + +EXIT: + FunctionOut(); + + return nBufferSize; +} + +static struct { + ExynosVideoColorFormatType eVideoFormat[2]; /* multi-FD, single-FD(H/W) */ + OMX_COLOR_FORMATTYPE eOMXFormat; +} VIDEO_COLORFORMAT_MAP[] = { +{{VIDEO_COLORFORMAT_NV12M, VIDEO_COLORFORMAT_NV12}, OMX_COLOR_FormatYUV420SemiPlanar}, +{{VIDEO_COLORFORMAT_NV12M_S10B, VIDEO_COLORFORMAT_NV12_S10B}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatS10bitYUV420SemiPlanar}, +{{VIDEO_COLORFORMAT_NV12M_P010, 0 /* not supported */ }, (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatYUV420Planar16}, +{{VIDEO_COLORFORMAT_NV12M_TILED, VIDEO_COLORFORMAT_NV12_TILED}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled}, +{{VIDEO_COLORFORMAT_NV21M, 0 /* not supported */}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV21Linear}, +{{VIDEO_COLORFORMAT_NV21M_S10B, 0 /* not supported */}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatS10bitYVU420SemiPlanar}, +{{VIDEO_COLORFORMAT_I420M, VIDEO_COLORFORMAT_I420}, OMX_COLOR_FormatYUV420Planar}, +{{VIDEO_COLORFORMAT_YV12M, 0 /* not supported */}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420Planar}, +{{VIDEO_COLORFORMAT_ARGB8888, VIDEO_COLORFORMAT_ARGB8888}, OMX_COLOR_Format32bitBGRA8888}, +{{VIDEO_COLORFORMAT_BGRA8888, VIDEO_COLORFORMAT_BGRA8888}, OMX_COLOR_Format32bitARGB8888}, +{{VIDEO_COLORFORMAT_RGBA8888, VIDEO_COLORFORMAT_RGBA8888}, (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888}, +{{VIDEO_COLORFORMAT_NV12M_SBWC, VIDEO_COLORFORMAT_NV12_SBWC}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC}, +{{VIDEO_COLORFORMAT_NV12M_10B_SBWC, VIDEO_COLORFORMAT_NV12_10B_SBWC}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC}, +{{VIDEO_COLORFORMAT_NV21M_SBWC, 0 /* not supported */}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420SemiPlanarSBWC}, +{{VIDEO_COLORFORMAT_NV21M_10B_SBWC, 0 /* not supported */}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYVU420SemiPlanarSBWC}, +{{VIDEO_COLORFORMAT_NV12M_SBWC_L50, VIDEO_COLORFORMAT_NV12_SBWC_L50}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC_L50}, +{{VIDEO_COLORFORMAT_NV12M_SBWC_L75, VIDEO_COLORFORMAT_NV12_SBWC_L75}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC_L75}, +{{VIDEO_COLORFORMAT_NV12M_10B_SBWC_L40, VIDEO_COLORFORMAT_NV12_10B_SBWC_L40}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L40}, +{{VIDEO_COLORFORMAT_NV12M_10B_SBWC_L60, VIDEO_COLORFORMAT_NV12_10B_SBWC_L60}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L60}, +{{VIDEO_COLORFORMAT_NV12M_10B_SBWC_L80, VIDEO_COLORFORMAT_NV12_10B_SBWC_L80}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L80}, +}; + +int Exynos_OSAL_OMX2VideoFormat( + OMX_COLOR_FORMATTYPE eColorFormat, + PLANE_TYPE ePlaneType) +{ + ExynosVideoColorFormatType nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int nVideoFormats = (int)(sizeof(VIDEO_COLORFORMAT_MAP)/sizeof(VIDEO_COLORFORMAT_MAP[0])); + int i; + + for (i = 0; i < nVideoFormats; i++) { + if (VIDEO_COLORFORMAT_MAP[i].eOMXFormat == eColorFormat) { + nVideoFormat = VIDEO_COLORFORMAT_MAP[i].eVideoFormat[(ePlaneType & 0x10)? 1:0]; + break; + } + } + + if (nVideoFormat == VIDEO_COLORFORMAT_UNKNOWN) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%s] color format(0x%x)/plane type(0x%x) is not supported", + __FUNCTION__, eColorFormat, ePlaneType); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] color format(0x%x)/plane type(0x%x) -> video format(0x%x)", + __FUNCTION__, eColorFormat, ePlaneType, nVideoFormat); + +EXIT: + + return (int)nVideoFormat; +} + +OMX_COLOR_FORMATTYPE Exynos_OSAL_Video2OMXFormat( + int nVideoFormat) +{ + OMX_COLOR_FORMATTYPE eOMXFormat = OMX_COLOR_FormatUnused; + int nVideoFormats = (int)(sizeof(VIDEO_COLORFORMAT_MAP)/sizeof(VIDEO_COLORFORMAT_MAP[0])); + int i; + + for (i = 0; i < nVideoFormats; i++) { + if (((int)VIDEO_COLORFORMAT_MAP[i].eVideoFormat[0] == nVideoFormat) || + ((int)VIDEO_COLORFORMAT_MAP[i].eVideoFormat[1] == nVideoFormat)) { + eOMXFormat = VIDEO_COLORFORMAT_MAP[i].eOMXFormat; + break; + } + } + + if (eOMXFormat == OMX_COLOR_FormatUnused) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] video format(0x%x) is not supported", __FUNCTION__, nVideoFormat); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] video format(0x%x) -> color format(0x%x)", __FUNCTION__, nVideoFormat, eOMXFormat); + +EXIT: + + + return eOMXFormat; +} + +static struct { + unsigned int nHALFormat[PLANE_MAX_NUM]; /* multi-FD, single-FD(H/W), sigle-FD(general) */ + OMX_COLOR_FORMATTYPE eOMXFormat; +} HAL_COLORFORMAT_MAP[] = { +/* NV12 format */ +#ifdef USE_PRIV_FORMAT +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP}, + OMX_COLOR_FormatYUV420SemiPlanar}, +#endif +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP}, + OMX_COLOR_FormatYUV420SemiPlanar}, + +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatS10bitYUV420SemiPlanar}, + +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M, 0 /* not implemented */, HAL_PIXEL_FORMAT_YCBCR_P010}, + (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatYUV420Planar16}, + +/* NV12T format */ +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_TILED, 0 /* not implemented */}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled}, + +/* NV21 format */ +{{HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M, 0 /* not implemented */, HAL_PIXEL_FORMAT_YCrCb_420_SP}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV21Linear}, + +{{0 /* not implemented */, 0 /* not implemented */, 0 /* not implemented */}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatS10bitYVU420SemiPlanar}, + +/* I420P format */ +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_PN, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P}, + OMX_COLOR_FormatYUV420Planar}, + +/* YV12 format */ +{{HAL_PIXEL_FORMAT_EXYNOS_YV12_M, 0 /* not implemented */, HAL_PIXEL_FORMAT_YV12}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420Planar}, + +/* RGB format */ +{{HAL_PIXEL_FORMAT_RGBA_8888, HAL_PIXEL_FORMAT_RGBA_8888, HAL_PIXEL_FORMAT_RGBA_8888}, + (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888}, + +{{HAL_PIXEL_FORMAT_EXYNOS_ARGB_8888, HAL_PIXEL_FORMAT_EXYNOS_ARGB_8888, HAL_PIXEL_FORMAT_EXYNOS_ARGB_8888}, + OMX_COLOR_Format32bitBGRA8888}, + +{{HAL_PIXEL_FORMAT_BGRA_8888, HAL_PIXEL_FORMAT_BGRA_8888, HAL_PIXEL_FORMAT_BGRA_8888}, + OMX_COLOR_Format32bitARGB8888}, + +/* SBWC format */ +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC, 0 /* not implemented */}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC}, + +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC, 0 /* not implemented */}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC}, + +{{HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC, 0 /* not implemented */, 0 /* not implemented */}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYVU420SemiPlanarSBWC}, + +{{HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC, 0 /* not implemented */, 0 /* not implemented */}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYVU420SemiPlanarSBWC}, + +/* SBWC Lossy format */ +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50, 0 /* not implemented */}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC_L50}, + +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75, 0 /* not implemented */}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarSBWC_L75}, + +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40, 0 /* not implemented */}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L40}, + +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60, 0 /* not implemented */}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L60}, + +{{HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80, 0 /* not implemented */}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYUV420SemiPlanarSBWC_L80}, +}; + +OMX_COLOR_FORMATTYPE Exynos_OSAL_HAL2OMXColorFormat( + unsigned int nHALFormat) +{ + OMX_COLOR_FORMATTYPE eOMXFormat = OMX_COLOR_FormatUnused; + int nHALFormats = (int)(sizeof(HAL_COLORFORMAT_MAP)/sizeof(HAL_COLORFORMAT_MAP[0])); + int i; + + for (i = 0; i < nHALFormats; i++) { + if ((HAL_COLORFORMAT_MAP[i].nHALFormat[0] == nHALFormat) || + (HAL_COLORFORMAT_MAP[i].nHALFormat[1] == nHALFormat) +#if 0 + || (HAL_COLORFORMAT_MAP[i].nHALFormat[2] == nHALFormat) /* userspace format : not used in vendor scenario */ +#endif + ) { + eOMXFormat = HAL_COLORFORMAT_MAP[i].eOMXFormat; + break; + } + } + + if (eOMXFormat == OMX_COLOR_FormatUnused) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] HAL format(0x%x) is not supported", __FUNCTION__, nHALFormat); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] HAL format(0x%x) -> color format(0x%x)", __FUNCTION__, nHALFormat, eOMXFormat); + +EXIT: + + return eOMXFormat; +} + +unsigned int Exynos_OSAL_OMX2HALPixelFormat( + OMX_COLOR_FORMATTYPE eOMXFormat, + PLANE_TYPE ePlaneType) +{ + unsigned int nHALFormat = 0; + int nHALFormats = (int)(sizeof(HAL_COLORFORMAT_MAP)/sizeof(HAL_COLORFORMAT_MAP[0])); + int i; + + for (i = 0; i < nHALFormats; i++) { + if (HAL_COLORFORMAT_MAP[i].eOMXFormat == eOMXFormat) { + nHALFormat = HAL_COLORFORMAT_MAP[i].nHALFormat[ePlaneType & 0xF]; + break; + } + } + + if (nHALFormat == 0) + goto EXIT; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] color format(0x%x)/plane type(0x%x) -> HAL format(0x%x)", + __FUNCTION__, eOMXFormat, ePlaneType, nHALFormat); + +EXIT: + + return nHALFormat; +} + +int Exynos_OSAL_DataSpaceToColorSpace(int nDataSpace, int nFormat) +{ + int nColorSpace = CSC_EQ_COLORSPACE_SMPTE170M; + OMX_BOOL isRGB = OMX_FALSE; + + if ((nFormat == HAL_PIXEL_FORMAT_EXYNOS_ARGB_8888) || + (nFormat == HAL_PIXEL_FORMAT_RGBA_8888) || + (nFormat == HAL_PIXEL_FORMAT_BGRA_8888)) { + /* it depends on + * libstagefright/colorconversion/ColorConverter.cpp + * only BT.601 is supported. + */ + + isRGB = OMX_TRUE; + } + +#ifdef USE_ANDROID + switch (nDataSpace) { + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_HLG | HAL_DATASPACE_STANDARD_BT2020): + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT2020): + case (HAL_DATASPACE_RANGE_LIMITED | HAL_DATASPACE_TRANSFER_ST2084 | HAL_DATASPACE_STANDARD_BT2020): + case HAL_DATASPACE_BT2020: + case HAL_DATASPACE_BT2020_PQ: + nColorSpace = CSC_EQ_COLORSPACE_BT2020; +#ifndef USE_BT2020_SUPPORT + if (isRGB) { + nColorSpace = CSC_EQ_COLORSPACE_REC709; /* GPU(BT.709) : default about BT.2020 */ +#ifndef USE_BT709_SUPPORT + nColorSpace = CSC_EQ_COLORSPACE_SMPTE170M; /* GPU(BT.601 only) : default */ +#endif + } +#endif + break; + case (HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT709): + case HAL_DATASPACE_BT709: + case HAL_DATASPACE_V0_BT709: + nColorSpace = CSC_EQ_COLORSPACE_REC709; /* BT.709 */ +#ifndef USE_BT709_SUPPORT + if (isRGB) { + nColorSpace = CSC_EQ_COLORSPACE_SMPTE170M; /* GPU(BT.601 only) : default */ + } +#endif + break; + case (HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_625): + case HAL_DATASPACE_BT601_625: + case HAL_DATASPACE_V0_BT601_625: + case (HAL_DATASPACE_RANGE_FULL | HAL_DATASPACE_TRANSFER_SMPTE_170M | HAL_DATASPACE_STANDARD_BT601_525): + case HAL_DATASPACE_BT601_525: + case HAL_DATASPACE_V0_BT601_525: + default: + nColorSpace = CSC_EQ_COLORSPACE_SMPTE170M; /* BT.601 */ + break; + }; +#endif + + return nColorSpace; +} + +void Exynos_OSAL_GetRGBColorTypeForBitStream( + EXYNOS_OMX_VIDEO_COLORASPECTS *pColorAspects, + int nDataSpace, + int nFormat) +{ + int colorspace = CSC_EQ_COLORSPACE_SMPTE170M; + + /* for enabling VUI encoding, set range value if it is not set */ + if (pColorAspects->nRangeType == RANGE_UNSPECIFIED) { + pColorAspects->nRangeType = RANGE_LIMITED; /* preferred value */ + } + + /* decides transfer vlaue depended on other modules */ + colorspace = Exynos_OSAL_DataSpaceToColorSpace(nDataSpace, nFormat); + + switch(colorspace) { + case CSC_EQ_COLORSPACE_SMPTE170M: /* uses BT.601 forcefully */ + pColorAspects->nPrimaryType = PRIMARIES_BT601_6_625; + pColorAspects->nCoeffType = MATRIX_COEFF_SMPTE170M; + pColorAspects->nTransferType = TRANSFER_SMPTE_170M; + break; + case CSC_EQ_COLORSPACE_REC709: /* uses BT.709 furcefully */ + default: /* best effort. uses BT.709 */ + pColorAspects->nPrimaryType = PRIMARIES_BT709_5; + pColorAspects->nCoeffType = MATRIX_COEFF_REC709; + pColorAspects->nTransferType = TRANSFER_BT709; + break; + }; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%s] colorspace: %d", __FUNCTION__, colorspace); + + return ; +} + + +#ifdef PERFORMANCE_DEBUG + +typedef enum _DEBUG_LEVEL +{ + PERF_LOG_OFF, + PERF_LOG_ON, +} EXYNOS_DEBUG_LEVEL; + +static int gPerfLevel = PERF_LOG_OFF; + +void Exynos_OSAL_Get_Perf_Property() +{ + char perfProp[PROPERTY_VALUE_MAX] = { 0, }; + + if (property_get("debug.omx.perf", perfProp, NULL) > 0) { + if(!(Exynos_OSAL_Strncmp(perfProp, "1", 1))) + gPerfLevel = PERF_LOG_ON; + else + gPerfLevel = PERF_LOG_OFF; + } +} + +typedef struct _BUFFER_INFO +{ + OMX_BUFFERHEADERTYPE *pBufferHeader; + OMX_TICKS timestamp; /* given from framework */ + struct timeval currentTime; /* system time */ + OMX_TICKS previousTimeStamp; + struct timeval previousTime; + OMX_S32 nCountInOMX; + + + struct timeval queueTime; /* system time : VL42 qbuf */ + struct timeval dequeueTime; /* system time : V4L2 dqbuf */ + OMX_S32 nCountInV4L2; +} BUFFER_INFO; + +typedef struct _EXYNOS_OMX_PERF_INFO +{ + OMX_HANDLETYPE mutex; + + OMX_S32 nCountInOMX; + OMX_S32 nCountInV4L2; + + OMX_S32 nCurSlotIndex; + OMX_S32 nNextSlotIndex; + BUFFER_INFO sBufferTime[MAX_TIMESTAMP]; + + OMX_TICKS latestOutTimestamp; +} EXYNOS_OMX_PERF_INFO; + +OMX_ERRORTYPE Exynos_OSAL_CountCreate(OMX_HANDLETYPE *hPerfInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_PERF_INFO *pPerfInfo = NULL; + + if (hPerfInfo == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + /* it only works when perperty is enabled */ + if (gPerfLevel == PERF_LOG_OFF) { + (*hPerfInfo) = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + pPerfInfo = (EXYNOS_OMX_PERF_INFO *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_PERF_INFO)); + if (pPerfInfo == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to malloc", __FUNCTION__); + (*hPerfInfo) = NULL; + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Memset((OMX_PTR)pPerfInfo, 0, sizeof(EXYNOS_OMX_PERF_INFO)); + + ret = Exynos_OSAL_MutexCreate(&(pPerfInfo->mutex)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to MutexCreate", __FUNCTION__); + Exynos_OSAL_Free(pPerfInfo); + (*hPerfInfo) = NULL; + goto EXIT; + } + + (*hPerfInfo) = pPerfInfo; + +EXIT: + + return ret; +} + +void Exynos_OSAL_CountTerminate(OMX_HANDLETYPE *hPerfInfo) +{ + EXYNOS_OMX_PERF_INFO *pPerfInfo = (EXYNOS_OMX_PERF_INFO *)(*hPerfInfo); + + if (pPerfInfo == NULL) + return; + + Exynos_OSAL_MutexTerminate(pPerfInfo->mutex); + Exynos_OSAL_Free(pPerfInfo); + (*pPerfInfo) = NULL; + + return; +} + +OMX_S32 Exynos_OSAL_CountIncrease( + OMX_HANDLETYPE *hPerfInfo, + OMX_BUFFERHEADERTYPE *pBufferHeader, + int nPortIndex) +{ + OMX_S32 nCountInOMX = 0; + EXYNOS_OMX_PERF_INFO *pPerfInfo = (EXYNOS_OMX_PERF_INFO *)hPerfInfo; + + struct timeval currentTime; + struct tm *ptm = NULL; + char time_string[40] = { 0, }; + + int nSlotIndex = 0; + int i; + + if (pPerfInfo == NULL) + return 0; + + if (pBufferHeader == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] bufferHeader is NULL", __FUNCTION__); + return pPerfInfo->nCountInOMX; + } + + Exynos_OSAL_MutexLock(pPerfInfo->mutex); + + pPerfInfo->nCountInOMX++; /* queued to OMX's port */ + nCountInOMX = pPerfInfo->nCountInOMX; + + nSlotIndex = pPerfInfo->nNextSlotIndex; + + /* if could not find an empty slot at the past */ + if (nSlotIndex < 0) { + /* re-try to find an empty slot */ + nSlotIndex = (pPerfInfo->nCurSlotIndex + 1) % MAX_TIMESTAMP; + for (i = 0; i < MAX_TIMESTAMP; i++) { + if (pPerfInfo->sBufferTime[nSlotIndex].pBufferHeader == NULL) + break; + + nSlotIndex = (nSlotIndex + 1) % MAX_TIMESTAMP; + } + + if (i >= MAX_TIMESTAMP) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] Can not find a empty slot", __FUNCTION__); + } else { + pPerfInfo->sBufferTime[nSlotIndex].previousTimeStamp = pPerfInfo->sBufferTime[pPerfInfo->nCurSlotIndex].timestamp; + Exynos_OSAL_Memcpy(&pPerfInfo->sBufferTime[nSlotIndex].previousTime, + &pPerfInfo->sBufferTime[pPerfInfo->nCurSlotIndex].timestamp, sizeof(struct timeval)); + pPerfInfo->nNextSlotIndex = nSlotIndex; + } + } + + /* save buffer header and timestamp */ + pPerfInfo->sBufferTime[nSlotIndex].pBufferHeader = pBufferHeader; + pPerfInfo->sBufferTime[nSlotIndex].timestamp = pBufferHeader->nTimeStamp; + + /* get currnet system time and save this for performance measurement */ + gettimeofday(&(currentTime), NULL); + Exynos_OSAL_Memcpy(&pPerfInfo->sBufferTime[nSlotIndex].currentTime, ¤tTime, sizeof(currentTime)); + pPerfInfo->sBufferTime[nSlotIndex].nCountInOMX = pPerfInfo->nCountInOMX; + pPerfInfo->nCurSlotIndex = nSlotIndex; + + /* find an empty slot for next */ + nSlotIndex = (pPerfInfo->nCurSlotIndex + 1) % MAX_TIMESTAMP; + for (i = 0; i < MAX_TIMESTAMP; i++) { + if (pPerfInfo->sBufferTime[nSlotIndex].pBufferHeader == NULL) + break; + + nSlotIndex = (nSlotIndex + 1) % MAX_TIMESTAMP; + } + + if (i >= MAX_TIMESTAMP) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] Can not find a empty slot", __FUNCTION__); + } else { + /* save cur info to next slot that will have future info */ + pPerfInfo->sBufferTime[nSlotIndex].previousTimeStamp = pPerfInfo->sBufferTime[pPerfInfo->nCurSlotIndex].timestamp; + Exynos_OSAL_Memcpy(&pPerfInfo->sBufferTime[nSlotIndex].previousTime, + &pPerfInfo->sBufferTime[pPerfInfo->nCurSlotIndex].timestamp, sizeof(struct timeval)); + pPerfInfo->nNextSlotIndex = nSlotIndex; + } + + ptm = localtime(¤tTime.tv_sec); + strftime(time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] %s time = %s.%03ld, header:0x%x, OMX Count:%d", __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "ETB":"FTB", + time_string, (currentTime.tv_usec / 1000), pBufferHeader, nCountInOMX); + + Exynos_OSAL_MutexUnlock(pPerfInfo->mutex); + + return nCountInOMX; +} + +OMX_S32 Exynos_OSAL_CountDecrease( + OMX_HANDLETYPE *hPerfInfo, + OMX_BUFFERHEADERTYPE *pBufferHeader, + int nPortIndex) +{ + OMX_S32 nCountInOMX = 0; + EXYNOS_OMX_PERF_INFO *pPerfInfo = (EXYNOS_OMX_PERF_INFO *)hPerfInfo; + + struct timeval currentTime; + struct tm *ptm = NULL; + char time_string[40] = { 0, }; + + int nSlotIndex = 0; + int i; + + if (pPerfInfo == NULL) + return 0; + + if (pBufferHeader == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] bufferHeader is NULL", __FUNCTION__); + return pPerfInfo->nCountInOMX; + } + + Exynos_OSAL_MutexLock(pPerfInfo->mutex); + + /* find a buffer */ + for (i = 0; i < MAX_TIMESTAMP; i++) { + if (pPerfInfo->sBufferTime[i].pBufferHeader == pBufferHeader) { + /* clear info */ + pPerfInfo->sBufferTime[i].pBufferHeader = NULL; + + if (nPortIndex == OUTPUT_PORT_INDEX) + pPerfInfo->latestOutTimestamp = pPerfInfo->sBufferTime[i].timestamp; + + nSlotIndex = i; + break; + } + } + + if (i >= MAX_TIMESTAMP) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] Can not find %p in slot", __FUNCTION__, pBufferHeader); + Exynos_OSAL_MutexUnlock(pPerfInfo->mutex); + return pPerfInfo->nCountInOMX; + } + + pPerfInfo->nCountInOMX--; /* dequeued to OMX's port */ + nCountInOMX = pPerfInfo->nCountInOMX; + + gettimeofday(&(currentTime), NULL); + ptm = localtime(¤tTime.tv_sec); + strftime(time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] %s time = %s.%03ld, header:0x%x, OMX Count:%d", __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "EBD":"FBD", + time_string, (currentTime.tv_usec / 1000), pBufferHeader, nCountInOMX); + + Exynos_OSAL_MutexUnlock(pPerfInfo->mutex); + + return nCountInOMX; +} + +OMX_S32 Exynos_OSAL_V4L2CountIncrease( + OMX_HANDLETYPE *hPerfInfo, + OMX_BUFFERHEADERTYPE *pBufferHeader, + int nPortIndex) +{ + OMX_S32 nCountInV4L2 = 0; + EXYNOS_OMX_PERF_INFO *pPerfInfo = (EXYNOS_OMX_PERF_INFO *)hPerfInfo; + + struct timeval currentTime; + struct tm *ptm = NULL; + char time_string[40] = { 0, }; + + int nSlotIndex = 0; + int i; + + if (pPerfInfo == NULL) + return 0; + + if (pBufferHeader == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] bufferHeader is NULL", __FUNCTION__); + return pPerfInfo->nCountInV4L2; + } + + Exynos_OSAL_MutexLock(pPerfInfo->mutex); + + for (i = 0; i < MAX_TIMESTAMP; i++) { + if (pPerfInfo->sBufferTime[i].pBufferHeader == pBufferHeader) { + nSlotIndex = i; + break; + } + } + + if (i >= MAX_TIMESTAMP) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] Can not find %p in slot", __FUNCTION__, pBufferHeader); + Exynos_OSAL_MutexUnlock(pPerfInfo->mutex); + return pPerfInfo->nCountInOMX; + } + + pPerfInfo->nCountInV4L2++; /* queued to MFC */ + + gettimeofday(&(currentTime), NULL); + Exynos_OSAL_Memcpy(&pPerfInfo->sBufferTime[nSlotIndex].queueTime, ¤tTime, sizeof(currentTime)); + pPerfInfo->sBufferTime[nSlotIndex].nCountInV4L2 = pPerfInfo->nCountInV4L2; + nCountInV4L2 = pPerfInfo->V4L2QCount; + + + ptm = localtime(&pPerfInfo->sBufferTime[nSlotIndex].queueTime.tv_sec); + strftime(time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] V4L2 %s time = %s.%03ld, header:0x%x, V4L2 Count:%d", __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "SRC Q":"DST Q", + time_string, (currentTime.tv_usec / 1000), pBufferHeader, nCountInV4L2); + + Exynos_OSAL_MutexUnlock(pPerfInfo->mutex); + + return nCountInV4L2; +} + +OMX_S32 Exynos_OSAL_V4L2CountDecrease( + OMX_HANDLETYPE *hPerfInfo, + OMX_BUFFERHEADERTYPE *pBufferHeader, + int nPortIndex) +{ + OMX_S32 nCountInV4L2 = 0; + EXYNOS_OMX_PERF_INFO *pPerfInfo = (EXYNOS_OMX_PERF_INFO *)hPerfInfo; + + struct timeval currentTime; + struct tm *ptm = NULL; + char time_string[40] = { 0, }; + + int nSlotIndex = 0; + int i; + + if (pPerfInfo == NULL) + return 0; + + if (pBufferHeader == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] bufferHeader is NULL", __FUNCTION__); + return pPerfInfo->nCountInV4L2; + } + + Exynos_OSAL_MutexLock(pPerfInfo->mutex); + + for (i = 0; i < MAX_TIMESTAMP; i++) { + if (pPerfInfo->sBufferTime[i].pBufferHeader == pBufferHeader) { + nSlotIndex = i; + break; + } + } + + if (i >= MAX_TIMESTAMP) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] Can not find %p in slot", __FUNCTION__, pBufferHeader); + Exynos_OSAL_MutexUnlock(pPerfInfo->mutex); + return pPerfInfo->nCountInOMX; + } + + pPerfInfo->nCountInV4L2--; /* dequeued to MFC */ + + gettimeofday(&(currentTime), NULL); + Exynos_OSAL_Memcpy(&pPerfInfo->sBufferTime[nSlotIndex].queueTime, ¤tTime, sizeof(currentTime)); + pPerfInfo->sBufferTime[nSlotIndex].nCountInV4L2 = pPerfInfo->nCountInV4L2; + nCountInV4L2 = pPerfInfo->V4L2QCount; + + if (nPortIndex == OUTPUT_PORT_INDEX) { + pPerfInfo->sBufferTime[nSlotIndex].timestamp = pBufferHeader->nTimeStamp; + pPerfInfo->sBufferTime[nSlotIndex].previousTimeStamp = pPerfInfo->latestOutTimestamp; + } + + ptm = localtime(&pPerfInfo->sBufferTime[index].dequeueTime.tv_sec); + strftime(time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] V4L2 %s time = %s.%03ld, header:0x%x, V4L2 Count:%d", __FUNCTION__, + (nPortIndex == INPUT_PORT_INDEX)? "SRC DQ":"DST DQ", + time_string, (currentTime.tv_usec / 1000), pBufferHeader, nCountInV4L2); + + Exynos_OSAL_MutexUnlock(pPerfInfo->mutex); + + return nCountInV4L2; +} + +void Exynos_OSAL_CountReset(OMX_HANDLETYPE *hPerfInfo) +{ + EXYNOS_OMX_PERF_INFO *pPerfInfo = (EXYNOS_OMX_PERF_INFO *)hPerfInfo; + + if (pPerfInfo == NULL) + return; + + Exynos_OSAL_MutexLock(pPerfInfo->mutex); + + pPerfInfo->nCountInOMX = 0; + pPerfInfo->nCountInV4L2 = 0; + + pPerfInfo->nCurSlotIndex = 0; + pPerfInfo->nNextSlotIndex = 1; + Exynos_OSAL_Memset(&pPerfInfo->sBufferTime, 0, sizeof(sBufferTime)); + + pPerfInfo->latestOutTimestamp = 0; + + Exynos_OSAL_MutexUnlock(pPerfInfo->mutex); + + return; +} + +#if 0 +OMX_ERRORTYPE Exynos_OSAL_GetCountInfoUseOMXBuffer(OMX_HANDLETYPE *hPerfInfo, OMX_BUFFERHEADERTYPE *OMXBufferHeader, BUFFER_TIME *pBufferInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_PERF_INFO *countHandle = (EXYNOS_OMX_PERF_INFO *)hCountHandle; + OMX_U32 i = 0; + + if ((countHandle == NULL) || + (OMXBufferHeader == NULL) || + (pBufferInfo == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Error : OMX_ErrorBadParameter"); + return OMX_ErrorBadParameter; + } + + if (OMX_ErrorNone == Exynos_OSAL_MutexLock(countHandle->mutex)) { + for (i = 0; i < MAX_TIMESTAMP; i++) { + if (countHandle->sBufferTime[i].pBufferHeader == OMXBufferHeader) { + Exynos_OSAL_Memcpy(pBufferInfo, &(countHandle->sBufferTime[i]), sizeof(BUFFER_TIME)); + break; + } + } + Exynos_OSAL_MutexUnlock(countHandle->mutex); + if (i >= MAX_TIMESTAMP) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "can not find a bufferHeader !!"); + ret = OMX_ErrorNoMore; + } + } + return ret; +} +#endif + +static OMX_ERRORTYPE Exynos_OSAL_GetPerfInfoUseTimestamp( + OMX_HANDLETYPE *hPerfInfo, + OMX_TICKS timestamp, + BUFFER_INFO *pBufferInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_PERF_INFO *pPerfInfo = (EXYNOS_OMX_PERF_INFO *)hCountHandle; + OMX_U32 i = 0; + + + if ((pPerfInfo == NULL) || + (pBufferInfo == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_MutexLock(pPerfInfo->mutex); + + for (i = 0; i < MAX_TIMESTAMP; i++) { + if (pPerfInfo->sBufferTime[i].timestamp == timestamp) { + Exynos_OSAL_Memcpy(pBufferInfo, &(pPerfInfo->sBufferTime[i]), sizeof(BUFFER_INFO)); + break; + } + } + + if (i >= MAX_TIMESTAMP) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] Can not find %p in slot", __FUNCTION__, pBufferHeader); + ret = OMX_ErrorNoMore; + } + + Exynos_OSAL_MutexUnlock(pPerfInfo->mutex); + +EXIT: + return ret; +} + +void Exynos_OSAL_PrintCountInfo( + OMX_HANDLETYPE *hSrcPerfInfo, + OMX_HANDLETYPE *hDstPerfInfo, + OMX_BUFFERHEADERTYPE *pBufferHeader) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_PERF_INFO *pSrcPerfInfo = (EXYNOS_OMX_PERF_INFO *)hSrcPerfInfo; + EXYNOS_OMX_PERF_INFO *pDstPerfInfo = (EXYNOS_OMX_PERF_INFO *)hDstPerfInfo; + + BUFFER_INFO srcBufferInfo, dstBufferInfo; + + struct timeval currentTime; + struct tm *ptm = NULL; + char time_string[40] = { 0, }; + long milliseconds; + + OMX_S32 srcOMXtoV4L2 = 0; + OMX_S32 srcV4L2toOMX = 0; + OMX_S32 dstOMXtoV4L2 = 0; + OMX_S32 dstV4L2toOMX = 0; + + OMX_S32 ETBFTB = 0; + OMX_S32 ETBFBD = 0; + OMX_S32 FTBFBD = 0; + + OMX_S32 srcQdstQ = 0; + OMX_S32 srcQdstDQ = 0; + OMX_S32 dstQdstDQ = 0; + + Exynos_OSAL_Memset(&srcBufferInfo, 0, sizeof(srcBufferInfo)); + Exynos_OSAL_Memset(&dstBufferInfo, 0, sizeof(dstBufferInfo)); + + ret = Exynos_OSAL_GetPerfInfoUseTimestamp(hSrcPerfInfo, pBufferHeader->nTimeStamp, &srcBufferInfo); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] Failed to GetPerfInfoUseTimestamp about src", __FUNCTION__); + return; + } + + ret = Exynos_OSAL_GetPerfInfoUseTimestamp(hDstPerfInfo, pBufferHeader->nTimeStamp, &dstBufferInfo); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] Failed to GetPerfInfoUseTimestamp about dst", __FUNCTION__); + return; + } + + /* internal */ + { + gettimeofday(¤tTime, NULL); + + srcOMXtoV4L2 = Exynos_OSAL_MeasureTime(&(srcBufferInfo.currentTime), &(srcBufferInfo.queueTime)) / 1000; + //srcV4L2toOMX = Exynos_OSAL_MeasureTime(&(srcBufferInfo.queueTime), &(srcBufferInfo.?????????????????)) / 1000; + + dstOMXtoV4L2 = Exynos_OSAL_MeasureTime(&(dstBufferInfo.currentTime), &(dstBufferInfo.queueTime)) / 1000; + dstV4L2toOMX = Exynos_OSAL_MeasureTime(&(dstBufferInfo.dequeueTime), ¤tTime) / 1000; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] INTERNAL: srcOMXtoV4L2:%d, srcV4L2toOMX:%d, dstOMXtoV4L2:%d, dstV4L2toOMX:%d", + __FUNCTION__, srcOMXtoV4L2, srcV4L2toOMX, dstOMXtoV4L2, dstV4L2toOMX); + } + + /* vl42 */ + { + srcQdstQ = Exynos_OSAL_MeasureTime(&(srcBufferInfo.queueTime), &(dstBufferInfo.queueTime)) / 1000; + srcQdstDQ = Exynos_OSAL_MeasureTime(&(srcBufferInfo.queueTime), &(dstBufferInfo.dequeueTime)) / 1000; + dstQdstDQ = Exynos_OSAL_MeasureTime(&(dstBufferInfo.queueTime), &(dstBufferInfo.dequeueTime)) / 1000; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] V4L2: srcQdstQ:%d, srcQdstDQ:%d, dstQdstDQ:%d, src-V4L2QBufferCount:%d, dst-V4L2QBufferCount:%d", + __FUNCTION__, srcQdstQ, srcQdstDQ, dstQdstDQ, srcBufferInfo.nCountInV4L2, dstBufferInfo.nCountInV4L2); + } + + /* buffer rotation */ + { + ETBFTB = Exynos_OSAL_MeasureTime(&(srcBufferInfo.currentTime), &(dstBufferInfo.currentTime)) / 1000; + ETBFBD = Exynos_OSAL_MeasureTime(&(srcBufferInfo.currentTime), ¤tTime) / 1000; + FTBFBD = Exynos_OSAL_MeasureTime(&(dstBufferInfo.currentTime), ¤tTime) / 1000; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] BUFFER: ETBFTB:%d, ETBFBD:%d, FTBFBD:%d, src-OMXQBufferCount:%d, dst-OMXQBufferCount:%d", + __FUNCTION__, ETBFTB, ETBFBD, FTBFBD, srcBufferInfo.nCountInOMX, dstBufferInfo.nCountInOMX); + + if (ETBFTB > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] BUFFER: OUTPUT is slow!! real decode time:%d", + __FUNCTION__, FTBFBD / dstBufferInfo.nCountInOMX); + } else if (ETBFTB < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] BUFFER: INPUT is slow!! real decode time:%d", + __FUNCTION__, ETBFBD / srcBufferInfo.nCountInOMX); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%s] BUFFER: real decode time:%d or %d", + __FUNCTION__, ETBFBD / srcBufferInfo.nCountInOMX, FTBFBD / dstBufferInfo.nCountInOMX); + } + } + + /* buffer interval */ + { + OMX_S32 srcBufferInterval; + OMX_S32 dstBufferInterval; + + srcBufferInterval = Exynos_OSAL_MeasureTime(&(srcBufferInfo.previousIncomingTime), &(srcBufferInfo.currentIncomingTime)) / 1000; + dstBufferInterval = Exynos_OSAL_MeasureTime(&(dstBufferInfo.previousIncomingTime), &(dstBufferInfo.currentIncomingTime)) / 1000; + + if ((srcBufferInterval / (srcBufferInfo.OMXQBufferCount - 1)) > ((dstBufferInfo.timestamp - dstBufferInfo.previousTimeStamp) / 1000)) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PERFORM:: SLOW: Warning!! src buffer slow. srcBuffer Interval:%d, correct interval:%d, OMXQBufferCount:%d", + srcBufferInterval, + (srcBufferInfo.OMXQBufferCount == 1) ? srcBufferInterval : (srcBufferInterval / (srcBufferInfo.OMXQBufferCount - 1)), + srcBufferInfo.OMXQBufferCount); + if ((dstBufferInterval / (dstBufferInfo.OMXQBufferCount - 1)) > ((dstBufferInfo.timestamp - dstBufferInfo.previousTimeStamp) / 1000)) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PERFORM:: SLOW: Warning!! dst buffer slow. dstBuffer Interval:%d, correct interval:%d, OMXQBufferCount:%d", + dstBufferInterval, + (dstBufferInfo.OMXQBufferCount == 1) ? dstBufferInterval : (dstBufferInterval / (dstBufferInfo.OMXQBufferCount - 1)), + dstBufferInfo.OMXQBufferCount); + } + + { + OMX_S32 srcTimestampInterval; + OMX_S32 dstTimestampInterval; + + srcTimestampInterval = ((OMX_S32)(srcBufferInfo.timestamp - srcBufferInfo.previousTimeStamp)) / 1000; + dstTimestampInterval = ((OMX_S32)(dstBufferInfo.timestamp - dstBufferInfo.previousTimeStamp)) / 1000; + + if ((srcTimestampInterval > 0) && (dstTimestampInterval > 0)) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PERFORM:: TYPE: Normal timestamp contents"); + else if ((srcTimestampInterval < 0) && (dstTimestampInterval > 0)) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "PERFORM:: TYPE: PTS timestamp contents"); + else if ((srcTimestampInterval > 0) && (dstTimestampInterval < 0)) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "PERFORM:: TYPE: DTS timestamp contents"); + else + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PERFORM:: TYPE: Timestamp is strange!!"); + } + +/* + ptm = localtime (&srcBufferInfo.currentIncomingTime.tv_sec); + strftime (time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm); + milliseconds = srcBufferInfo.currentIncomingTime.tv_usec / 1000; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "ETB time = %s.%03ld\n", time_string, milliseconds); + + ptm = localtime (&dstBufferInfo.currentIncomingTime.tv_sec); + strftime (time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm); + milliseconds = dstBufferInfo.currentIncomingTime.tv_usec / 1000; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "FTB time = %s.%03ld\n", time_string, milliseconds); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "return time = %d ms", + Exynos_OSAL_MeasureTime(&(srcBufferInfo.currentIncomingTime), &(dstBufferInfo.currentIncomingTime)) / 1000); +*/ + + return; +} +#endif diff --git a/openmax/osal/Exynos_OSAL_ETC.h b/openmax/osal/Exynos_OSAL_ETC.h new file mode 100644 index 0000000..fdb6d96 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_ETC.h @@ -0,0 +1,119 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_ETC.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef Exynos_OSAL_ETC +#define Exynos_OSAL_ETC + +#include "OMX_Types.h" +#include "Exynos_OMX_Def.h" + +#ifdef PERFORMANCE_DEBUG +#include +#endif + +#define INT_TO_PTR(var) ((void *)(unsigned long)var) +#define PTR_TO_INT(var) ((int)(unsigned long)var) + +#ifdef __cplusplus +extern "C" { +#endif + +size_t Exynos_OSAL_Strcpy(OMX_PTR dest, OMX_PTR src); +OMX_S32 Exynos_OSAL_Strncmp(OMX_PTR str1, OMX_PTR str2, size_t num); +OMX_S32 Exynos_OSAL_Strcmp(OMX_PTR str1, OMX_PTR str2); +const char* Exynos_OSAL_Strstr(const char *str1, const char *str2); +size_t Exynos_OSAL_Strcat(OMX_PTR dest, OMX_PTR src); +size_t Exynos_OSAL_Strlen(const char *str); + +/* perf */ +typedef enum _PERF_ID_TYPE { + PERF_ID_CSC = 0, + PERF_ID_DEC, + PERF_ID_ENC, + PERF_ID_USER, + PERF_ID_MAX, +} PERF_ID_TYPE; + +void Exynos_OSAL_PerfInit(PERF_ID_TYPE id); +void Exynos_OSAL_PerfStart(PERF_ID_TYPE id); +void Exynos_OSAL_PerfStop(PERF_ID_TYPE id); +OMX_U32 Exynos_OSAL_PerfFrame(PERF_ID_TYPE id); +OMX_U32 Exynos_OSAL_PerfTotal(PERF_ID_TYPE id); +OMX_U32 Exynos_OSAL_PerfFrameCount(PERF_ID_TYPE id); +int Exynos_OSAL_PerfOver30ms(PERF_ID_TYPE id); +void Exynos_OSAL_PerfPrint(OMX_STRING prefix, PERF_ID_TYPE id); + +unsigned int Exynos_OSAL_GetPlaneCount(OMX_COLOR_FORMATTYPE eOMXFormat, PLANE_TYPE ePlaneType); +void Exynos_OSAL_GetPlaneSize(OMX_COLOR_FORMATTYPE eColorFormat, PLANE_TYPE ePlaneType, OMX_U32 nWidth, OMX_U32 nHeight, unsigned int nDataLen[MAX_BUFFER_PLANE], unsigned int nAllocLen[MAX_BUFFER_PLANE]); +OMX_U32 Exynos_OSAL_GetOutBufferSize(OMX_U32 nWidth, OMX_U32 nHeight, OMX_U32 nDefaultBufferSize); + +int Exynos_OSAL_OMX2VideoFormat(OMX_COLOR_FORMATTYPE eColorFormat, PLANE_TYPE ePlaneType); +OMX_COLOR_FORMATTYPE Exynos_OSAL_Video2OMXFormat(int nVideoFormat); + +OMX_COLOR_FORMATTYPE Exynos_OSAL_HAL2OMXColorFormat(unsigned int nHALFormat); +unsigned int Exynos_OSAL_OMX2HALPixelFormat(OMX_COLOR_FORMATTYPE eOMXFormat, PLANE_TYPE ePlaneType); + +int Exynos_OSAL_DataSpaceToColorSpace(int nDataSpace, int nFormat); +void Exynos_OSAL_GetRGBColorTypeForBitStream(EXYNOS_OMX_VIDEO_COLORASPECTS *pColorAspects, int nDataSpace, int nFormat); + +inline static const char *stateString(OMX_STATETYPE i) { + switch (i) { + case OMX_StateInvalid: return "OMX_StateInvaild"; + case OMX_StateLoaded: return "OMX_StateLoaded"; + case OMX_StateIdle: return "OMX_StateIdle"; + case OMX_StateExecuting: return "OMX_StateExecuting"; + case OMX_StatePause: return "OMX_StatePause"; + case OMX_StateWaitForResources: return "OMX_StateWaitForResources"; + default: return "??"; + } +} + +#ifdef PERFORMANCE_DEBUG +void Exynos_OSAL_Get_Perf_Property(); + +OMX_ERRORTYPE Exynos_OSAL_CountCreate(OMX_HANDLETYPE *hPerfInfo); +void Exynos_OSAL_CountTerminate(OMX_HANDLETYPE *hPerfInfo); + +OMX_S32 Exynos_OSAL_CountIncrease(OMX_HANDLETYPE *hPerfInfo, OMX_BUFFERHEADERTYPE *pBufferHeader, int nPortIndex); +OMX_S32 Exynos_OSAL_CountDecrease(OMX_HANDLETYPE *hPerfInfo, OMX_BUFFERHEADERTYPE *pBufferHeader, int nPortIndex); + +OMX_S32 Exynos_OSAL_V4L2CountIncrease(OMX_HANDLETYPE *hPerfInfo, OMX_BUFFERHEADERTYPE *pBufferHeader, int nPortIndex); +OMX_S32 Exynos_OSAL_V4L2CountDecrease(OMX_HANDLETYPE *hPerfInfo, OMX_BUFFERHEADERTYPE *pBufferHeader, int nPortIndex); + +void Exynos_OSAL_CountReset(OMX_HANDLETYPE *hPerfInfo); + +void Exynos_OSAL_PrintPerfInfo(OMX_HANDLETYPE *hSrcPerfInfo, OMX_HANDLETYPE *hDstPerfInfo, OMX_BUFFERHEADERTYPE *pBufferHeader); +//void Exynos_OSAL_PrintCountInfo(OMX_PTR *pStartHandle, BUFFER_TIME dstBufferInfo); +//OMX_ERRORTYPE Exynos_OSAL_GetCountInfoUseOMXBuffer(OMX_HANDLETYPE hCountHandle, OMX_BUFFERHEADERTYPE *OMXBufferHeader, BUFFER_TIME *pBufferInfo); + + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/osal/Exynos_OSAL_Event.c b/openmax/osal/Exynos_OSAL_Event.c new file mode 100644 index 0000000..88bdc88 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Event.c @@ -0,0 +1,220 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +/* + * @file Exynos_OSAL_Event.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + + +#include +#include +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_Event.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "Exynos_OSAL_EVENT" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OMX_ERRORTYPE Exynos_OSAL_SignalCreate(OMX_HANDLETYPE *eventHandle) +{ + Exynos_OSAL_THREADEVENT *event; + OMX_ERRORTYPE ret = OMX_ErrorNone; + + event = (Exynos_OSAL_THREADEVENT *)Exynos_OSAL_Malloc(sizeof(Exynos_OSAL_THREADEVENT)); + if (!event) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Memset(event, 0, sizeof(Exynos_OSAL_THREADEVENT)); + event->signal = OMX_FALSE; + + ret = Exynos_OSAL_MutexCreate(&event->mutex); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Free(event); + goto EXIT; + } + + if (pthread_cond_init(&event->condition, NULL)) { + Exynos_OSAL_MutexTerminate(event->mutex); + Exynos_OSAL_Free(event); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + *eventHandle = (OMX_HANDLETYPE)event; + ret = OMX_ErrorNone; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_SignalTerminate(OMX_HANDLETYPE eventHandle) +{ + Exynos_OSAL_THREADEVENT *event = (Exynos_OSAL_THREADEVENT *)eventHandle; + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (!event) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = Exynos_OSAL_MutexLock(event->mutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pthread_cond_destroy(&event->condition)) { + Exynos_OSAL_MutexUnlock(event->mutex); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + ret = Exynos_OSAL_MutexUnlock(event->mutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + ret = Exynos_OSAL_MutexTerminate(event->mutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Free(event); + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_SignalReset(OMX_HANDLETYPE eventHandle) +{ + Exynos_OSAL_THREADEVENT *event = (Exynos_OSAL_THREADEVENT *)eventHandle; + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (!event) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = Exynos_OSAL_MutexLock(event->mutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + event->signal = OMX_FALSE; + + Exynos_OSAL_MutexUnlock(event->mutex); + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_SignalSet(OMX_HANDLETYPE eventHandle) +{ + Exynos_OSAL_THREADEVENT *event = (Exynos_OSAL_THREADEVENT *)eventHandle; + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (!event) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + ret = Exynos_OSAL_MutexLock(event->mutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + event->signal = OMX_TRUE; + pthread_cond_signal(&event->condition); + + Exynos_OSAL_MutexUnlock(event->mutex); + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_SignalWait(OMX_HANDLETYPE eventHandle, OMX_U32 ms) +{ + Exynos_OSAL_THREADEVENT *event = (Exynos_OSAL_THREADEVENT *)eventHandle; + OMX_ERRORTYPE ret = OMX_ErrorNone; + struct timespec timeout; + struct timeval now; + int funcret = 0; + long tv_us, tv_ns; + + FunctionIn(); + + if (!event) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + gettimeofday(&now, NULL); + + tv_us = now.tv_usec + (ms * 1000); + timeout.tv_sec = now.tv_sec + (tv_us / 1000000); + tv_ns = (tv_us % 1000000) * 1000; + timeout.tv_nsec = tv_ns; + + ret = Exynos_OSAL_MutexLock(event->mutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (ms == 0) { + if (!event->signal) + ret = OMX_ErrorTimeout; + } else if (ms == DEF_MAX_WAIT_TIME) { + while (!event->signal) + pthread_cond_wait(&event->condition, (pthread_mutex_t *)(event->mutex)); + ret = OMX_ErrorNone; + } else { + while (!event->signal) { + funcret = pthread_cond_timedwait(&event->condition, (pthread_mutex_t *)(event->mutex), &timeout); + if ((!event->signal) && (funcret == ETIMEDOUT)) { + ret = OMX_ErrorTimeout; + break; + } + } + } + + Exynos_OSAL_MutexUnlock(event->mutex); + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/openmax/osal/Exynos_OSAL_Event.h b/openmax/osal/Exynos_OSAL_Event.h new file mode 100644 index 0000000..f7ccd89 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Event.h @@ -0,0 +1,61 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Event.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef Exynos_OSAL_EVENT +#define Exynos_OSAL_EVENT + +#include +#include "OMX_Types.h" +#include "OMX_Core.h" + + +#define DEF_MAX_WAIT_TIME 0xFFFFFFFF + +typedef struct _Exynos_OSAL_THREADEVENT +{ + OMX_BOOL signal; + OMX_HANDLETYPE mutex; + pthread_cond_t condition; +} Exynos_OSAL_THREADEVENT; + + +#ifdef __cplusplus +extern "C" { +#endif + + +OMX_ERRORTYPE Exynos_OSAL_SignalCreate(OMX_HANDLETYPE *eventHandle); +OMX_ERRORTYPE Exynos_OSAL_SignalTerminate(OMX_HANDLETYPE eventHandle); +OMX_ERRORTYPE Exynos_OSAL_SignalReset(OMX_HANDLETYPE eventHandle); +OMX_ERRORTYPE Exynos_OSAL_SignalSet(OMX_HANDLETYPE eventHandle); +OMX_ERRORTYPE Exynos_OSAL_SignalWait(OMX_HANDLETYPE eventHandle, OMX_U32 ms); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/osal/Exynos_OSAL_ImageConverter.cpp b/openmax/osal/Exynos_OSAL_ImageConverter.cpp new file mode 100644 index 0000000..660525b --- /dev/null +++ b/openmax/osal/Exynos_OSAL_ImageConverter.cpp @@ -0,0 +1,403 @@ +/* + * Copyright 2019 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_ImageConverter.c + * @brief + * @author Taehwan Kim (t_h.kim@samsung.com) + * @author Byunggwan Kang (bk0917.kang@samsung.com) + * @author Seungbeom Kim (sbcrux.kim@samsung.com) + * @version 1.0.0 + * @history + * 2019.02.12 : Create + */ +#include + +#include +#include +#include + +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Def.h" + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_Library.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Platform.h" + +#include "Exynos_OSAL_ImageConverter.h" + +#include "VendorVideoAPI.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "Exynos_OSAL_ImageConverter" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +using namespace android; + +#ifdef __cplusplus + extern "C" { +#endif + +#define CHECK_HDR10(f, r, p, t, c) \ + ((f == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatYUV420Planar16) && \ + (r == ColorAspects::RangeLimited) && \ + (p == ColorAspects::PrimariesBT2020) && \ + (t == ColorAspects::TransferST2084) && \ + (c == ColorAspects::MatrixBT2020)) + +#define LUMINANCE_DIV_FACTOR 10000.0 + +#define LIB_NAME "libImageFormatConverter.so" +#define LIB_FN_NAME_INIT "CL_HDR2SDR_ARM_init" +#define LIB_FN_NAME_DEINIT "CL_HDR2SDR_ARM_deinit" +#define LIB_FN_NAME_RUN "CL_HDR2SDR_ARM_convert" + +typedef enum _Image_ColorFormat { + INVALID = -1, + TP10_UBWC_QCOM = 0, + P010_LINEAR = 1, + NV12 = 2, + RGBA = 3, + YV12 = 4, + NV21 = 5, +} Image_ColorFormat; + +typedef enum _ALGO_t { + NONE = 0, + NORMAL = 1, + HI_JACK = 2, +} ALGO_t; + +typedef struct _MULTIPLANE_t { + int handle; + void *host_ptr; + int size; +} MULTIPLANE_t; + +typedef struct _HDR2SDR_config_params_t { + Image_ColorFormat color_format; + MULTIPLANE_t buffer[3]; +} HDR2SDR_config_params_t; + +typedef struct _HDR10PLUS_DYNAMIC_INFO { + unsigned char country_code; // 0xB5 + unsigned short provider_code; // 0x003C + unsigned short provider_oriented_code; // 0x0001 + + unsigned char application_identifier; + unsigned char application_version; + + unsigned int display_max_luminance; + //unsigned char targeted_system_display_actual_peak_luminance_flag = 0; + //-------------------------------------------------------------------- + /* window = 1, fixed point at this moment */ + unsigned int maxscl[3]; + unsigned int avg_maxrgb; + unsigned char num_maxrgb_percentiles; + unsigned char maxrgb_percentages[15]; + unsigned int maxrgb_percentiles[15]; + //unsigned char fraction_bright_pixels = 1; + //-------------------------------------------------------------------- + //unsigned char mastering_display_actual_peak_luminance_flag = 0; + //-------------------------------------------------------------------- + /* window = 1, fixed point at this moment */ + unsigned char tone_mapping_flag; // 1 + unsigned short knee_point_x; //[ ~ 4095] + unsigned short knee_point_y; //[ ~ 4095] + unsigned char num_bezier_curve_anchors; // 10 [ ~ 15] + unsigned short bezier_curve_anchors[15]; + //unsigned char color_saturation_mapping_flag = 0; + //-------------------------------------------------------------------- +} HDR10PLUS_DYNAMIC_INFO; + +typedef OMX_BOOL (*ConvertInitFunc)(const unsigned int width, const unsigned int height, const ALGO_t algo, void **user_data, const bool usage); +typedef void (*ConvertDeinitFunc)(void *user_data); +typedef OMX_BOOL (*ConvertRunFunc)(HDR2SDR_config_params_t *In_params, HDR2SDR_config_params_t *Out_params, HDR10PLUS_DYNAMIC_INFO *meta, unsigned int mastering_max_luminance, void *user_data); + +typedef struct _EXYNOS_OMX_IMG_CONV_HANDLE { + void *pLibHandle; + ConvertInitFunc Init; + ConvertDeinitFunc Deinit; + ConvertRunFunc Run; + void *pUserData; + OMX_BOOL bHasDynamicInfo; + HDR10PLUS_DYNAMIC_INFO *pDynamicInfo; +} EXYNOS_OMX_IMG_CONV_HANDLE; + + +OMX_HANDLETYPE Exynos_OSAL_ImgConv_Create( + OMX_U32 nWidth, + OMX_U32 nHeight, + OMX_U32 nMode) +{ + EXYNOS_OMX_IMG_CONV_HANDLE *pHandle = NULL; + + pHandle = (EXYNOS_OMX_IMG_CONV_HANDLE *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_IMG_CONV_HANDLE)); + if (pHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__); + goto EXIT; + } + + pHandle->pDynamicInfo = (HDR10PLUS_DYNAMIC_INFO *)Exynos_OSAL_Malloc(sizeof(HDR10PLUS_DYNAMIC_INFO)); + if (pHandle->pDynamicInfo == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__); + Exynos_OSAL_Free(pHandle); + pHandle = NULL; + goto EXIT; + } + + pHandle->pLibHandle = Exynos_OSAL_dlopen(LIB_NAME, RTLD_NOW|RTLD_GLOBAL); + if (pHandle->pLibHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%s] Failed to Exynos_OSAL_dlopen() : reason(%s)", + __FUNCTION__, Exynos_OSAL_dlerror()); + Exynos_OSAL_Free(pHandle->pDynamicInfo); + Exynos_OSAL_Free(pHandle); + pHandle = NULL; + goto EXIT; + } + + pHandle->Init = (ConvertInitFunc)Exynos_OSAL_dlsym(pHandle->pLibHandle, (const char *)LIB_FN_NAME_INIT); + pHandle->Deinit = (ConvertDeinitFunc)Exynos_OSAL_dlsym(pHandle->pLibHandle, (const char *)LIB_FN_NAME_DEINIT); + pHandle->Run = (ConvertRunFunc)Exynos_OSAL_dlsym(pHandle->pLibHandle, (const char *)LIB_FN_NAME_RUN); + + if ((pHandle->Init == NULL) || + (pHandle->Deinit == NULL) || + (pHandle->Run == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_dlsym()", __FUNCTION__); + Exynos_OSAL_dlclose(pHandle->pLibHandle); + Exynos_OSAL_Free(pHandle->pDynamicInfo); + Exynos_OSAL_Free(pHandle); + pHandle = NULL; + goto EXIT; + } + + if (pHandle->Init(nWidth, nHeight, ((nMode == 0)? NORMAL:HI_JACK), &pHandle->pUserData, false) != OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Init()", __FUNCTION__); + Exynos_OSAL_dlclose(pHandle->pLibHandle); + Exynos_OSAL_Free(pHandle->pDynamicInfo); + Exynos_OSAL_Free(pHandle); + pHandle = NULL; + goto EXIT; + } + + pHandle->bHasDynamicInfo = OMX_FALSE; + +EXIT: + return (OMX_HANDLETYPE)pHandle; +} + +void Exynos_OSAL_ImgConv_Terminate(OMX_HANDLETYPE hImgConv) +{ + EXYNOS_OMX_IMG_CONV_HANDLE *pHandle = (EXYNOS_OMX_IMG_CONV_HANDLE *)hImgConv; + + if (pHandle == NULL) + return; + + if (pHandle->Deinit != NULL) + pHandle->Deinit(pHandle->pUserData); + + Exynos_OSAL_dlclose(pHandle->pLibHandle); + + if (pHandle->pDynamicInfo != NULL) + Exynos_OSAL_Free(pHandle->pDynamicInfo); + + Exynos_OSAL_Free(pHandle); + pHandle = NULL; +} + +OMX_ERRORTYPE Exynos_OSAL_ImgConv_Run( + OMX_HANDLETYPE hImgConv, + OMX_COMPONENTTYPE *pOMXComponent, + OMX_PTR pBuffer, + OMX_PTR pHDRDynamic) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_IMG_CONV_HANDLE *pHandle = (EXYNOS_OMX_IMG_CONV_HANDLE *)hImgConv; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + /* graphic buffer */ + EXYNOS_OMX_MULTIPLANE_BUFFER bufferInfo; + EXYNOS_OMX_LOCK_RANGE range; + OMX_U32 stride = 0; + unsigned int nAllocLen[MAX_BUFFER_PLANE] = { 0, 0, 0 }; + unsigned int nDataLen[MAX_BUFFER_PLANE] = { 0, 0, 0 }; + + /* HDR information */ + EXYNOS_OMX_VIDEO_COLORASPECTS *pFWCA = NULL; /* framework */ + EXYNOS_OMX_VIDEO_COLORASPECTS *pBSCA = NULL; /* bitstream */ + DescribeColorAspectsParams CA; + + /* parmas for image convert */ + HDR2SDR_config_params_t inConfig, outConfig; + OMX_U16 max_display_luminance_cd_m2 = 0; + + int i; + + if ((pHandle == NULL) || + (pOMXComponent == NULL) || + (pBuffer == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] invalid parameters", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) { + pExynosPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + + if (pExynosPort->eMetaDataType != METADATA_TYPE_GRAPHIC) { + /* not supported */ + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] meta type is wrong(0x%x)", + pExynosComponent, __FUNCTION__, pExynosPort->eMetaDataType); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + range.nWidth = pExynosPort->portDefinition.format.video.nFrameWidth; + range.nHeight = pExynosPort->portDefinition.format.video.nFrameHeight; + range.eColorFormat = pExynosPort->portDefinition.format.video.eColorFormat; + + pFWCA = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].ColorAspects; + pBSCA = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX].ColorAspects; + + if (Exynos_OSAL_Strstr(pExynosComponent->componentName, "VP9") || + Exynos_OSAL_Strstr(pExynosComponent->componentName, "vp9")) { + /* In case of VP9, should rely on information in webm container */ + getColorAspectsPreferFramework(pBSCA, pFWCA, (void *)&CA); + } else { + /* generally, rely on information in bitstream */ + getColorAspectsPreferBitstream(pBSCA, pFWCA, (void *)&CA); + } + } else { + /* not supported */ + ret = OMX_ErrorUndefined; + goto EXIT; + } + + ret = Exynos_OSAL_LockMetaData(pBuffer, range, &stride, &bufferInfo, pExynosPort->eMetaDataType); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]: Failed to Exynos_OSAL_LockMetaData()", + pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (!CHECK_HDR10(bufferInfo.eColorFormat, CA.sAspects.mRange, CA.sAspects.mPrimaries, + CA.sAspects.mTransfer, CA.sAspects.mMatrixCoeffs)) { + /* it is not HDR10 */ + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_GetPlaneSize(bufferInfo.eColorFormat, pExynosPort->ePlaneType, stride, range.nHeight, nDataLen, nAllocLen); + + Exynos_OSAL_Memset(&inConfig, 1, sizeof(inConfig)); + Exynos_OSAL_Memset(&outConfig, 1, sizeof(outConfig)); + + inConfig.color_format = P010_LINEAR; + inConfig.buffer[0].handle = bufferInfo.fd[0]; + inConfig.buffer[0].size = nAllocLen[0]; + inConfig.buffer[0].host_ptr = bufferInfo.addr[0]; + inConfig.buffer[1].handle = bufferInfo.fd[1]; + inConfig.buffer[1].size = nAllocLen[1]; + inConfig.buffer[1].host_ptr = bufferInfo.addr[1]; + + outConfig.color_format = P010_LINEAR; + + if (pHDRDynamic != NULL) { + ExynosHdrDynamicInfo *DY = (ExynosHdrDynamicInfo *)pHDRDynamic; + + if (DY->valid != 0) { + HDR10PLUS_DYNAMIC_INFO info; + memset(&info, 0, sizeof(info)); + + info.country_code = DY->data.country_code; + info.provider_code = DY->data.provider_code; + info.provider_oriented_code = DY->data.provider_oriented_code; + info.application_identifier = DY->data.application_identifier; + info.application_version = DY->data.application_version; +#ifdef USE_FULL_ST2094_40 + info.display_max_luminance = DY->data.targeted_system_display_maximum_luminance; + for (int i = 0; i < 3; i++) { + info.maxscl[i] = DY->data.maxscl[0][i]; + } + + info.avg_maxrgb = DY->data.average_maxrgb[0]; + info.num_maxrgb_percentiles = DY->data.num_maxrgb_percentiles[0]; + for (int i = 0; i < info.num_maxrgb_percentiles; i++) { + info.maxrgb_percentages[i] = DY->data.maxrgb_percentages[0][i]; + info.maxrgb_percentiles[i] = DY->data.maxrgb_percentiles[0][i]; + } + + info.tone_mapping_flag = DY->data.tone_mapping.tone_mapping_flag[0]; + info.knee_point_x = DY->data.tone_mapping.knee_point_x[0]; + info.knee_point_y = DY->data.tone_mapping.knee_point_y[0]; + info.num_bezier_curve_anchors = DY->data.tone_mapping.num_bezier_curve_anchors[0]; + + for (int i = 0; i < info.num_bezier_curve_anchors; i++) { + info.bezier_curve_anchors[i] = DY->data.tone_mapping.bezier_curve_anchors[0][i]; + } +#else // USE_FULL_ST2094_40 + info.display_max_luminance = DY->data.display_maximum_luminance; + for (int i = 0; i < 3; i++) { + info.maxscl[i] = DY->data.maxscl[i]; + } + + info.num_maxrgb_percentiles = DY->data.num_maxrgb_percentiles; + for (int i = 0; i < info.num_maxrgb_percentiles; i++) { + info.maxrgb_percentages[i] = DY->data.maxrgb_percentages[i]; + info.maxrgb_percentiles[i] = DY->data.maxrgb_percentiles[i]; + } + + info.tone_mapping_flag = DY->data.tone_mapping.tone_mapping_flag; + info.knee_point_x = DY->data.tone_mapping.knee_point_x; + info.knee_point_y = DY->data.tone_mapping.knee_point_y; + info.num_bezier_curve_anchors = DY->data.tone_mapping.num_bezier_curve_anchors; + + for (int i = 0; i < info.num_bezier_curve_anchors; i++) { + info.bezier_curve_anchors[i] = DY->data.tone_mapping.bezier_curve_anchors[i]; + } +#endif + if (memcmp(pHandle->pDynamicInfo, &info, sizeof(info))) { + pHandle->bHasDynamicInfo = OMX_TRUE; + memcpy(pHandle->pDynamicInfo, &info, sizeof(info)); + } + } + } + + max_display_luminance_cd_m2 = (int)((pExynosPort->HDRStaticInfo.nMaxDisplayLuminance / LUMINANCE_DIV_FACTOR) + 0.5); + + if (pHandle->Run != NULL) { + pHandle->Run(&inConfig, &outConfig, ((pHandle->bHasDynamicInfo == OMX_TRUE)? pHandle->pDynamicInfo:NULL), + max_display_luminance_cd_m2, pHandle->pUserData); + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +EXIT: + if ((pBuffer != NULL) && (pExynosPort != NULL)) + Exynos_OSAL_UnlockMetaData(pBuffer, pExynosPort->eMetaDataType); + + return ret; +} + +#ifdef __cplusplus +} +#endif diff --git a/openmax/osal/Exynos_OSAL_ImageConverter.h b/openmax/osal/Exynos_OSAL_ImageConverter.h new file mode 100644 index 0000000..b4d7789 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_ImageConverter.h @@ -0,0 +1,44 @@ +/* + * Copyright 2019 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_ImageConverter.h + * @brief + * @author Taehwan Kim (t_h.kim@samsung.com) + * @author Byunggwan Kang (bk0917.kang@samsung.com) + * @author Seungbeom Kim (sbcrux.kim@samsung.com) + * @version 1.0.0 + * @history + * 2019.02.12 : Create + */ + +#ifndef Exynos_OSAL_IMAGE_CONVERTER +#define Exynos_OSAL_IMAGE_CONVERTER + +#include "OMX_Types.h" +#include "OMX_Component.h" + +#ifdef __cplusplus +extern "C" { +#endif +OMX_HANDLETYPE Exynos_OSAL_ImgConv_Create(OMX_U32 nWidth, OMX_U32 nHeight, OMX_U32 nMode); +void Exynos_OSAL_ImgConv_Terminate(OMX_HANDLETYPE hImgConv); +OMX_ERRORTYPE Exynos_OSAL_ImgConv_Run(OMX_HANDLETYPE hImgConv, OMX_COMPONENTTYPE *pOMXComponent, OMX_PTR pBuffer, OMX_PTR pHDRDynamic); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/osal/Exynos_OSAL_Library.c b/openmax/osal/Exynos_OSAL_Library.c new file mode 100644 index 0000000..88d2251 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Library.c @@ -0,0 +1,108 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Library.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + + +#include +#include +#include +#include +#include + +#include "Exynos_OSAL_Library.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_Memory.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_OSAL_LIB" +#include "Exynos_OSAL_Log.h" + +void *Exynos_OSAL_dlopen(const char *filename, int flag) +{ + return dlopen(filename, flag); +} + +void *Exynos_OSAL_dlsym(void *handle, const char *symbol) +{ + return dlsym(handle, symbol); +} + +int Exynos_OSAL_dlclose(void *handle) +{ + return dlclose(handle); +} + +const char *Exynos_OSAL_dlerror(void) +{ + return dlerror(); +} + +const char *Exynos_OSAL_GetLibPath(void) +{ +#ifdef USE_VENDOR_IMAGE + const char *ANDROID_LIB_INSTALL_PATH = "/vendor/lib/omx/"; + const char *ANDROID_LIB64_INSTALL_PATH = "/vendor/lib64/omx/"; +#else + const char *ANDROID_LIB_INSTALL_PATH = "/system/lib/omx/"; + const char *ANDROID_LIB64_INSTALL_PATH = "/system/lib64/omx/"; +#endif + const char *OTHERS_LIB_INSTALL_PATH = "/usr/lib/"; + const char *OTHERS_LIB64_INSTALL_PATH = "/usr/lib/"; + + struct utsname buf; + + Exynos_OSAL_Memset(&buf, 0, sizeof(buf)); + +#ifndef USE_ANDROID + /* try to get system info */ + if (uname(&buf) < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to uname()", __FUNCTION__); + return (IS_64BIT_OS)? ANDROID_LIB64_INSTALL_PATH:ANDROID_LIB_INSTALL_PATH; + } + + if (Exynos_OSAL_Strncmp(buf.sysname, "Linux", Exynos_OSAL_Strlen("Linux")) != 0) { + /* others */ + return (IS_64BIT_OS)? OTHERS_LIB64_INSTALL_PATH:OTHERS_LIB_INSTALL_PATH; + } +#endif + /* default : android */ + return (IS_64BIT_OS)? ANDROID_LIB64_INSTALL_PATH:ANDROID_LIB_INSTALL_PATH; +} + +int Exynos_OSAL_CheckLibName(char *pLibName) +{ + if (pLibName == NULL) + return -1; + + /* it should be started as "libOMX.Exynos." */ + if (Exynos_OSAL_Strncmp(pLibName, "libOMX.Exynos.", Exynos_OSAL_Strlen("libOMX.Exynos.")) == 0) { + /* it should be delimited as ".so" */ + char *pExtPosit =(((char *)pLibName) + (Exynos_OSAL_Strlen(pLibName) - 3)); + if (Exynos_OSAL_Strncmp(pExtPosit, ".so", Exynos_OSAL_Strlen(".so")) == 0) + return 0; + } + + return -1; +} diff --git a/openmax/osal/Exynos_OSAL_Library.h b/openmax/osal/Exynos_OSAL_Library.h new file mode 100644 index 0000000..62c5c89 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Library.h @@ -0,0 +1,48 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Library.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef Exynos_OSAL_LIBRARY +#define Exynos_OSAL_LIBRARY + +#include "OMX_Types.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +void *Exynos_OSAL_dlopen(const char *filename, int flag); +void *Exynos_OSAL_dlsym(void *handle, const char *symbol); +int Exynos_OSAL_dlclose(void *handle); +const char *Exynos_OSAL_dlerror(void); +const char *Exynos_OSAL_GetLibPath(void); +int Exynos_OSAL_CheckLibName(char *pLibName); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/osal/Exynos_OSAL_Log.c b/openmax/osal/Exynos_OSAL_Log.c new file mode 100644 index 0000000..042bd43 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Log.c @@ -0,0 +1,126 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Log.c + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include + +#include "Exynos_OSAL_Log.h" +#include "Exynos_OSAL_ETC.h" +/* =======TAG========= +EXYNOS_RM +EXYNOS_LOG +EXYNOS_COMP_REGS +EXYNOS_OMX_CORE +EXYNOS_LOG_THREAD +EXYNOS_LOG_SEMA +Exynos_OSAL_SkypeHD +Exynos_OSAL_Android +Exynos_OSAL_EVENT +EXYNOS_BASE_COMP +EXYNOS_BASE_PORT +EXYNOS_VIDEO_DEC +EXYNOS_VIDEO_DECCONTROL +EXYNOS_H264_DEC +EXYNOS_HEVC_DEC +EXYNOS_MPEG2_DEC +EXYNOS_MPEG4_DEC +EXYNOS_WMV_DEC +EXYNOS_VP8_DEC +EXYNOS_VP9_DEC +EXYNOS_VIDEO_ENC +EXYNOS_VIDEO_ENCCONTROL +EXYNOS_HEVC_ENC +EXYNOS_H264_ENC +EXYNOS_MPEG4_ENC +EXYNOS_VP8_ENC +EXYNOS_VP9_ENC +======================*/ +static char debugProp[PROPERTY_VALUE_MAX]; +typedef enum _DEBUG_LEVEL +{ + LOG_LEVEL_ALL = EXYNOS_LOG_FUNC_TRACE, + LOG_LEVEL2 = EXYNOS_LOG_TRACE, + LOG_LEVEL1 = EXYNOS_LOG_ESSENTIAL, + LOG_DEFAULT = EXYNOS_LOG_INFO, + LOG_LEVELTAG, +} EXYNOS_DEBUG_LEVEL; + +static unsigned int log_prop = LOG_DEFAULT; + +void Exynos_OSAL_Get_Log_Property() +{ +#ifdef EXYNOS_LOG + if (property_get("ro.vendor.debug.omx.level", debugProp, NULL) > 0) { + if(!(Exynos_OSAL_Strncmp(debugProp, "0", 1))) { + log_prop = LOG_DEFAULT; + } else if (!(Exynos_OSAL_Strncmp(debugProp, "1", 1))) { + log_prop = LOG_LEVEL1; + } else if (!(Exynos_OSAL_Strncmp(debugProp, "2", 1))) { + log_prop = LOG_LEVEL2; + } else if (!(Exynos_OSAL_Strncmp(debugProp, "3", 1))) { + log_prop = LOG_LEVEL_ALL; + } else { + log_prop = LOG_LEVELTAG; + } + } +#endif +} + +void _Exynos_OSAL_Log(EXYNOS_LOG_LEVEL logLevel, const char *tag, const char *msg, ...) +{ + va_list argptr; +#ifdef EXYNOS_LOG + if (log_prop == LOG_LEVELTAG) { + if(!Exynos_OSAL_Strstr(debugProp, tag)) + return; + } else if (logLevel < log_prop) + return; +#endif + va_start(argptr, msg); + + switch (logLevel) { + case EXYNOS_LOG_FUNC_TRACE: + __android_log_vprint(ANDROID_LOG_VERBOSE, tag, msg, argptr); + break; + case EXYNOS_LOG_TRACE: + __android_log_vprint(ANDROID_LOG_DEBUG, tag, msg, argptr); + break; + case EXYNOS_LOG_ESSENTIAL: + case EXYNOS_LOG_INFO: + __android_log_vprint(ANDROID_LOG_INFO, tag, msg, argptr); + break; + case EXYNOS_LOG_WARNING: + __android_log_vprint(ANDROID_LOG_WARN, tag, msg, argptr); + break; + case EXYNOS_LOG_ERROR: + __android_log_vprint(ANDROID_LOG_ERROR, tag, msg, argptr); + break; + default: + __android_log_vprint(ANDROID_LOG_VERBOSE, tag, msg, argptr); + } + + va_end(argptr); +} diff --git a/openmax/osal/Exynos_OSAL_Log.h b/openmax/osal/Exynos_OSAL_Log.h new file mode 100644 index 0000000..9c3f23a --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Log.h @@ -0,0 +1,86 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Log.h + * @brief + * @author Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + * 2012.8.27 : Add trace function + */ + +#ifndef EXYNOS_OSAL_LOG +#define EXYNOS_OSAL_LOG + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef EXYNOS_LOG_OFF +#define EXYNOS_LOG +#endif + +#ifndef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_LOG" +#endif + +#define EXYNOS_TRACE_FUNCTION_INFO + +#ifndef USE_ANDROID +#define PROPERTY_KEY_MAX 32 +#define PROPERTY_VALUE_MAX 92 +#endif + +typedef enum _LOG_LEVEL +{ + EXYNOS_LOG_FUNC_TRACE, + EXYNOS_LOG_TRACE, + EXYNOS_LOG_ESSENTIAL, + EXYNOS_LOG_INFO, + EXYNOS_LOG_WARNING, + EXYNOS_LOG_ERROR +} EXYNOS_LOG_LEVEL; + +#ifdef EXYNOS_LOG +#define Exynos_OSAL_Log(a, ...) ((void)_Exynos_OSAL_Log(a, EXYNOS_LOG_TAG, __VA_ARGS__)) +#else +#define Exynos_OSAL_Log(a, ...) \ + do { \ + if ((a == EXYNOS_LOG_ERROR) || \ + (a == EXYNOS_LOG_WARNING)) \ + ((void)_Exynos_OSAL_Log(a, EXYNOS_LOG_TAG, __VA_ARGS__)); \ + } while (0) +#endif + +#ifdef EXYNOS_TRACE_FUNCTION_INFO +#define FunctionIn() _Exynos_OSAL_Log(EXYNOS_LOG_FUNC_TRACE, EXYNOS_LOG_TAG, "%s In , Line: %d", __FUNCTION__, __LINE__) +#define FunctionOut() _Exynos_OSAL_Log(EXYNOS_LOG_FUNC_TRACE, EXYNOS_LOG_TAG, "%s Out , Line: %d", __FUNCTION__, __LINE__) +#else +#define FunctionIn() ((void *)0) +#define FunctionOut() ((void *)0) +#endif + +void Exynos_OSAL_Get_Log_Property(); +void _Exynos_OSAL_Log(EXYNOS_LOG_LEVEL logLevel, const char *tag, const char *msg, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/osal/Exynos_OSAL_Memory.c b/openmax/osal/Exynos_OSAL_Memory.c new file mode 100644 index 0000000..28006a6 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Memory.c @@ -0,0 +1,92 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Memory.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" + +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +static int mem_cnt = 0; + +OMX_PTR Exynos_OSAL_Malloc(OMX_U32 size) +{ + OMX_PTR addr = NULL; + + addr = (OMX_PTR)malloc(size); + if (addr != NULL) { + mem_cnt++; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] count: %d", __FUNCTION__, mem_cnt); + } + + return addr; +} + +void Exynos_OSAL_Free(OMX_PTR addr) +{ + if (addr) { + free(addr); + mem_cnt--; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] count: %d", __FUNCTION__, mem_cnt); + } + + return; +} + +OMX_PTR Exynos_OSAL_Memset(OMX_PTR dest, OMX_S32 c, OMX_S32 n) +{ + return memset(dest, c, n); +} + +OMX_PTR Exynos_OSAL_Memcpy(OMX_PTR dest, OMX_PTR src, OMX_S32 n) +{ + return memcpy(dest, src, n); +} + +OMX_PTR Exynos_OSAL_Memmove(OMX_PTR dest, OMX_PTR src, OMX_S32 n) +{ + return memmove(dest, src, n); +} + +OMX_S32 Exynos_OSAL_Memcmp(OMX_PTR dest, OMX_PTR src, OMX_S32 n) +{ + return memcmp(dest, src, n); +} + +OMX_PTR Exynos_OSAL_Mmap(OMX_PTR addr, size_t length, OMX_S32 prot, OMX_S32 flags, unsigned long fd, off_t offset) +{ + return mmap(addr, length, prot, flags, fd, offset); +} + +OMX_S32 Exynos_OSAL_Munmap(OMX_PTR addr, size_t length) +{ + return munmap(addr, length); +} diff --git a/openmax/osal/Exynos_OSAL_Memory.h b/openmax/osal/Exynos_OSAL_Memory.h new file mode 100644 index 0000000..73cae7d --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Memory.h @@ -0,0 +1,51 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Memory.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef Exynos_OSAL_MEMORY +#define Exynos_OSAL_MEMORY + +#include "OMX_Types.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_PTR Exynos_OSAL_Malloc(OMX_U32 size); +void Exynos_OSAL_Free(OMX_PTR addr); +OMX_PTR Exynos_OSAL_Memset(OMX_PTR dest, OMX_S32 c, OMX_S32 n); +OMX_PTR Exynos_OSAL_Memcpy(OMX_PTR dest, OMX_PTR src, OMX_S32 n); +OMX_PTR Exynos_OSAL_Memmove(OMX_PTR dest, OMX_PTR src, OMX_S32 n); +OMX_S32 Exynos_OSAL_Memcmp(OMX_PTR dest, OMX_PTR src, OMX_S32 n); +OMX_PTR Exynos_OSAL_Mmap(OMX_PTR addr, size_t length, OMX_S32 prot, OMX_S32 flags, unsigned long fd, off_t offset); +OMX_S32 Exynos_OSAL_Munmap(OMX_PTR addr, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/openmax/osal/Exynos_OSAL_Mutex.c b/openmax/osal/Exynos_OSAL_Mutex.c new file mode 100644 index 0000000..511a715 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Mutex.c @@ -0,0 +1,90 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Mutex.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_Mutex.h" + +OMX_ERRORTYPE Exynos_OSAL_MutexCreate(OMX_HANDLETYPE *mutexHandle) +{ + pthread_mutex_t *mutex; + + mutex = (pthread_mutex_t *)Exynos_OSAL_Malloc(sizeof(pthread_mutex_t)); + if (!mutex) + return OMX_ErrorInsufficientResources; + + if (pthread_mutex_init(mutex, NULL) != 0) { + Exynos_OSAL_Free(mutex); + return OMX_ErrorUndefined; + } + + *mutexHandle = (OMX_HANDLETYPE)mutex; + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OSAL_MutexTerminate(OMX_HANDLETYPE mutexHandle) +{ + pthread_mutex_t *mutex = (pthread_mutex_t *)mutexHandle; + + if (mutex == NULL) + return OMX_ErrorBadParameter; + + if (pthread_mutex_destroy(mutex) != 0) + return OMX_ErrorUndefined; + + Exynos_OSAL_Free(mutex); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OSAL_MutexLock(OMX_HANDLETYPE mutexHandle) +{ + pthread_mutex_t *mutex = (pthread_mutex_t *)mutexHandle; + + if (mutex == NULL) + return OMX_ErrorBadParameter; + + if (pthread_mutex_lock(mutex) != 0) + return OMX_ErrorUndefined; + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OSAL_MutexUnlock(OMX_HANDLETYPE mutexHandle) +{ + pthread_mutex_t *mutex = (pthread_mutex_t *)mutexHandle; + + if (mutex == NULL) + return OMX_ErrorBadParameter; + + if (pthread_mutex_unlock(mutex) != 0) + return OMX_ErrorUndefined; + + return OMX_ErrorNone; +} diff --git a/openmax/osal/Exynos_OSAL_Mutex.h b/openmax/osal/Exynos_OSAL_Mutex.h new file mode 100644 index 0000000..d8875ed --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Mutex.h @@ -0,0 +1,47 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Mutex.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create +*/ + +#ifndef Exynos_OSAL_MUTEX +#define Exynos_OSAL_MUTEX + +#include "OMX_Types.h" +#include "OMX_Core.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OSAL_MutexCreate(OMX_HANDLETYPE *mutexHandle); +OMX_ERRORTYPE Exynos_OSAL_MutexTerminate(OMX_HANDLETYPE mutexHandle); +OMX_ERRORTYPE Exynos_OSAL_MutexLock(OMX_HANDLETYPE mutexHandle); +OMX_ERRORTYPE Exynos_OSAL_MutexUnlock(OMX_HANDLETYPE mutexHandle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/osal/Exynos_OSAL_Platform.h b/openmax/osal/Exynos_OSAL_Platform.h new file mode 100644 index 0000000..18b0e01 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Platform.h @@ -0,0 +1,69 @@ +/* + * Copyright 2016 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Platform.h + * @brief + * @author Taehwan Kim (t_h.kim@samsung.com) + * @version 1.0.0 + * @history + * 2016.07.05 : Create + */ + +#ifndef Exynos_OSAL_PLATFORM +#define Exynos_OSAL_PLATFORM + +#include "OMX_Types.h" +#include "OMX_Core.h" +#include "OMX_Index.h" +#include "Exynos_OSAL_SharedMemory.h" + +#include "Exynos_OSAL_Android.h" +#include "Exynos_OSAL_ImageConverter.h" + +#ifdef __cplusplus +extern "C" { +#endif +OMX_ERRORTYPE Exynos_OSAL_GetParameter(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure); +OMX_ERRORTYPE Exynos_OSAL_SetParameter(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure); + +OMX_ERRORTYPE Exynos_OSAL_GetConfig(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_INOUT OMX_PTR pComponentConfigStructure); +OMX_ERRORTYPE Exynos_OSAL_SetConfig(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentConfigStructure); + +OMX_ERRORTYPE Exynos_OSAL_LockMetaData(OMX_IN OMX_PTR pBuffer, + OMX_IN EXYNOS_OMX_LOCK_RANGE range, + OMX_OUT OMX_U32 *pStride, + OMX_OUT EXYNOS_OMX_MULTIPLANE_BUFFER *pBufferInfo, + OMX_IN EXYNOS_METADATA_TYPE eMetaType); +OMX_ERRORTYPE Exynos_OSAL_UnlockMetaData(OMX_IN OMX_PTR pBuffer, + OMX_IN EXYNOS_METADATA_TYPE eMetaType); + +OMX_ERRORTYPE Exynos_OSAL_GetInfoFromMetaData(OMX_IN OMX_PTR pBuffer, OMX_OUT EXYNOS_OMX_MULTIPLANE_BUFFER *pBufferInfo, OMX_IN EXYNOS_METADATA_TYPE eMetaDataType); + +OMX_PTR Exynos_OSAL_AllocMetaDataBuffer(OMX_HANDLETYPE hSharedMemory, EXYNOS_METADATA_TYPE eMetaDataType, OMX_U32 nSizeBytes, MEMORY_TYPE eMemoryType); +OMX_ERRORTYPE Exynos_OSAL_FreeMetaDataBuffer(OMX_HANDLETYPE hSharedMemory, EXYNOS_METADATA_TYPE eMetaDataType, OMX_PTR pTempBuffer); +#ifdef __cplusplus +} +#endif +#endif diff --git a/openmax/osal/Exynos_OSAL_Queue.c b/openmax/osal/Exynos_OSAL_Queue.c new file mode 100644 index 0000000..024111c --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Queue.c @@ -0,0 +1,201 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Queue.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + + +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_Queue.h" + + +OMX_ERRORTYPE Exynos_OSAL_QueueCreate(EXYNOS_QUEUE *queueHandle, int maxNumElem) +{ + int i = 0; + EXYNOS_QElem *newqelem = NULL; + EXYNOS_QElem *currentqelem = NULL; + EXYNOS_QUEUE *queue = (EXYNOS_QUEUE *)queueHandle; + + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (!queue) + return OMX_ErrorBadParameter; + + ret = Exynos_OSAL_MutexCreate(&queue->qMutex); + if (ret != OMX_ErrorNone) + return ret; + + queue->first = (EXYNOS_QElem *)Exynos_OSAL_Malloc(sizeof(EXYNOS_QElem)); + if (queue->first == NULL) + return OMX_ErrorInsufficientResources; + + Exynos_OSAL_Memset(queue->first, 0, sizeof(EXYNOS_QElem)); + currentqelem = queue->last = queue->first; + queue->numElem = 0; + queue->maxNumElem = maxNumElem; + for (i = 0; i < (queue->maxNumElem - 2); i++) { + newqelem = (EXYNOS_QElem *)Exynos_OSAL_Malloc(sizeof(EXYNOS_QElem)); + if (newqelem == NULL) { + while (queue->first != NULL) { + currentqelem = queue->first->qNext; + Exynos_OSAL_Free((OMX_PTR)queue->first); + queue->first = currentqelem; + } + return OMX_ErrorInsufficientResources; + } else { + Exynos_OSAL_Memset(newqelem, 0, sizeof(EXYNOS_QElem)); + currentqelem->qNext = newqelem; + currentqelem = newqelem; + } + } + + currentqelem->qNext = queue->first; + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OSAL_QueueTerminate(EXYNOS_QUEUE *queueHandle) +{ + int i = 0; + EXYNOS_QElem *currentqelem = NULL; + EXYNOS_QUEUE *queue = (EXYNOS_QUEUE *)queueHandle; + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (!queue) + return OMX_ErrorBadParameter; + + for ( i = 0; i < (queue->maxNumElem - 2); i++) { + if (queue->first == NULL) + goto EXIT; + currentqelem = queue->first->qNext; + Exynos_OSAL_Free(queue->first); + queue->first = currentqelem; + } + + if(queue->first) { + Exynos_OSAL_Free(queue->first); + queue->first = NULL; + } + +EXIT: + ret = Exynos_OSAL_MutexTerminate(queue->qMutex); + queue->qMutex = NULL; + + return ret; +} + +int Exynos_OSAL_Queue(EXYNOS_QUEUE *queueHandle, void *data) +{ + EXYNOS_QUEUE *queue = (EXYNOS_QUEUE *)queueHandle; + if (queue == NULL) + return -1; + + Exynos_OSAL_MutexLock(queue->qMutex); + + if ((queue->last == NULL) || + (queue->last->data != NULL) || + (queue->numElem >= queue->maxNumElem)) { + Exynos_OSAL_MutexUnlock(queue->qMutex); + return -1; + } + queue->last->data = data; + queue->last = queue->last->qNext; + queue->numElem++; + + Exynos_OSAL_MutexUnlock(queue->qMutex); + return 0; +} + +void *Exynos_OSAL_Dequeue(EXYNOS_QUEUE *queueHandle) +{ + void *data = NULL; + EXYNOS_QUEUE *queue = (EXYNOS_QUEUE *)queueHandle; + if (queue == NULL) + return NULL; + + Exynos_OSAL_MutexLock(queue->qMutex); + + if ((queue->first->data == NULL) || (queue->numElem <= 0)) { + Exynos_OSAL_MutexUnlock(queue->qMutex); + return NULL; + } + data = queue->first->data; + queue->first->data = NULL; + queue->first = queue->first->qNext; + queue->numElem--; + + Exynos_OSAL_MutexUnlock(queue->qMutex); + return data; +} + +int Exynos_OSAL_GetElemNum(EXYNOS_QUEUE *queueHandle) +{ + int ElemNum = 0; + EXYNOS_QUEUE *queue = (EXYNOS_QUEUE *)queueHandle; + if (queue == NULL) + return -1; + + Exynos_OSAL_MutexLock(queue->qMutex); + ElemNum = queue->numElem; + Exynos_OSAL_MutexUnlock(queue->qMutex); + return ElemNum; +} + +int Exynos_OSAL_SetElemNum(EXYNOS_QUEUE *queueHandle, int ElemNum) +{ + EXYNOS_QUEUE *queue = (EXYNOS_QUEUE *)queueHandle; + if (queue == NULL) + return -1; + + Exynos_OSAL_MutexLock(queue->qMutex); + queue->numElem = ElemNum; + Exynos_OSAL_MutexUnlock(queue->qMutex); + return ElemNum; +} + +int Exynos_OSAL_ResetQueue(EXYNOS_QUEUE *queueHandle) +{ + EXYNOS_QUEUE *queue = (EXYNOS_QUEUE *)queueHandle; + EXYNOS_QElem *currentqelem = NULL; + + if (queue == NULL) + return -1; + + Exynos_OSAL_MutexLock(queue->qMutex); + queue->first->data = NULL; + currentqelem = queue->first->qNext; + while (currentqelem != queue->first) { + currentqelem->data = NULL; + currentqelem = currentqelem->qNext; + } + queue->last = queue->first; + queue->numElem = 0x00; + Exynos_OSAL_MutexUnlock(queue->qMutex); + + return 0; +} diff --git a/openmax/osal/Exynos_OSAL_Queue.h b/openmax/osal/Exynos_OSAL_Queue.h new file mode 100644 index 0000000..6300b45 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Queue.h @@ -0,0 +1,68 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Queue.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OSAL_QUEUE +#define EXYNOS_OSAL_QUEUE + +#include "OMX_Types.h" +#include "OMX_Core.h" + +#define QUEUE_ELEMENTS 10 +#define MAX_QUEUE_ELEMENTS 40 + +typedef struct _EXYNOS_QElem +{ + void *data; + struct _EXYNOS_QElem *qNext; +} EXYNOS_QElem; + +typedef struct _EXYNOS_QUEUE +{ + EXYNOS_QElem *first; + EXYNOS_QElem *last; + int numElem; + int maxNumElem; + OMX_HANDLETYPE qMutex; +} EXYNOS_QUEUE; + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OSAL_QueueCreate(EXYNOS_QUEUE *queueHandle, int maxNumElem); +OMX_ERRORTYPE Exynos_OSAL_QueueTerminate(EXYNOS_QUEUE *queueHandle); +int Exynos_OSAL_Queue(EXYNOS_QUEUE *queueHandle, void *data); +void *Exynos_OSAL_Dequeue(EXYNOS_QUEUE *queueHandle); +int Exynos_OSAL_GetElemNum(EXYNOS_QUEUE *queueHandle); +int Exynos_OSAL_SetElemNum(EXYNOS_QUEUE *queueHandle, int ElemNum); +int Exynos_OSAL_ResetQueue(EXYNOS_QUEUE *queueHandle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/osal/Exynos_OSAL_Semaphore.c b/openmax/osal/Exynos_OSAL_Semaphore.c new file mode 100644 index 0000000..d454730 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Semaphore.c @@ -0,0 +1,161 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Semaphore.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_Thread.h" +#include "Exynos_OSAL_Semaphore.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_LOG_SEMA" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +OMX_ERRORTYPE Exynos_OSAL_SemaphoreCreate(OMX_HANDLETYPE *semaphoreHandle) +{ + sem_t *sema; + + sema = (sem_t *)Exynos_OSAL_Malloc(sizeof(sem_t)); + if (!sema) + return OMX_ErrorInsufficientResources; + + if (sem_init(sema, 0, 0) != 0) { + Exynos_OSAL_Free(sema); + return OMX_ErrorUndefined; + } + + *semaphoreHandle = (OMX_HANDLETYPE)sema; + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OSAL_SemaphoreTerminate(OMX_HANDLETYPE semaphoreHandle) +{ + sem_t *sema = (sem_t *)semaphoreHandle; + + if (sema == NULL) + return OMX_ErrorBadParameter; + + if (sem_destroy(sema) != 0) + return OMX_ErrorUndefined; + + Exynos_OSAL_Free(sema); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OSAL_SemaphoreWait(OMX_HANDLETYPE semaphoreHandle) +{ + sem_t *sema = (sem_t *)semaphoreHandle; + + FunctionIn(); + + if (sema == NULL) + return OMX_ErrorBadParameter; + + if (sem_wait(sema) != 0) + return OMX_ErrorUndefined; + + FunctionOut(); + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OSAL_SemaphoreTryWait(OMX_HANDLETYPE semaphoreHandle) +{ + sem_t *sema = (sem_t *)semaphoreHandle; + + FunctionIn(); + + if (sema == NULL) + return OMX_ErrorBadParameter; + + if (sem_trywait(sema) != 0) + return OMX_ErrorUndefined; + + FunctionOut(); + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OSAL_SemaphorePost(OMX_HANDLETYPE semaphoreHandle) +{ + sem_t *sema = (sem_t *)semaphoreHandle; + + FunctionIn(); + + if (sema == NULL) + return OMX_ErrorBadParameter; + + if (sem_post(sema) != 0) + return OMX_ErrorUndefined; + + FunctionOut(); + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OSAL_Set_SemaphoreCount(OMX_HANDLETYPE semaphoreHandle, OMX_S32 val) +{ + if (semaphoreHandle == NULL) + return OMX_ErrorBadParameter; + + while (semaphoreHandle != NULL) { + OMX_S32 cnt = 0; + Exynos_OSAL_Get_SemaphoreCount(semaphoreHandle, &cnt); + + if (cnt == val) + break; + else if (cnt > val) + Exynos_OSAL_SemaphoreWait(semaphoreHandle); + else if (cnt < val) + Exynos_OSAL_SemaphorePost(semaphoreHandle); + + Exynos_OSAL_SleepMillisec(0); + } + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OSAL_Get_SemaphoreCount(OMX_HANDLETYPE semaphoreHandle, OMX_S32 *val) +{ + sem_t *sema = (sem_t *)semaphoreHandle; + int semaVal = 0; + + if (sema == NULL) + return OMX_ErrorBadParameter; + + if (sem_getvalue(sema, &semaVal) != 0) + return OMX_ErrorUndefined; + + *val = (OMX_S32)semaVal; + + return OMX_ErrorNone; +} diff --git a/openmax/osal/Exynos_OSAL_Semaphore.h b/openmax/osal/Exynos_OSAL_Semaphore.h new file mode 100644 index 0000000..8618407 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Semaphore.h @@ -0,0 +1,50 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Semaphore.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef Exynos_OSAL_SEMAPHORE +#define Exynos_OSAL_SEMAPHORE + +#include "OMX_Types.h" +#include "OMX_Core.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OSAL_SemaphoreCreate(OMX_HANDLETYPE *semaphoreHandle); +OMX_ERRORTYPE Exynos_OSAL_SemaphoreTerminate(OMX_HANDLETYPE semaphoreHandle); +OMX_ERRORTYPE Exynos_OSAL_SemaphoreWait(OMX_HANDLETYPE semaphoreHandle); +OMX_ERRORTYPE Exynos_OSAL_SemaphoreTryWait(OMX_HANDLETYPE semaphoreHandle); +OMX_ERRORTYPE Exynos_OSAL_SemaphorePost(OMX_HANDLETYPE semaphoreHandle); +OMX_ERRORTYPE Exynos_OSAL_Set_SemaphoreCount(OMX_HANDLETYPE semaphoreHandle, OMX_S32 val); +OMX_ERRORTYPE Exynos_OSAL_Get_SemaphoreCount(OMX_HANDLETYPE semaphoreHandle, OMX_S32 *val); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/osal/Exynos_OSAL_SharedMemory.c b/openmax/osal/Exynos_OSAL_SharedMemory.c new file mode 100644 index 0000000..371894c --- /dev/null +++ b/openmax/osal/Exynos_OSAL_SharedMemory.c @@ -0,0 +1,546 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_SharedMemory.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Jinsung Yang (jsgood.yang@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include +#include +#include +#ifdef USE_ANDROID +#include +#include +#endif +#include +#include + +#include + +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_SharedMemory.h" + +#include "Exynos_OSAL_ETC.h" + +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +static int mem_cnt = 0; +static int map_cnt = 0; + +struct EXYNOS_SHAREDMEM_LIST; +typedef struct _EXYNOS_SHAREDMEM_LIST +{ + unsigned long IONBuffer; + OMX_PTR mapAddr; + OMX_U32 allocSize; + OMX_BOOL owner; + struct _EXYNOS_SHAREDMEM_LIST *pNextMemory; +} EXYNOS_SHAREDMEM_LIST; + +typedef struct _EXYNOS_SHARED_MEMORY +{ + unsigned long hIONHandle; + EXYNOS_SHAREDMEM_LIST *pAllocMemory; + OMX_HANDLETYPE hSMMutex; +} EXYNOS_SHARED_MEMORY; + + +OMX_HANDLETYPE Exynos_OSAL_SharedMemory_Open() +{ + EXYNOS_SHARED_MEMORY *pHandle = NULL; + long IONClient = -1; + + pHandle = (EXYNOS_SHARED_MEMORY *)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHARED_MEMORY)); + if (pHandle == NULL) + goto EXIT; + Exynos_OSAL_Memset(pHandle, 0, sizeof(EXYNOS_SHARED_MEMORY)); + + IONClient = (long)exynos_ion_open(); + if (IONClient < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_open is failed: %d", IONClient); + Exynos_OSAL_Free((void *)pHandle); + pHandle = NULL; + goto EXIT; + } + + pHandle->hIONHandle = (unsigned long)IONClient; + + if (OMX_ErrorNone != Exynos_OSAL_MutexCreate(&pHandle->hSMMutex)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_MutexCreate", __FUNCTION__); + /* free a ion_client */ + exynos_ion_close(pHandle->hIONHandle); + pHandle->hIONHandle = 0; + + Exynos_OSAL_Free((void *)pHandle); + pHandle = NULL; + } + +EXIT: + return (OMX_HANDLETYPE)pHandle; +} + +void Exynos_OSAL_SharedMemory_Close(OMX_HANDLETYPE handle) +{ + EXYNOS_SHARED_MEMORY *pHandle = (EXYNOS_SHARED_MEMORY *)handle; + EXYNOS_SHAREDMEM_LIST *pSMList = NULL; + EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL; + EXYNOS_SHAREDMEM_LIST *pDeleteElement = NULL; + + if (pHandle == NULL) + goto EXIT; + + Exynos_OSAL_MutexLock(pHandle->hSMMutex); + pCurrentElement = pSMList = pHandle->pAllocMemory; + + while (pCurrentElement != NULL) { + pDeleteElement = pCurrentElement; + pCurrentElement = pCurrentElement->pNextMemory; + + /* if mmap was not called, mapAddr is same as IONBuffer */ + if (pDeleteElement->mapAddr != (void *)pDeleteElement->IONBuffer) { + if (Exynos_OSAL_Munmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Munmap", __FUNCTION__); + } + + pDeleteElement->mapAddr = NULL; + pDeleteElement->allocSize = 0; + + if (pDeleteElement->owner) { + /* free a ion_buffer */ + close(pDeleteElement->IONBuffer); + mem_cnt--; + } + pDeleteElement->IONBuffer = 0; + + Exynos_OSAL_Free(pDeleteElement); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] count: %d", __FUNCTION__, mem_cnt); + } + + pHandle->pAllocMemory = pSMList = NULL; + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + Exynos_OSAL_MutexTerminate(pHandle->hSMMutex); + pHandle->hSMMutex = NULL; + + /* free a ion_client */ + exynos_ion_close(pHandle->hIONHandle); + pHandle->hIONHandle = 0; + + Exynos_OSAL_Free(pHandle); + +EXIT: + return; +} + +OMX_PTR Exynos_OSAL_SharedMemory_Alloc(OMX_HANDLETYPE handle, OMX_U32 size, MEMORY_TYPE memoryType) +{ + EXYNOS_SHARED_MEMORY *pHandle = (EXYNOS_SHARED_MEMORY *)handle; + EXYNOS_SHAREDMEM_LIST *pSMList = NULL; + EXYNOS_SHAREDMEM_LIST *pElement = NULL; + EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL; + long IONBuffer = -1; + OMX_PTR pBuffer = NULL; + unsigned int mask; + unsigned int flag; + + if (pHandle == NULL) + goto EXIT; + + pElement = (EXYNOS_SHAREDMEM_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHAREDMEM_LIST)); + if (pElement == NULL) + goto EXIT; + Exynos_OSAL_Memset(pElement, 0, sizeof(EXYNOS_SHAREDMEM_LIST)); + pElement->owner = OMX_TRUE; + + /* priority is like as EXT > SECURE > CONTIG > CACHED > NORMAL */ + switch ((int)memoryType) { + case (EXT_MEMORY | SECURE_MEMORY | CONTIG_MEMORY | CACHED_MEMORY): /* EXTRA */ + case (EXT_MEMORY | SECURE_MEMORY | CONTIG_MEMORY): + case (EXT_MEMORY | SECURE_MEMORY | CACHED_MEMORY): + case (EXT_MEMORY | SECURE_MEMORY): + mask = EXYNOS_ION_HEAP_VIDEO_STREAM_MASK; + flag = ION_FLAG_PROTECTED; + break; + case (EXT_MEMORY | CONTIG_MEMORY | CACHED_MEMORY): + case (EXT_MEMORY | CONTIG_MEMORY): + case (EXT_MEMORY | CACHED_MEMORY): + case EXT_MEMORY: + mask = EXYNOS_ION_HEAP_VIDEO_STREAM_MASK; + flag = 0; + break; + case (SECURE_MEMORY | CONTIG_MEMORY | CACHED_MEMORY): /* SECURE */ + case (SECURE_MEMORY | CONTIG_MEMORY): + case (SECURE_MEMORY | CACHED_MEMORY): + case SECURE_MEMORY: + mask = EXYNOS_ION_HEAP_VIDEO_STREAM_MASK; + flag = ION_FLAG_PROTECTED; + break; + case (CONTIG_MEMORY | CACHED_MEMORY): /* CONTIG */ + case CONTIG_MEMORY: + mask = EXYNOS_ION_HEAP_VIDEO_STREAM_MASK; + flag = 0; + break; + case CACHED_MEMORY: /* CACHED */ + mask = EXYNOS_ION_HEAP_SYSTEM_MASK; + flag = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; + break; + default: /* NORMAL */ + // NOTE: cached? + mask = EXYNOS_ION_HEAP_SYSTEM_MASK; + flag = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; + break; + } + + if (flag & ION_FLAG_CACHED) /* use improved cache oprs */ + flag |= ION_FLAG_CACHED_NEEDS_SYNC; + + if ((IONBuffer = exynos_ion_alloc(pHandle->hIONHandle, size, mask, flag)) < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%s] Failed to exynos_ion_alloc(mask:%x, flag:%x)", __FUNCTION__, mask, flag); + if (memoryType == CONTIG_MEMORY) { + /* retry at normal area */ + flag = 0; + if ((IONBuffer = exynos_ion_alloc(pHandle->hIONHandle, size, mask, flag)) < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] retry: Failed to exynos_ion_alloc(mask:%x, flag:%x)", __FUNCTION__, mask, flag); + Exynos_OSAL_Free((OMX_PTR)pElement); + goto EXIT; + } + } + } + + if (flag & ION_FLAG_PROTECTED) { + /* in case of DRM, do not call mmap. so set a fd instead of vaddr */ + pBuffer = (OMX_PTR)IONBuffer; + } else { + pBuffer = Exynos_OSAL_Mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, IONBuffer, 0); + if (pBuffer == MAP_FAILED) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Mmap(size:%d)", __FUNCTION__, size); + /* free a ion_buffer */ + close(IONBuffer); // NOTE: argument to exynos_ion_close/ion_close() should be allocated by ion_open/exynos_ion_open + Exynos_OSAL_Free((OMX_PTR)pElement); + pBuffer = NULL; + goto EXIT; + } + } + + pElement->IONBuffer = (unsigned long)IONBuffer; + pElement->mapAddr = pBuffer; + pElement->allocSize = size; + pElement->pNextMemory = NULL; + + Exynos_OSAL_MutexLock(pHandle->hSMMutex); + pSMList = pHandle->pAllocMemory; + if (pSMList == NULL) { + pHandle->pAllocMemory = pSMList = pElement; + } else { + pCurrentElement = pSMList; + while (pCurrentElement->pNextMemory != NULL) { + pCurrentElement = pCurrentElement->pNextMemory; + } + pCurrentElement->pNextMemory = pElement; + } + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + mem_cnt++; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] count: %d", __FUNCTION__, mem_cnt); + +EXIT: + return pBuffer; +} + +void Exynos_OSAL_SharedMemory_Free(OMX_HANDLETYPE handle, OMX_PTR pBuffer) +{ + EXYNOS_SHARED_MEMORY *pHandle = (EXYNOS_SHARED_MEMORY *)handle; + EXYNOS_SHAREDMEM_LIST *pSMList = NULL; + EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL; + EXYNOS_SHAREDMEM_LIST *pDeleteElement = NULL; + + if (pHandle == NULL) + goto EXIT; + + Exynos_OSAL_MutexLock(pHandle->hSMMutex); + pSMList = pHandle->pAllocMemory; + if (pSMList == NULL) { + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + goto EXIT; + } + + pCurrentElement = pSMList; + if (pSMList->mapAddr == pBuffer) { + pDeleteElement = pSMList; + pHandle->pAllocMemory = pSMList = pSMList->pNextMemory; + } else { + while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) && + (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr != pBuffer)) + pCurrentElement = pCurrentElement->pNextMemory; + + if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) && + (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr == pBuffer)) { + pDeleteElement = pCurrentElement->pNextMemory; + pCurrentElement->pNextMemory = pDeleteElement->pNextMemory; + } else { + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] can't find a buffer(%p) in list", __FUNCTION__, pBuffer); + goto EXIT; + } + } + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + if (pDeleteElement->mapAddr != (void *)pDeleteElement->IONBuffer) { + if (Exynos_OSAL_Munmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Munmap", __FUNCTION__); + goto EXIT; + } + } + + pDeleteElement->mapAddr = NULL; + pDeleteElement->allocSize = 0; + + if (pDeleteElement->owner) { + /* free a ion_buffer */ + close(pDeleteElement->IONBuffer); + mem_cnt--; + } + pDeleteElement->IONBuffer = 0; + + Exynos_OSAL_Free(pDeleteElement); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] count: %d", __FUNCTION__, mem_cnt); + +EXIT: + return; +} + +OMX_PTR Exynos_OSAL_SharedMemory_Map(OMX_HANDLETYPE handle, OMX_U32 size, unsigned long ionfd) +{ + EXYNOS_SHARED_MEMORY *pHandle = (EXYNOS_SHARED_MEMORY *)handle; + EXYNOS_SHAREDMEM_LIST *pSMList = NULL; + EXYNOS_SHAREDMEM_LIST *pElement = NULL; + EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL; + OMX_S32 IONBuffer = 0; + OMX_PTR pBuffer = NULL; + + if (pHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + goto EXIT; + } + + pElement = (EXYNOS_SHAREDMEM_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHAREDMEM_LIST)); + if (pElement == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Malloc()", __FUNCTION__); + goto EXIT; + } + + Exynos_OSAL_Memset(pElement, 0, sizeof(EXYNOS_SHAREDMEM_LIST)); + + IONBuffer = (OMX_S32)ionfd; + + if (IONBuffer < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] FD(%u) is wrong", __FUNCTION__, IONBuffer); + Exynos_OSAL_Free((void*)pElement); + goto EXIT; + } + + pBuffer = Exynos_OSAL_Mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, IONBuffer, 0); + if (pBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Mmap(size:%d)", __FUNCTION__, size); + /* free a ion_buffer */ + close(IONBuffer); + Exynos_OSAL_Free((void*)pElement); + goto EXIT; + } + + pElement->IONBuffer = IONBuffer; + pElement->mapAddr = pBuffer; + pElement->allocSize = size; + pElement->pNextMemory = NULL; + + Exynos_OSAL_MutexLock(pHandle->hSMMutex); + pSMList = pHandle->pAllocMemory; + if (pSMList == NULL) { + pHandle->pAllocMemory = pSMList = pElement; + } else { + pCurrentElement = pSMList; + while (pCurrentElement->pNextMemory != NULL) { + pCurrentElement = pCurrentElement->pNextMemory; + } + pCurrentElement->pNextMemory = pElement; + } + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + map_cnt++; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] count: %d", __FUNCTION__, map_cnt); + +EXIT: + return pBuffer; +} + +void Exynos_OSAL_SharedMemory_Unmap(OMX_HANDLETYPE handle, unsigned long ionfd) +{ + EXYNOS_SHARED_MEMORY *pHandle = (EXYNOS_SHARED_MEMORY *)handle; + EXYNOS_SHAREDMEM_LIST *pSMList = NULL; + EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL; + EXYNOS_SHAREDMEM_LIST *pDeleteElement = NULL; + + if (pHandle == NULL) + goto EXIT; + + Exynos_OSAL_MutexLock(pHandle->hSMMutex); + pSMList = pHandle->pAllocMemory; + if (pSMList == NULL) { + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + goto EXIT; + } + + pCurrentElement = pSMList; + if (pSMList->IONBuffer == ionfd) { + pDeleteElement = pSMList; + pHandle->pAllocMemory = pSMList = pSMList->pNextMemory; + } else { + while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) && + (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer != ionfd)) + pCurrentElement = pCurrentElement->pNextMemory; + + if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) && + (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer == ionfd)) { + pDeleteElement = pCurrentElement->pNextMemory; + pCurrentElement->pNextMemory = pDeleteElement->pNextMemory; + } else { + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] can't find a buffer(%u) in list", __FUNCTION__, ionfd); + goto EXIT; + } + } + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + if (Exynos_OSAL_Munmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Failed to Exynos_OSAL_Munmap", __FUNCTION__); + goto EXIT; + } + pDeleteElement->mapAddr = NULL; + pDeleteElement->allocSize = 0; + pDeleteElement->IONBuffer = 0; + + Exynos_OSAL_Free(pDeleteElement); + + map_cnt--; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] count: %d", __FUNCTION__, map_cnt); + +EXIT: + return; +} + +unsigned long Exynos_OSAL_SharedMemory_VirtToION(OMX_HANDLETYPE handle, OMX_PTR pBuffer) +{ + EXYNOS_SHARED_MEMORY *pHandle = (EXYNOS_SHARED_MEMORY *)handle; + EXYNOS_SHAREDMEM_LIST *pSMList = NULL; + EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL; + EXYNOS_SHAREDMEM_LIST *pFindElement = NULL; + + unsigned long ion_addr = 0; + + if (pHandle == NULL || pBuffer == NULL) + goto EXIT; + + Exynos_OSAL_MutexLock(pHandle->hSMMutex); + pSMList = pHandle->pAllocMemory; + if (pSMList == NULL) { + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + goto EXIT; + } + + pCurrentElement = pSMList; + if (pSMList->mapAddr == pBuffer) { + pFindElement = pSMList; + } else { + while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) && + (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr != pBuffer)) + pCurrentElement = pCurrentElement->pNextMemory; + + if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) && + (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->mapAddr == pBuffer)) { + pFindElement = pCurrentElement->pNextMemory; + } else { + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] can't find a buffer(%p) in list", __FUNCTION__, pBuffer); + goto EXIT; + } + } + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + ion_addr = pFindElement->IONBuffer; + +EXIT: + return ion_addr; +} + +OMX_PTR Exynos_OSAL_SharedMemory_IONToVirt(OMX_HANDLETYPE handle, unsigned long ionfd) +{ + EXYNOS_SHARED_MEMORY *pHandle = (EXYNOS_SHARED_MEMORY *)handle; + EXYNOS_SHAREDMEM_LIST *pSMList = NULL; + EXYNOS_SHAREDMEM_LIST *pCurrentElement = NULL; + EXYNOS_SHAREDMEM_LIST *pFindElement = NULL; + + OMX_PTR pBuffer = NULL; + + if ((pHandle == NULL) || ((long)ionfd < 0)) + goto EXIT; + + Exynos_OSAL_MutexLock(pHandle->hSMMutex); + pSMList = pHandle->pAllocMemory; + if (pSMList == NULL) { + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + goto EXIT; + } + + pCurrentElement = pSMList; + if (pSMList->IONBuffer == ionfd) { + pFindElement = pSMList; + } else { + while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) && + (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer != ionfd)) + pCurrentElement = pCurrentElement->pNextMemory; + + if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) && + (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer == ionfd)) { + pFindElement = pCurrentElement->pNextMemory; + } else { + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%s] can't find a buffer(%u) in list", __FUNCTION__, ionfd); + goto EXIT; + } + } + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + pBuffer = pFindElement->mapAddr; + +EXIT: + return pBuffer; +} diff --git a/openmax/osal/Exynos_OSAL_SharedMemory.h b/openmax/osal/Exynos_OSAL_SharedMemory.h new file mode 100644 index 0000000..78fd969 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_SharedMemory.h @@ -0,0 +1,61 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_SharedMemory.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef EXYNOS_OSAL_SHAREDMEMORY +#define EXYNOS_OSAL_SHAREDMEMORY + +#include "OMX_Types.h" + +typedef enum _MEMORY_TYPE +{ + NORMAL_MEMORY = 0x00, + CACHED_MEMORY = 0x01, /* cached */ + CONTIG_MEMORY = 0x02, /* continuos */ + SECURE_MEMORY = 0x04, /* secure */ + EXT_MEMORY = 0x08, /* ext area */ +} MEMORY_TYPE; + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_HANDLETYPE Exynos_OSAL_SharedMemory_Open(); +void Exynos_OSAL_SharedMemory_Close(OMX_HANDLETYPE handle); +OMX_PTR Exynos_OSAL_SharedMemory_Alloc(OMX_HANDLETYPE handle, OMX_U32 size, MEMORY_TYPE memoryType); +void Exynos_OSAL_SharedMemory_Free(OMX_HANDLETYPE handle, OMX_PTR pBuffer); +unsigned long Exynos_OSAL_SharedMemory_VirtToION(OMX_HANDLETYPE handle, OMX_PTR pBuffer); +OMX_PTR Exynos_OSAL_SharedMemory_IONToVirt(OMX_HANDLETYPE handle, unsigned long ionfd); + +OMX_PTR Exynos_OSAL_SharedMemory_Map(OMX_HANDLETYPE handle, OMX_U32 size, unsigned long ionfd); +void Exynos_OSAL_SharedMemory_Unmap(OMX_HANDLETYPE handle, unsigned long ionfd); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/openmax/osal/Exynos_OSAL_SkypeHD.c b/openmax/osal/Exynos_OSAL_SkypeHD.c new file mode 100644 index 0000000..51a360d --- /dev/null +++ b/openmax/osal/Exynos_OSAL_SkypeHD.c @@ -0,0 +1,1020 @@ +/* + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_SkypeHD.cpp + * @brief + * @author Seungbeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2015.04.27 : Create + */ + +#include +#include +#include + +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OMX_Baseport.h" +#include "Exynos_OMX_Basecomponent.h" +#include "Exynos_OMX_Macros.h" +#include "Exynos_OSAL_SkypeHD.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OMX_Def.h" +#include "exynos_format.h" + +#include "ExynosVideoApi.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "Exynos_OSAL_SkypeHD" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +#include "Exynos_OSAL_SkypeHD.h" + +/* ENCODE_ONLY */ +#ifdef BUILD_ENC +#include "Exynos_OMX_Venc.h" +#include "Exynos_OMX_H264enc.h" +#endif + +/* DECODE_ONLY */ +#ifdef BUILD_DEC +#include "Exynos_OMX_Vdec.h" +#include "Exynos_OMX_H264dec.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* ENCODE_ONLY */ +#ifdef BUILD_ENC +/* video enc */ +OMX_ERRORTYPE Exynos_H264Enc_GetParameter_SkypeHD( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + switch ((int)nParamIndex) { + case OMX_IndexSkypeParamDriverVersion: + { + OMX_VIDEO_PARAM_DRIVERVER *pDriverVer = (OMX_VIDEO_PARAM_DRIVERVER *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDriverVer, sizeof(OMX_VIDEO_PARAM_DRIVERVER)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDriverVer->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDriverVer->nDriverVersion = (OMX_U64)(pH264Enc->hMFCH264Handle.videoInstInfo.SwVersion); + } + break; + case OMX_IndexSkypeParamLowLatency: + { + OMX_PARAM_U32TYPE *pLowLatency = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pLowLatency, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pLowLatency->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pLowLatency->nU32 = (pH264Enc->hMFCH264Handle.bLowLatency == OMX_TRUE)? 1:0; + } + break; + case OMX_IndexSkypeParamEncoderMaxTemporalLayerCount: + { + OMX_PARAM_ENC_MAX_TEMPORALLAYER_COUNT *pTemporalLayer = (OMX_PARAM_ENC_MAX_TEMPORALLAYER_COUNT *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pTemporalLayer, sizeof(OMX_PARAM_ENC_MAX_TEMPORALLAYER_COUNT)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pTemporalLayer->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pTemporalLayer->nMaxCountP = OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS; + pTemporalLayer->nMaxCountB = (OMX_VIDEO_MAX_AVC_TEMPORAL_LAYERS - 1); + } + break; + case OMX_IndexSkypeParamEncoderMaxLTR: + { + OMX_PARAM_U32TYPE *pLTR = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pLTR, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pLTR->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pLTR->nU32 = OMX_VIDEO_MAX_LTR_FRAMES; + } + break; + case OMX_IndexSkypeParamEncoderLTR: + { + OMX_PARAM_U32TYPE *pLTR = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pLTR, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pLTR->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pLTR->nU32 = pH264Enc->hMFCH264Handle.nLTRFrames; + } + break; + case OMX_IndexSkypeParamEncoderPreprocess: + { + OMX_PARAM_ENC_PREPROCESS *pPreprocess = (OMX_PARAM_ENC_PREPROCESS *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pPreprocess, sizeof(OMX_PARAM_ENC_PREPROCESS)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pPreprocess->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pPreprocess->nResize = 0; /* 1:1 */ + pPreprocess->nRotation = 0; /* not supported */ + } + break; + case OMX_IndexSkypeParamEncoderSar: + { + OMX_PARAM_ENC_SAR *pSar = (OMX_PARAM_ENC_SAR *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pSar, sizeof(OMX_PARAM_ENC_SAR)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSar->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSar->nWidth = pH264Enc->hMFCH264Handle.stSarParam.SarWidth; + pSar->nHeight = pH264Enc->hMFCH264Handle.stSarParam.SarHeight; + } + break; + case OMX_IndexSkypeParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE *pVideoBitrate = (OMX_VIDEO_PARAM_BITRATETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoBitrate->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pPortDef = &(pExynosComponent->pExynosPort[nPortIndex].portDefinition); + + pVideoBitrate->eControlRate = pVideoEnc->eControlRate[nPortIndex]; + pVideoBitrate->nTargetBitrate = pPortDef->format.video.nBitrate; + } + } + break; + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_SetParameter_SkypeHD( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + switch ((int)nIndex) { + case OMX_IndexSkypeParamLowLatency: + { + OMX_PARAM_U32TYPE *pLowLatency = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pLowLatency, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pLowLatency->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.bLowLatency = (pLowLatency->nU32 == 0)? OMX_FALSE:OMX_TRUE; + } + break; + case OMX_IndexSkypeParamEncoderLTR: + { + OMX_PARAM_U32TYPE *pLTR = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pLTR, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pLTR->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pLTR->nU32 > OMX_VIDEO_MAX_LTR_FRAMES) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.nLTRFrames = pLTR->nU32; + } + break; + case OMX_IndexSkypeParamEncoderSar: + { + OMX_PARAM_ENC_SAR *pSar = (OMX_PARAM_ENC_SAR *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pSar, sizeof(OMX_PARAM_ENC_SAR)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pSar->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.stSarParam.SarEnable = OMX_TRUE; + pH264Enc->hMFCH264Handle.stSarParam.SarIndex = 0xFF; /* depends on width/height info */ + pH264Enc->hMFCH264Handle.stSarParam.SarWidth = pSar->nWidth; + pH264Enc->hMFCH264Handle.stSarParam.SarHeight = pSar->nHeight; + } + break; + case OMX_IndexSkypeParamEncoderInputControl: + { + OMX_PARAM_U32TYPE *pInputControl = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pInputControl, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pInputControl->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (pInputControl->nU32 > 0) { + pH264Enc->hMFCH264Handle.bEnableSkypeHD = OMX_TRUE; + } else { + pH264Enc->hMFCH264Handle.bEnableSkypeHD = OMX_FALSE; + } + } + break; + case OMX_IndexSkypeParamVideoBitrate: + { + OMX_VIDEO_PARAM_BITRATETYPE *pVideoBitrate = (OMX_VIDEO_PARAM_BITRATETYPE *)pComponentParameterStructure; + OMX_U32 nPortIndex = pVideoBitrate->nPortIndex; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + if (nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } else { + pPortDef = &(pExynosComponent->pExynosPort[nPortIndex].portDefinition); + + pVideoEnc->eControlRate[nPortIndex] = pVideoBitrate->eControlRate; + pPortDef->format.video.nBitrate = pVideoBitrate->nTargetBitrate; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "[%p][%s] Bitrate mode is set through vendor extension", + pExynosComponent, __FUNCTION__); + pH264Enc->hMFCH264Handle.bSkypeBitrate = OMX_TRUE; + } + ret = OMX_ErrorNone; + } + break; + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_GetConfig_SkypeHD( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + switch ((int)nIndex) { + case OMX_IndexSkypeConfigBasePid: + { + OMX_VIDEO_CONFIG_BASELAYERPID *pBaseLayerPid = (OMX_VIDEO_CONFIG_BASELAYERPID *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pBaseLayerPid, sizeof(OMX_VIDEO_CONFIG_BASELAYERPID)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pBaseLayerPid->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pBaseLayerPid->nPID = pH264Enc->hMFCH264Handle.nBaseLayerPid; + } + break; + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Enc_SetConfig_SkypeHD( + OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, + OMX_PTR pComponentConfigStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentConfigStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoEnc->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + switch ((int)nIndex) { + case OMX_IndexSkypeConfigMarkLTRFrame: + { + OMX_VIDEO_CONFIG_MARKLTRFRAME *pMarkLTRFrame = (OMX_VIDEO_CONFIG_MARKLTRFRAME *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pMarkLTRFrame, sizeof(OMX_VIDEO_CONFIG_MARKLTRFRAME)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pMarkLTRFrame->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeConfigUseLTRFrame: + { + OMX_VIDEO_CONFIG_USELTRFRAME *pUseLTRFrame = (OMX_VIDEO_CONFIG_USELTRFRAME *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pUseLTRFrame, sizeof(OMX_VIDEO_CONFIG_USELTRFRAME)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pUseLTRFrame->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + } + break; + case OMX_IndexSkypeConfigQP: + { + OMX_VIDEO_CONFIG_QP *pConfigQp = (OMX_VIDEO_CONFIG_QP *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pConfigQp, sizeof(OMX_VIDEO_CONFIG_QP)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pConfigQp->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pVideoEnc->quantization.nQpI = pConfigQp->nQP; + pVideoEnc->quantization.nQpP = pConfigQp->nQP; + pVideoEnc->quantization.nQpB = pConfigQp->nQP; + } + break; + case OMX_IndexSkypeConfigBasePid: + { + OMX_VIDEO_CONFIG_BASELAYERPID *pBaseLayerPid = (OMX_VIDEO_CONFIG_BASELAYERPID *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pBaseLayerPid, sizeof(OMX_VIDEO_CONFIG_BASELAYERPID)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pBaseLayerPid->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.nBaseLayerPid = pBaseLayerPid->nPID; + } + break; + case OMX_IndexSkypeConfigEncoderInputTrigger: + { + OMX_CONFIG_ENC_TRIGGER_TS *pTriggerTS = (OMX_CONFIG_ENC_TRIGGER_TS *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pTriggerTS, sizeof(OMX_CONFIG_ENC_TRIGGER_TS)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pTriggerTS->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + } + break; + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Change_H264Enc_SkypeHDParam( + EXYNOS_OMX_BASECOMPONENT *pExynosComponent, + OMX_PTR pDynamicConfigCMD) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + OMX_PTR pConfigData = NULL; + OMX_S32 nCmdIndex = 0; + ExynosVideoEncOps *pEncOps = NULL; + int nValue = 0; + + int i; + + FunctionIn(); + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncOps = pMFCH264Handle->pEncOps; + + if (pDynamicConfigCMD == NULL) + goto EXIT; + + nCmdIndex = *(OMX_S32 *)pDynamicConfigCMD; + pConfigData = (OMX_PTR)((OMX_U8 *)pDynamicConfigCMD + sizeof(OMX_S32)); + + switch ((int)nCmdIndex) { + case OMX_IndexSkypeConfigMarkLTRFrame: + { + OMX_VIDEO_CONFIG_MARKLTRFRAME *pMarkLTRFrame = (OMX_VIDEO_CONFIG_MARKLTRFRAME *)pConfigData; + + ret = Exynos_OMX_Check_SizeVersion(pMarkLTRFrame, sizeof(OMX_VIDEO_CONFIG_MARKLTRFRAME)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pMarkLTRFrame->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Mark LTR : index(%d)", + pExynosComponent, __FUNCTION__, pMarkLTRFrame->nLongTermFrmIdx + 1); + + pEncOps->Set_MarkLTRFrame(pMFCH264Handle->hMFCHandle, pMarkLTRFrame->nLongTermFrmIdx + 1); + } + break; + case OMX_IndexSkypeConfigUseLTRFrame: + { + OMX_VIDEO_CONFIG_USELTRFRAME *pUseLTRFrame = (OMX_VIDEO_CONFIG_USELTRFRAME *)pConfigData; + + ret = Exynos_OMX_Check_SizeVersion(pUseLTRFrame, sizeof(OMX_VIDEO_CONFIG_USELTRFRAME)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pUseLTRFrame->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Use LTR : BM(%x)", + pExynosComponent, __FUNCTION__, pUseLTRFrame->nUsedLTRFrameBM); + + pEncOps->Set_UsedLTRFrame(pMFCH264Handle->hMFCHandle, pUseLTRFrame->nUsedLTRFrameBM); + } + break; + case OMX_IndexSkypeConfigQP: + { + OMX_VIDEO_CONFIG_QP *pConfigQp = (OMX_VIDEO_CONFIG_QP *)pConfigData; + + ret = Exynos_OMX_Check_SizeVersion(pConfigQp, sizeof(OMX_VIDEO_CONFIG_QP)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pConfigQp->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] QP : %d", pExynosComponent, __FUNCTION__, pConfigQp->nQP); + + pEncOps->Set_DynamicQpControl(pMFCH264Handle->hMFCHandle, pConfigQp->nQP); + } + break; + case OMX_IndexSkypeConfigBasePid: + { + OMX_VIDEO_CONFIG_BASELAYERPID *pBaseLayerPid = (OMX_VIDEO_CONFIG_BASELAYERPID *)pConfigData; + + ret = Exynos_OMX_Check_SizeVersion(pBaseLayerPid, sizeof(OMX_VIDEO_CONFIG_BASELAYERPID)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pBaseLayerPid->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] BasePID : %d", pExynosComponent, __FUNCTION__, pBaseLayerPid->nPID); + + pEncOps->Set_BasePID(pMFCH264Handle->hMFCHandle, pBaseLayerPid->nPID); + } + break; + case OMX_IndexSkypeConfigEncoderInputTrigger: + { + OMX_CONFIG_ENC_TRIGGER_TS *pTriggerTS = (OMX_CONFIG_ENC_TRIGGER_TS *)pConfigData; + EXYNOS_OMX_BASEPORT *pInputPort = &(pExynosComponent->pExynosPort[INPUT_PORT_INDEX]); + + ret = Exynos_OMX_Check_SizeVersion(pTriggerTS, sizeof(OMX_CONFIG_ENC_TRIGGER_TS)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pTriggerTS->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMFCH264Handle->nTriggerTS = pTriggerTS->nTimestamp; + + if (pInputPort->processData.timeStamp == pMFCH264Handle->nTriggerTS) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] input trigger is matched input timestamp : %lld", + pExynosComponent, __FUNCTION__, pTriggerTS->nTimestamp); + ret = OMX_ErrorNoMore; + goto EXIT; + } + + if (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) <= 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] no more input trigger", pExynosComponent, __FUNCTION__); + ret = OMX_ErrorNoMore; + goto EXIT; + } + } + break; + default: + break; + } + +EXIT: + + FunctionOut(); + + return ret; +} +#endif + + +/* DECODE_ONLY */ +#ifdef BUILD_DEC +/* video dec */ +OMX_ERRORTYPE Exynos_H264Dec_GetParameter_SkypeHD( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, + OMX_INOUT OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + FunctionIn(); + + if ((hComponent == NULL) || + (pComponentParameterStructure == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invalid parameter", __FUNCTION__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + + switch ((int)nParamIndex) { + case OMX_IndexSkypeParamDriverVersion: + { + OMX_VIDEO_PARAM_DRIVERVER *pDriverVer = (OMX_VIDEO_PARAM_DRIVERVER *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pDriverVer, sizeof(OMX_VIDEO_PARAM_DRIVERVER)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pDriverVer->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDriverVer->nDriverVersion = (OMX_U64)(pH264Dec->hMFCH264Handle.videoInstInfo.SwVersion); + } + break; + case OMX_IndexSkypeParamLowLatency: + { + OMX_PARAM_U32TYPE *pLowLatency = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pLowLatency, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pLowLatency->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pLowLatency->nU32 = (pH264Dec->hMFCH264Handle.bLowLatency == OMX_TRUE)? 1:0; + } + break; + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_H264Dec_SetParameter_SkypeHD( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR pComponentParameterStructure) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + FunctionIn(); + + if (hComponent == NULL || pComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_Check_SizeVersion(pOMXComponent, sizeof(OMX_COMPONENTTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + if (pOMXComponent->pComponentPrivate == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + if (pExynosComponent->currentState == OMX_StateInvalid) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] invalid state(0x%x)", + pExynosComponent, __FUNCTION__, pExynosComponent->currentState); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (pVideoDec->hCodecHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + + switch ((int)nIndex) { + case OMX_IndexSkypeParamLowLatency: + { + OMX_PARAM_U32TYPE *pLowLatency = (OMX_PARAM_U32TYPE *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion(pLowLatency, sizeof(OMX_PARAM_U32TYPE)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s] Failed to Check_SizeVersion", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (pLowLatency->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pH264Dec->hMFCH264Handle.bLowLatency = (pLowLatency->nU32 == 0)? OMX_FALSE:OMX_TRUE; + } + break; + default: + ret = OMX_ErrorUnsupportedIndex; + break; + + } + +EXIT: + + FunctionOut(); + + return ret; +} +#endif + +#ifdef __cplusplus +} +#endif diff --git a/openmax/osal/Exynos_OSAL_SkypeHD.h b/openmax/osal/Exynos_OSAL_SkypeHD.h new file mode 100644 index 0000000..69e8a01 --- /dev/null +++ b/openmax/osal/Exynos_OSAL_SkypeHD.h @@ -0,0 +1,62 @@ +/* + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_SkypeHD.h + * @brief + * @author Seungbeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2015.04.27 : Create + */ + +#ifndef Exynos_OSAL_SKYPEHD +#define Exynos_OSAL_SKYPEHD + +#include "OMX_Types.h" +#include "OMX_Core.h" +#include "OMX_Index.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef BUILD_ENC +/* ENCODE_ONLY */ +OMX_ERRORTYPE Exynos_H264Enc_GetParameter_SkypeHD(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, OMX_INOUT OMX_PTR pComponentParameterStructure); +OMX_ERRORTYPE Exynos_H264Enc_SetParameter_SkypeHD(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, OMX_IN OMX_PTR pComponentParameterStructure); +OMX_ERRORTYPE Exynos_H264Enc_GetConfig_SkypeHD(OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, OMX_PTR pComponentConfigStructure); +OMX_ERRORTYPE Exynos_H264Enc_SetConfig_SkypeHD(OMX_HANDLETYPE hComponent, + OMX_INDEXTYPE nIndex, OMX_PTR pComponentConfigStructure); +OMX_ERRORTYPE Change_H264Enc_SkypeHDParam(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_PTR pDynamicConfigCMD); +#endif + +#ifdef BUILD_DEC +/* DECODE_ONLY */ +OMX_ERRORTYPE Exynos_H264Dec_GetParameter_SkypeHD(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nParamIndex, OMX_INOUT OMX_PTR pComponentParameterStructure); +OMX_ERRORTYPE Exynos_H264Dec_SetParameter_SkypeHD(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, OMX_IN OMX_PTR pComponentParameterStructure); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/osal/Exynos_OSAL_Thread.c b/openmax/osal/Exynos_OSAL_Thread.c new file mode 100644 index 0000000..617e94a --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Thread.c @@ -0,0 +1,184 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Thread.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Exynos_OSAL_Memory.h" +#include "Exynos_OSAL_Thread.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_LOG_THREAD" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + + +typedef struct _EXYNOS_THREAD_HANDLE_TYPE +{ + pthread_t pthread; + pthread_attr_t attr; + struct sched_param schedparam; + int stack_size; +} EXYNOS_THREAD_HANDLE_TYPE; + + +OMX_ERRORTYPE Exynos_OSAL_ThreadCreate(OMX_HANDLETYPE *threadHandle, OMX_PTR function_name, OMX_PTR argument) +{ + FunctionIn(); + + int result = 0; + int detach_ret = 0; + EXYNOS_THREAD_HANDLE_TYPE *thread; + OMX_ERRORTYPE ret = OMX_ErrorNone; + + thread = Exynos_OSAL_Malloc(sizeof(EXYNOS_THREAD_HANDLE_TYPE)); + if (thread == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Memset(thread, 0, sizeof(EXYNOS_THREAD_HANDLE_TYPE)); + + pthread_attr_init(&thread->attr); + if (thread->stack_size != 0) + pthread_attr_setstacksize(&thread->attr, thread->stack_size); + + /* set priority */ + if (thread->schedparam.sched_priority != 0) + pthread_attr_setschedparam(&thread->attr, &thread->schedparam); + + detach_ret = pthread_attr_setdetachstate(&thread->attr, PTHREAD_CREATE_JOINABLE); + if (detach_ret != 0) { + Exynos_OSAL_Free(thread); + *threadHandle = NULL; + ret = OMX_ErrorUndefined; + goto EXIT; + } + + result = pthread_create(&thread->pthread, &thread->attr, function_name, (void *)argument); + /* pthread_setschedparam(thread->pthread, SCHED_RR, &thread->schedparam); */ + + switch (result) { + case 0: + *threadHandle = (OMX_HANDLETYPE)thread; + ret = OMX_ErrorNone; + break; + case EAGAIN: + Exynos_OSAL_Free(thread); + *threadHandle = NULL; + ret = OMX_ErrorInsufficientResources; + break; + default: + Exynos_OSAL_Free(thread); + *threadHandle = NULL; + ret = OMX_ErrorUndefined; + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_ThreadTerminate(OMX_HANDLETYPE threadHandle) +{ + FunctionIn(); + + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_THREAD_HANDLE_TYPE *thread = (EXYNOS_THREAD_HANDLE_TYPE *)threadHandle; + + if (!thread) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pthread_join(thread->pthread, NULL) != 0) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + Exynos_OSAL_Free(thread); + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_ThreadDetach(OMX_HANDLETYPE threadHandle) +{ + EXYNOS_THREAD_HANDLE_TYPE *thread = (EXYNOS_THREAD_HANDLE_TYPE *)threadHandle; + + if (!thread) + return OMX_ErrorBadParameter; + + if (pthread_detach(thread->pthread) != 0) + return OMX_ErrorUndefined; + + Exynos_OSAL_Free(thread); + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE Exynos_OSAL_ThreadCancel(OMX_HANDLETYPE threadHandle) +{ + EXYNOS_THREAD_HANDLE_TYPE *thread = (EXYNOS_THREAD_HANDLE_TYPE *)threadHandle; + + if (!thread) + return OMX_ErrorBadParameter; + + /* android doesn't support this function */ + //pthread_cancel(thread->pthread); + + Exynos_OSAL_Free(thread); + return OMX_ErrorNone; +} + +void Exynos_OSAL_ThreadExit(void *value_ptr) +{ + pthread_exit(value_ptr); + return; +} + +void Exynos_OSAL_SleepMillisec(OMX_U32 ms) +{ + if (ms == 0) { + sched_yield(); + } else { + struct timespec time; + time.tv_sec = (time_t)(ms / 1000); + time.tv_nsec = (long)(ms % 1000) * 1000000; + nanosleep(&time, NULL); + } + return; +} diff --git a/openmax/osal/Exynos_OSAL_Thread.h b/openmax/osal/Exynos_OSAL_Thread.h new file mode 100644 index 0000000..856797d --- /dev/null +++ b/openmax/osal/Exynos_OSAL_Thread.h @@ -0,0 +1,49 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file Exynos_OSAL_Thread.h + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#ifndef Exynos_OSAL_THREAD +#define Exynos_OSAL_THREAD + +#include "OMX_Types.h" +#include "OMX_Core.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OSAL_ThreadCreate(OMX_HANDLETYPE *threadHandle, OMX_PTR function_name, OMX_PTR argument); +OMX_ERRORTYPE Exynos_OSAL_ThreadTerminate(OMX_HANDLETYPE threadHandle); +OMX_ERRORTYPE Exynos_OSAL_ThreadDetach(OMX_HANDLETYPE threadHandle); +OMX_ERRORTYPE Exynos_OSAL_ThreadCancel(OMX_HANDLETYPE threadHandle); +void Exynos_OSAL_ThreadExit(void *value_ptr); +void Exynos_OSAL_SleepMillisec(OMX_U32 ms); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/openmax/osal/NOTICE b/openmax/osal/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/openmax/osal/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/videocodec/Android.mk b/videocodec/Android.mk new file mode 100644 index 0000000..a1a97a0 --- /dev/null +++ b/videocodec/Android.mk @@ -0,0 +1,74 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + ExynosVideoInterface.c \ + osal/ExynosVideo_OSAL.c \ + dec/ExynosVideoDecoder.c \ + enc/ExynosVideoEncoder.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH)/include \ + $(LOCAL_PATH)/osal/include \ + $(TOP)/hardware/samsung_slsi/exynos/include \ + +LOCAL_SHARED_LIBRARIES := libion_exynos + +LOCAL_SHARED_LIBRARIES += liblog + +ifeq ($(BOARD_USE_KHRONOS_OMX_HEADER), true) +LOCAL_C_INCLUDES += $(TOP)/hardware/samsung_slsi/openmax/include/khronos +else +LOCAL_HEADER_LIBRARIES := media_plugin_headers +endif + +LOCAL_CFLAGS := +LOCAL_PROPRIETARY_MODULE := true + +# only 3.4 kernel +ifeq ($(filter-out 3.4, $(TARGET_LINUX_KERNEL_VERSION)),) +LOCAL_CFLAGS += -DUSE_EXYNOS_MEDIA_EXT +endif + +# since 3.10 kernel +ifneq ($(filter-out 3.4, $(TARGET_LINUX_KERNEL_VERSION)),) +LOCAL_CFLAGS += -DUSE_DEFINE_H264_SEI_TYPE +endif + +# since 3.18 kernel +ifneq ($(filter-out 3.4 3.10, $(TARGET_LINUX_KERNEL_VERSION)),) +LOCAL_C_INCLUDES += $(LOCAL_PATH)/mfc_headers +LOCAL_CFLAGS += -DUSE_ORIGINAL_HEADER +LOCAL_CFLAGS += -DUSE_MFC_HEADER +endif + +# since 4.19 kernel +ifneq ($(filter 4.19 5.4, $(TARGET_LINUX_KERNEL_VERSION)),) +LOCAL_CFLAGS += -DMAINLINE_FEATURE_IN_SINCE_4_19 +endif + +ifeq ($(BOARD_USE_HEVC_HWIP), true) +LOCAL_CFLAGS += -DUSE_HEVC_HWIP +endif + +ifeq ($(BOARD_USE_DEINTERLACING_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_DEINTERLACING_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PALNE_SUPPORT +endif + +ifneq ($(BOARD_USE_FRAMERATE_THRESH_HOLD),) +LOCAL_CFLAGS += -DFRAMERATE_THRESH_HOLD=$(BOARD_USE_FRAMERATE_THRESH_HOLD) +endif + +LOCAL_MODULE := libExynosVideoApi +LOCAL_MODULE_TAGS := optional +LOCAL_PRELINK_MODULE := false +LOCAL_ARM_MODE := arm + +LOCAL_CFLAGS += -Wno-unused-variable -Wno-unused-label -Wno-unused-function + +include $(BUILD_STATIC_LIBRARY) diff --git a/videocodec/ExynosVideoInterface.c b/videocodec/ExynosVideoInterface.c new file mode 100644 index 0000000..8cdb9ed --- /dev/null +++ b/videocodec/ExynosVideoInterface.c @@ -0,0 +1,119 @@ +/* + * Copyright 2013 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file ExynosVideoInterface.c + * @brief + * @author Satish Kumar Reddy (palli.satish@samsung.com) + * @version 1.0 + * @history + * 2013.08.14 : Initial versaion + */ + +#include +#include +#include +#include + +#include "ExynosVideoApi.h" +#include "ExynosVideoDec.h" +#include "ExynosVideoEnc.h" + +/* #define LOG_NDEBUG 0 */ +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "ExynosVideoInterface" + +ExynosVideoErrorType Exynos_Video_GetInstInfo( + ExynosVideoInstInfo *pVideoInstInfo, + ExynosVideoBoolType bIsDec) +{ + if (bIsDec == VIDEO_TRUE) + return MFC_Exynos_Video_GetInstInfo_Decoder(pVideoInstInfo); + else + return MFC_Exynos_Video_GetInstInfo_Encoder(pVideoInstInfo); +} + +int Exynos_Video_Register_Decoder( + ExynosVideoDecOps *pDecOps, + ExynosVideoDecBufferOps *pInbufOps, + ExynosVideoDecBufferOps *pOutbufOps) +{ + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + ret = MFC_Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps); + +EXIT: + return ret; +} + +int Exynos_Video_Register_Encoder( + ExynosVideoEncOps *pEncOps, + ExynosVideoEncBufferOps *pInbufOps, + ExynosVideoEncBufferOps *pOutbufOps) +{ + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if ((pEncOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + ret = MFC_Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps); + +EXIT: + return ret; +} + +void Exynos_Video_Unregister_Decoder( + ExynosVideoDecOps *pDecOps, + ExynosVideoDecBufferOps *pInbufOps, + ExynosVideoDecBufferOps *pOutbufOps) +{ + if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + goto EXIT; + } + + memset(pDecOps, 0, sizeof(ExynosVideoDecOps)); + memset(pInbufOps, 0, sizeof(ExynosVideoDecBufferOps)); + memset(pOutbufOps, 0, sizeof(ExynosVideoDecBufferOps)); + +EXIT: + return; +} + +void Exynos_Video_Unregister_Encoder( + ExynosVideoEncOps *pEncOps, + ExynosVideoEncBufferOps *pInbufOps, + ExynosVideoEncBufferOps *pOutbufOps) +{ + if ((pEncOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + goto EXIT; + } + + memset(pEncOps, 0, sizeof(ExynosVideoEncOps)); + memset(pInbufOps, 0, sizeof(ExynosVideoEncBufferOps)); + memset(pOutbufOps, 0, sizeof(ExynosVideoEncBufferOps)); + +EXIT: + return; +} diff --git a/videocodec/NOTICE b/videocodec/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/videocodec/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2014, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/videocodec/dec/ExynosVideoDecoder.c b/videocodec/dec/ExynosVideoDecoder.c new file mode 100644 index 0000000..e7fd417 --- /dev/null +++ b/videocodec/dec/ExynosVideoDecoder.c @@ -0,0 +1,3457 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file ExynosVideoDecoder.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.01.15: Initial Version + * 2016.01.28: Update Version to support OSAL + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "ExynosVideoApi.h" +#include "ExynosVideoDec.h" +#include "ExynosVideo_OSAL_Dec.h" +#include "OMX_Core.h" + +/* #define LOG_NDEBUG 0 */ +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "ExynosVideoDecoder" + +#define MAX_INPUTBUFFER_COUNT 32 +#define MAX_OUTPUTBUFFER_COUNT 32 + +#define HAS_HDR_DYNAMIC_INFO 0x40 +#define HAS_HDR_STATIC_INFO 0x3 +#define HAS_COLOR_ASPECTS_INFO 0x1C +#define HAS_HDR_INFO (HAS_COLOR_ASPECTS_INFO | HAS_HDR_STATIC_INFO | HAS_HDR_DYNAMIC_INFO) +#define HAS_BLACK_BAR_CROP_INFO 0x20 +#define HAS_UNCOMP_DATA 0x100 +#define HAS_INTER_RESOLUTION_CHANGE 0x80 +#define HAS_ACTUAL_FRAMERATE 0x200 + +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +/* + * [Common] __Set_SupportFormat + */ +static void __Set_SupportFormat(ExynosVideoInstInfo *pVideoInstInfo) +{ + int nLastIndex = 0; + + if (pVideoInstInfo == NULL) { + ALOGE("%s: ExynosVideoInstInfo must be supplied", __FUNCTION__); + goto EXIT; + } + + memset(pVideoInstInfo->supportFormat, (int)VIDEO_COLORFORMAT_UNKNOWN, + sizeof(pVideoInstInfo->supportFormat)); + +#ifdef USE_HEVC_HWIP + if (pVideoInstInfo->eCodecType == VIDEO_CODING_HEVC) { + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_YV12M; + goto EXIT; + } +#endif + + switch (pVideoInstInfo->HwVersion) { + case MFC_1501: + case MFC_150: + case MFC_1410: /* NV12, NV21, I420, YV12, NV12_10B, NV21_10B, SBWC(NV12, NV21, NV12_10B, NV21_10B) */ + case MFC_1400: + case MFC_140: + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_YV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_SBWC; + + if ((pVideoInstInfo->eCodecType == VIDEO_CODING_HEVC) || + (pVideoInstInfo->eCodecType == VIDEO_CODING_VP9)) { + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_P010; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_P010; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_10B_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_10B_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_10B_SBWC; + } + break; + case MFC_130: /* NV12, NV21, I420, YV12, NV12_10B, NV21_10B */ + case MFC_120: + case MFC_1220: + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_YV12M; + + if ((pVideoInstInfo->eCodecType == VIDEO_CODING_HEVC) || + (pVideoInstInfo->eCodecType == VIDEO_CODING_VP9)) { + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_P010; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_P010; + } + break; + case MFC_110: /* NV12, NV21, I420, YV12 */ + case MFC_1120: + case MFC_101: + case MFC_100: + case MFC_1010: + case MFC_1011: + case MFC_90: + case MFC_80: + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_YV12M; + break; + case MFC_92: /* NV12, NV21 */ + case MFC_78D: + case MFC_1020: + case MFC_1021: + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M; + break; + case MFC_723: /* NV12T, [NV12, NV21, I420, YV12] */ + case MFC_72: + case MFC_77: +#if 0 + if (pVideoInstInfo->supportInfo.dec.bDualDPBSupport == VIDEO_TRUE) { + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_YV12M; + } +#endif + case MFC_78: /* NV12T */ + case MFC_65: + case MFC_61: + case MFC_51: + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_TILED; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_TILED; + break; + default: + break; + } + +EXIT: + return; +} + +/* + * [Decoder OPS] Init + */ +static void *MFC_Decoder_Init(ExynosVideoInstInfo *pVideoInfo) +{ + CodecOSALVideoContext *pCtx = NULL; + pthread_mutex_t *pMutex = NULL; + + int ret = 0; + int hIonClient = -1; + int fd = -1; + + if (pVideoInfo == NULL) { + ALOGE("%s: bad parameter", __FUNCTION__); + goto EXIT_ALLOC_FAIL; + } + + pCtx = (CodecOSALVideoContext *)malloc(sizeof(CodecOSALVideoContext)); + if (pCtx == NULL) { + ALOGE("%s: Failed to allocate decoder context buffer", __FUNCTION__); + goto EXIT_ALLOC_FAIL; + } + memset(pCtx, 0, sizeof(*pCtx)); + + pCtx->videoCtx.hDevice = -1; + pCtx->videoCtx.hIONHandle = -1; + pCtx->videoCtx.specificInfo.dec.nPrivateDataShareFD = -1; + pCtx->videoCtx.specificInfo.dec.nHDRInfoShareBufferFD = -1; + + /* node open */ +#ifdef USE_HEVC_HWIP + if (pVideoInfo->eCodecType == VIDEO_CODING_HEVC) { + if (pVideoInfo->eSecurityType == VIDEO_SECURE) + ret = Codec_OSAL_DevOpen(VIDEO_HEVC_SECURE_DECODER_NAME, O_RDWR, pCtx); + else + ret = Codec_OSAL_DevOpen(VIDEO_HEVC_DECODER_NAME, O_RDWR, pCtx); + } else +#endif + { + if (pVideoInfo->eSecurityType == VIDEO_SECURE) + ret = Codec_OSAL_DevOpen(VIDEO_MFC_SECURE_DECODER_NAME, O_RDWR, pCtx); + else + ret = Codec_OSAL_DevOpen(VIDEO_MFC_DECODER_NAME, O_RDWR, pCtx); + } + + if (ret < 0) { + ALOGE("%s: Failed to open decoder device", __FUNCTION__); + goto EXIT_OPEN_FAIL; + } + + memcpy(&pCtx->videoCtx.instInfo, pVideoInfo, sizeof(*pVideoInfo)); + + ALOGV("%s: HW version is %x", __FUNCTION__, pCtx->videoCtx.instInfo.HwVersion); + + if (Codec_OSAL_QueryCap(pCtx) != 0) { + ALOGE("%s: Failed to querycap", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + + pCtx->videoCtx.bStreamonInbuf = VIDEO_FALSE; + pCtx->videoCtx.bStreamonOutbuf = VIDEO_FALSE; + + /* mutex for input */ + pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + if (pMutex == NULL) { + ALOGE("%s: Failed to allocate mutex for input buffer", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + + if (pthread_mutex_init(pMutex, NULL) != 0) { + free(pMutex); + goto EXIT_QUERYCAP_FAIL; + } + pCtx->videoCtx.pInMutex = (void*)pMutex; + + /* mutex for output */ + pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + if (pMutex == NULL) { + ALOGE("%s: Failed to allocate mutex for output buffer", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + + if (pthread_mutex_init(pMutex, NULL) != 0) { + free(pMutex); + goto EXIT_QUERYCAP_FAIL; + } + pCtx->videoCtx.pOutMutex = (void*)pMutex; + + /* for shared memory : referenced DPB handling */ + hIonClient = (long)exynos_ion_open(); + + if (hIonClient < 0) { + ALOGE("%s: Failed to create ion_client", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + + pCtx->videoCtx.hIONHandle = hIonClient; + + /* for DPB ref. count */ + if (pCtx->videoCtx.instInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) { + fd = exynos_ion_alloc(pCtx->videoCtx.hIONHandle, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM, + EXYNOS_ION_HEAP_SYSTEM_MASK, ION_FLAG_CACHED); + if (fd < 0) { + ALOGE("%s: Failed to exynos_ion_alloc() for nPrivateDataShareFD", __FUNCTION__); + pCtx->videoCtx.specificInfo.dec.nPrivateDataShareFD = -1; + goto EXIT_QUERYCAP_FAIL; + } + + pCtx->videoCtx.specificInfo.dec.nPrivateDataShareFD = fd; + + pCtx->videoCtx.specificInfo.dec.pPrivateDataShareAddress = + Codec_OSAL_MemoryMap(NULL, (sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM), + PROT_READ | PROT_WRITE, MAP_SHARED, + pCtx->videoCtx.specificInfo.dec.nPrivateDataShareFD, 0); + if (pCtx->videoCtx.specificInfo.dec.pPrivateDataShareAddress == MAP_FAILED) { + ALOGE("%s: Failed to mmap for pPrivateDataShareAddress", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + + memset(pCtx->videoCtx.specificInfo.dec.pPrivateDataShareAddress, + 0, sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM); + } + + /* for HDR Dynamic Info */ + if (pCtx->videoCtx.instInfo.supportInfo.dec.bHDRDynamicInfoSupport == VIDEO_TRUE) { + fd = exynos_ion_alloc(pCtx->videoCtx.hIONHandle, sizeof(ExynosVideoHdrDynamic) * VIDEO_BUFFER_MAX_NUM, + EXYNOS_ION_HEAP_SYSTEM_MASK, ION_FLAG_CACHED); + if (fd < 0) { + ALOGE("[%s] Failed to exynos_ion_alloc() for pHDRInfoShareBufferFD", __FUNCTION__); + pCtx->videoCtx.specificInfo.dec.nHDRInfoShareBufferFD = -1; + goto EXIT_QUERYCAP_FAIL; + } + + pCtx->videoCtx.specificInfo.dec.nHDRInfoShareBufferFD = fd; + + pCtx->videoCtx.specificInfo.dec.pHDRInfoShareBufferAddr = + Codec_OSAL_MemoryMap(NULL, (sizeof(ExynosVideoHdrDynamic) * VIDEO_BUFFER_MAX_NUM), + PROT_READ | PROT_WRITE, MAP_SHARED, + pCtx->videoCtx.specificInfo.dec.nHDRInfoShareBufferFD, 0); + if (pCtx->videoCtx.specificInfo.dec.pHDRInfoShareBufferAddr == MAP_FAILED) { + ALOGE("[%s] Failed to Codec_OSAL_MemoryMap() for pHDRInfoShareBufferAddr", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + + memset(pCtx->videoCtx.specificInfo.dec.pHDRInfoShareBufferAddr, + 0, sizeof(ExynosVideoHdrDynamic) * VIDEO_BUFFER_MAX_NUM); + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_SET_HDR_USER_SHARED_HANDLE, + pCtx->videoCtx.specificInfo.dec.nHDRInfoShareBufferFD) != 0) { + ALOGE("[%s] Failed to Codec_OSAL_SetControl(CODEC_OSAL_CID_VIDEO_SET_HDR_USER_SHARED_HANDLE)", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + } + + if (pCtx->videoCtx.instInfo.bVideoBufFlagCtrl == VIDEO_TRUE) { + pCtx->videoCtx.bVideoBufFlagCtrl = VIDEO_TRUE; + } + + return (void *)pCtx; + +EXIT_QUERYCAP_FAIL: + if (pCtx->videoCtx.pInMutex != NULL) { + pthread_mutex_destroy(pCtx->videoCtx.pInMutex); + free(pCtx->videoCtx.pInMutex); + } + + if (pCtx->videoCtx.pOutMutex != NULL) { + pthread_mutex_destroy(pCtx->videoCtx.pOutMutex); + free(pCtx->videoCtx.pOutMutex); + } + + if (pCtx->videoCtx.instInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) { + if (pCtx->videoCtx.specificInfo.dec.pPrivateDataShareAddress != NULL) { + Codec_OSAL_MemoryUnmap(pCtx->videoCtx.specificInfo.dec.pPrivateDataShareAddress, + sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM); + pCtx->videoCtx.specificInfo.dec.pPrivateDataShareAddress = NULL; + } + + /* free a ion_buffer */ + if (pCtx->videoCtx.specificInfo.dec.nPrivateDataShareFD >= 0) { + close(pCtx->videoCtx.specificInfo.dec.nPrivateDataShareFD); + pCtx->videoCtx.specificInfo.dec.nPrivateDataShareFD = -1; + } + } + + if (pCtx->videoCtx.instInfo.supportInfo.dec.bHDRDynamicInfoSupport == VIDEO_TRUE) { + if (pCtx->videoCtx.specificInfo.dec.pHDRInfoShareBufferAddr != NULL) { + Codec_OSAL_MemoryUnmap(pCtx->videoCtx.specificInfo.dec.pHDRInfoShareBufferAddr, + sizeof(ExynosVideoHdrDynamic) * VIDEO_BUFFER_MAX_NUM); + pCtx->videoCtx.specificInfo.dec.pHDRInfoShareBufferAddr = NULL; + } + + /* free a ion_buffer */ + if (pCtx->videoCtx.specificInfo.dec.nHDRInfoShareBufferFD >= 0) { + close(pCtx->videoCtx.specificInfo.dec.nHDRInfoShareBufferFD); + pCtx->videoCtx.specificInfo.dec.nHDRInfoShareBufferFD = -1; + } + } + + /* free a ion_client */ + if (pCtx->videoCtx.hIONHandle >= 0) { + exynos_ion_close(pCtx->videoCtx.hIONHandle); + pCtx->videoCtx.hIONHandle = -1; + } + + Codec_OSAL_DevClose(pCtx); + +EXIT_OPEN_FAIL: + free(pCtx); + +EXIT_ALLOC_FAIL: + return NULL; +} + +/* + * [Decoder OPS] Finalize + */ +static ExynosVideoErrorType MFC_Decoder_Finalize(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoPlane *pVideoPlane = NULL; + pthread_mutex_t *pMutex = NULL; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i, j; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.instInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) { + if (pCtx->videoCtx.specificInfo.dec.pPrivateDataShareAddress != NULL) { + Codec_OSAL_MemoryUnmap(pCtx->videoCtx.specificInfo.dec.pPrivateDataShareAddress, + sizeof(PrivateDataShareBuffer) * VIDEO_BUFFER_MAX_NUM); + pCtx->videoCtx.specificInfo.dec.pPrivateDataShareAddress = NULL; + } + + /* free a ion_buffer */ + if (pCtx->videoCtx.specificInfo.dec.nPrivateDataShareFD >= 0) { + close(pCtx->videoCtx.specificInfo.dec.nPrivateDataShareFD); + pCtx->videoCtx.specificInfo.dec.nPrivateDataShareFD = -1; + } + } + + if (pCtx->videoCtx.instInfo.supportInfo.dec.bHDRDynamicInfoSupport == VIDEO_TRUE) { + if (pCtx->videoCtx.specificInfo.dec.pHDRInfoShareBufferAddr != NULL) { + Codec_OSAL_MemoryUnmap(pCtx->videoCtx.specificInfo.dec.pHDRInfoShareBufferAddr, + sizeof(ExynosVideoHdrDynamic) * VIDEO_BUFFER_MAX_NUM); + pCtx->videoCtx.specificInfo.dec.pHDRInfoShareBufferAddr = NULL; + } + + /* free a ion_buffer */ + if (pCtx->videoCtx.specificInfo.dec.nHDRInfoShareBufferFD >= 0) { + close(pCtx->videoCtx.specificInfo.dec.nHDRInfoShareBufferFD); + pCtx->videoCtx.specificInfo.dec.nHDRInfoShareBufferFD = -1; + } + } + + /* free a ion_client */ + if (pCtx->videoCtx.hIONHandle >= 0) { + exynos_ion_close(pCtx->videoCtx.hIONHandle); + pCtx->videoCtx.hIONHandle = -1; + } + + if (pCtx->videoCtx.pOutMutex != NULL) { + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pOutMutex; + pthread_mutex_destroy(pMutex); + free(pMutex); + pCtx->videoCtx.pOutMutex = NULL; + } + + if (pCtx->videoCtx.pInMutex != NULL) { + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pInMutex; + pthread_mutex_destroy(pMutex); + free(pMutex); + pCtx->videoCtx.pInMutex = NULL; + } + + if (pCtx->videoCtx.bShareInbuf == VIDEO_FALSE) { + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + for (j = 0; j < pCtx->videoCtx.nInbufPlanes; j++) { + pVideoPlane = &pCtx->videoCtx.pInbuf[i].planes[j]; + if (pVideoPlane->addr != NULL) { + Codec_OSAL_MemoryUnmap(pVideoPlane->addr, pVideoPlane->allocSize); + pVideoPlane->addr = NULL; + pVideoPlane->allocSize = 0; + pVideoPlane->dataSize = 0; + } + + pCtx->videoCtx.pInbuf[i].pGeometry = NULL; + pCtx->videoCtx.pInbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pInbuf[i].bRegistered = VIDEO_FALSE; + } + } + } + + if (pCtx->videoCtx.bShareOutbuf == VIDEO_FALSE) { + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + for (j = 0; j < pCtx->videoCtx.nOutbufPlanes; j++) { + pVideoPlane = &pCtx->videoCtx.pOutbuf[i].planes[j]; + if (pVideoPlane->addr != NULL) { + Codec_OSAL_MemoryUnmap(pVideoPlane->addr, pVideoPlane->allocSize); + pVideoPlane->addr = NULL; + pVideoPlane->allocSize = 0; + pVideoPlane->dataSize = 0; + } + + pCtx->videoCtx.pOutbuf[i].pGeometry = NULL; + pCtx->videoCtx.pOutbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pOutbuf[i].bRegistered = VIDEO_FALSE; + } + } + } + + if (pCtx->videoCtx.pInbuf != NULL) + free(pCtx->videoCtx.pInbuf); + + if (pCtx->videoCtx.pOutbuf != NULL) + free(pCtx->videoCtx.pOutbuf); + + Codec_OSAL_DevClose(pCtx); + + free(pCtx); + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Set Frame Tag + */ +static ExynosVideoErrorType MFC_Decoder_Set_FrameTag( + void *pHandle, + int nFrameTag) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_FRAME_TAG, nFrameTag) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Get Frame Tag + */ +static int MFC_Decoder_Get_FrameTag(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int nFrameTag = -1; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + goto EXIT; + } + + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_VIDEO_FRAME_TAG, &nFrameTag); + +EXIT: + return nFrameTag; +} + +/* + * [Decoder OPS] Get Buffer Count + */ +static int MFC_Decoder_Get_ActualBufferCount(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int bufferCount = 0; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + goto EXIT; + } + + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_DEC_NUM_MIN_BUFFERS, &bufferCount); + +EXIT: + return bufferCount; +} + +/* + * [Decoder OPS] Set Display Delay + */ +static ExynosVideoErrorType MFC_Decoder_Set_DisplayDelay( + void *pHandle, + int nDelay) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_DISPLAY_DELAY, nDelay) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Set Immediate Display + */ +static ExynosVideoErrorType MFC_Decoder_Set_ImmediateDisplay(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_IMMEDIATE_DISPLAY, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Set I-Frame Decoding + */ +static ExynosVideoErrorType MFC_Decoder_Set_IFrameDecoding(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + +#ifdef USE_HEVC_HWIP + if ((pCtx->videoCtx.instInfo.eCodecType != VIDEO_CODING_HEVC) && + (pCtx->videoCtx.instInfo.HwVersion == (int)MFC_51)) +#else + if (pCtx->videoCtx.instInfo.HwVersion == (int)MFC_51) +#endif + return MFC_Decoder_Set_DisplayDelay(pHandle, 0); + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_I_FRAME_DECODING, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Enable Packed PB + */ +static ExynosVideoErrorType MFC_Decoder_Enable_PackedPB(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_PACKED_PB, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Enable Loop Filter + */ +static ExynosVideoErrorType MFC_Decoder_Enable_LoopFilter(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_DEBLOCK_FILTER, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Enable Slice Mode + */ +static ExynosVideoErrorType MFC_Decoder_Enable_SliceMode(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_SLICE_MODE, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Enable SEI Parsing + */ +static ExynosVideoErrorType MFC_Decoder_Enable_SEIParsing(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_SEI_PARSING, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Get Frame Packing information + */ +static ExynosVideoErrorType MFC_Decoder_Get_FramePackingInfo( + void *pHandle, + ExynosVideoFramePacking *pFramePacking) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if ((pCtx == NULL) || (pFramePacking == NULL)) { + ALOGE("%s: Video context info or FramePacking pointer must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_GetControls(pCtx, CODEC_OSAL_CID_DEC_SEI_INFO, (void *)pFramePacking) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Enable Decoding Timestamp Mode + */ +static ExynosVideoErrorType MFC_Decoder_Enable_DTSMode(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_DTS_MODE, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Set Qos Ratio + */ +static ExynosVideoErrorType MFC_Decoder_Set_QosRatio( + void *pHandle, + int nRatio) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_QOS_RATIO, nRatio) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Enable Dual DPB Mode + */ +static ExynosVideoErrorType MFC_Decoder_Enable_DualDPBMode(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_DUAL_DPB_MODE, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Enable Dynamic DPB + */ +static ExynosVideoErrorType MFC_Decoder_Enable_DynamicDPB(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_DYNAMIC_DPB_MODE, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_SET_USER_SHARED_HANDLE, + pCtx->videoCtx.specificInfo.dec.nPrivateDataShareFD) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Enable Discard RCV header + */ +static ExynosVideoErrorType MFC_Decoder_Enable_DiscardRcvHeader(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + +#if 0 // TODO + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_DISCARD_RCVHEADER, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } +#else + ALOGW("%s: not implemented yet", __FUNCTION__); +#endif + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Get HDR Info + */ +static ExynosVideoErrorType MFC_Decoder_Get_HDRInfo(void *pHandle, ExynosVideoHdrInfo *pHdrInfo) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if ((pCtx == NULL) || + (pHdrInfo == NULL)) { + ALOGE("%s: Video context info or HDR Info pointer must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + /* get Color Aspects and HDR Static Info + * in case of HDR Dynamic Info is already updated at dqbuf */ + if (pCtx->videoCtx.outbufGeometry.HdrInfo.eValidType & ~HDR_INFO_DYNAMIC_META) { + if (Codec_OSAL_GetControls(pCtx, CODEC_OSAL_CID_DEC_HDR_INFO, + (void *)&(pCtx->videoCtx.outbufGeometry.HdrInfo)) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + } + + memcpy(pHdrInfo, &(pCtx->videoCtx.outbufGeometry.HdrInfo), sizeof(ExynosVideoHdrInfo)); + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Set Search Black Bar + */ +static ExynosVideoErrorType MFC_Decoder_Set_SearchBlackBar(void *pHandle, ExynosVideoBoolType bUse) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_SEARCH_BLACK_BAR, bUse) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Get Actual Format + */ +static int MFC_Decoder_Get_ActualFormat(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoColorFormatType nVideoFormat = VIDEO_COLORFORMAT_UNKNOWN; + int nV4l2Format = 0; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + goto EXIT; + } + + if (Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_DEC_ACTUAL_FORMAT, &nV4l2Format) != 0) { + ALOGE("%s: Get extra format is failed", __FUNCTION__); + goto EXIT; + } + + nVideoFormat = Codec_OSAL_PixelFormatToColorFormat((unsigned int)nV4l2Format); + +EXIT: + return nVideoFormat; +} + +/* + * [Decoder OPS] Get Actual Framerate + */ +static int MFC_Decoder_Get_ActualFramerate(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int nFrameRate = -1; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + goto EXIT; + } + + if (Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_ACTUAL_FRAMERATE, &nFrameRate) != 0) { + ALOGW("%s: Get Actual frame rate is failed", __FUNCTION__); + goto EXIT; + } + +EXIT: + return nFrameRate; +} + +/* + * [Decoder OPS] Set Operating Rate + */ +static ExynosVideoErrorType MFC_Decoder_Set_OperatingRate( + void *pHandle, + unsigned int framerate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.instInfo.supportInfo.dec.bOperatingRateSupport != VIDEO_TRUE) { + ret = VIDEO_ERROR_NOSUPPORT; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ACTUAL_FRAMERATE, framerate) != 0) { + ALOGE("%s: Failed to set operating rate", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Set Priority + */ +static ExynosVideoErrorType MFC_Decoder_Set_Priority( + void *pHandle, + unsigned int priority) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.instInfo.supportInfo.dec.bPrioritySupport != VIDEO_TRUE) { + ret = VIDEO_ERROR_NOSUPPORT; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_PRIOTIY, priority) != 0) { + ALOGE("%s: Failed to set priority", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Enable Cacheable (Input) + */ +static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_CACHEABLE_BUFFER, 2) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Enable Cacheable (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Enable_Cacheable_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_CACHEABLE_BUFFER, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Set Shareable Buffer (Input) + */ +static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + pCtx->videoCtx.bShareInbuf = VIDEO_TRUE; + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Set Shareable Buffer (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Set_Shareable_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + pCtx->videoCtx.bShareOutbuf = VIDEO_TRUE; + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Get Buffer (Input) + */ +static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Inbuf( + void *pHandle, + int nIndex, + ExynosVideoBuffer **pBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + *pBuffer = NULL; + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if ((nIndex < 0) || + (pCtx->videoCtx.nInbufs <= nIndex)) { + *pBuffer = NULL; + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + *pBuffer = (ExynosVideoBuffer *)&pCtx->videoCtx.pInbuf[nIndex]; + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Get Buffer (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Get_Buffer_Outbuf( + void *pHandle, + int nIndex, + ExynosVideoBuffer **pBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + *pBuffer = NULL; + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if ((nIndex < 0) || + (pCtx->videoCtx.nOutbufs <= nIndex)) { + *pBuffer = NULL; + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + *pBuffer = (ExynosVideoBuffer *)&pCtx->videoCtx.pOutbuf[nIndex]; + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Set Geometry (Input) + */ +static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Inbuf( + void *pHandle, + ExynosVideoGeometry *pBufferConf) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_Format fmt; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pBufferConf == NULL) { + ALOGE("%s: Buffer geometry must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = CODEC_OSAL_BUF_TYPE_SRC; + fmt.format = Codec_OSAL_CodingTypeToCompressdFormat(pBufferConf->eCompressionFormat); + fmt.planeSize[0] = pBufferConf->nSizeImage; + fmt.nPlane = pBufferConf->nPlaneCnt; + + if (Codec_OSAL_SetFormat(pCtx, &fmt) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + memcpy(&pCtx->videoCtx.inbufGeometry, pBufferConf, sizeof(pCtx->videoCtx.inbufGeometry)); + pCtx->videoCtx.nInbufPlanes = pBufferConf->nPlaneCnt; + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Set Geometry (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Set_Geometry_Outbuf( + void *pHandle, + ExynosVideoGeometry *pBufferConf) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_Format fmt; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pBufferConf == NULL) { + ALOGE("%s: Buffer geometry must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = CODEC_OSAL_BUF_TYPE_DST; + fmt.format = Codec_OSAL_ColorFormatToPixelFormat( + pBufferConf->eColorFormat, pCtx->videoCtx.instInfo.HwVersion); + fmt.nPlane = pBufferConf->nPlaneCnt; + + if (Codec_OSAL_SetFormat(pCtx, &fmt) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + memcpy(&pCtx->videoCtx.outbufGeometry, pBufferConf, sizeof(pCtx->videoCtx.outbufGeometry)); + pCtx->videoCtx.nOutbufPlanes = pBufferConf->nPlaneCnt; + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Get Geometry (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Get_Geometry_Outbuf( + void *pHandle, + ExynosVideoGeometry *pBufferConf) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + ExynosVideoGeometry *pCodecBufferConf = NULL; + + CodecOSAL_Format fmt; + CodecOSAL_Crop crop; + int i, value; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pBufferConf == NULL) { + ALOGE("%s: Buffer geometry must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&fmt, 0, sizeof(fmt)); + memset(&crop, 0, sizeof(crop)); + + fmt.type = CODEC_OSAL_BUF_TYPE_DST; + if (Codec_OSAL_GetFormat(pCtx, &fmt) != 0) { + if (errno == EAGAIN) + ret = VIDEO_ERROR_HEADERINFO; + else + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + crop.type = CODEC_OSAL_BUF_TYPE_DST; + if (Codec_OSAL_GetCrop(pCtx, &crop) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCodecBufferConf = &(pCtx->videoCtx.outbufGeometry); + + pCodecBufferConf->nFrameWidth = fmt.width; + pCodecBufferConf->nFrameHeight = fmt.height; + pCodecBufferConf->eColorFormat = Codec_OSAL_PixelFormatToColorFormat(fmt.format); + pCodecBufferConf->nStride = fmt.stride; + +#ifdef USE_DEINTERLACING_SUPPORT + if ((fmt.field == CODEC_OSAL_INTER_TYPE_INTER) || + (fmt.field == CODEC_OSAL_INTER_TYPE_TB) || + (fmt.field == CODEC_OSAL_INTER_TYPE_BT)) + pCodecBufferConf->bInterlaced = VIDEO_TRUE; + else +#endif + pCodecBufferConf->bInterlaced = VIDEO_FALSE; + + switch (pCodecBufferConf->eColorFormat) { + /* if it is 10bit contents, the format obtained from MFC D/D will be one of 10bit formats */ + case VIDEO_COLORFORMAT_NV12_S10B: + pCodecBufferConf->eFilledDataType = DATA_8BIT_WITH_2BIT; + pCtx->videoCtx.nOutbufPlanes = 1; + break; + case VIDEO_COLORFORMAT_NV12M_S10B: + case VIDEO_COLORFORMAT_NV21M_S10B: + pCodecBufferConf->eFilledDataType = DATA_8BIT_WITH_2BIT; + pCtx->videoCtx.nOutbufPlanes = 2; + break; + case VIDEO_COLORFORMAT_NV12M_P010: + case VIDEO_COLORFORMAT_NV21M_P010: + pCodecBufferConf->eFilledDataType = DATA_10BIT; + pCtx->videoCtx.nOutbufPlanes = 2; + pCodecBufferConf->nStride = (fmt.stride / 2); /* MFC D/D returns bytes multiplied bpp instead of length on pixel */ + break; + case VIDEO_COLORFORMAT_NV12M_SBWC: + case VIDEO_COLORFORMAT_NV21M_SBWC: + pCodecBufferConf->eFilledDataType = DATA_8BIT_SBWC; + pCodecBufferConf->nStride = ALIGN(fmt.width, 32); + pCtx->videoCtx.nOutbufPlanes = 2; + break; + case VIDEO_COLORFORMAT_NV12_SBWC: + pCodecBufferConf->eFilledDataType = DATA_8BIT_SBWC; + pCodecBufferConf->nStride = ALIGN(fmt.width, 32); + pCtx->videoCtx.nOutbufPlanes = 1; + break; + case VIDEO_COLORFORMAT_NV12M_10B_SBWC: + case VIDEO_COLORFORMAT_NV21M_10B_SBWC: + pCodecBufferConf->eFilledDataType = DATA_10BIT_SBWC; + pCodecBufferConf->nStride = ALIGN(fmt.width, 32); + pCtx->videoCtx.nOutbufPlanes = 2; + break; + case VIDEO_COLORFORMAT_NV12_10B_SBWC: + pCodecBufferConf->eFilledDataType = DATA_10BIT_SBWC; + pCodecBufferConf->nStride = ALIGN(fmt.width, 32); + pCtx->videoCtx.nOutbufPlanes = 1; + break; + default: + /* for backward compatibility : MFC D/D only supports g_ctrl */ + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_DEC_GET_10BIT_INFO, &value); + if (value == 1) { + /* supports only S10B format */ + pCodecBufferConf->eFilledDataType = DATA_8BIT_WITH_2BIT; + pCodecBufferConf->eColorFormat = VIDEO_COLORFORMAT_NV12M_S10B; + pCtx->videoCtx.nOutbufPlanes = 2; + +#ifdef USE_SINGLE_PALNE_SUPPORT + if (pCtx->videoCtx.instInfo.eSecurityType == VIDEO_SECURE) { + pCodecBufferConf->eColorFormat = VIDEO_COLORFORMAT_NV12_S10B; + pCtx->videoCtx.nOutbufPlanes = 1; + } +#endif + } else { + pCodecBufferConf->eFilledDataType = DATA_8BIT; + } + break; + } + + /* Get planes aligned buffer size */ + for (i = 0; i < pCtx->videoCtx.nOutbufPlanes; i++) + pCodecBufferConf->nAlignPlaneSize[i] = fmt.planeSize[i]; + + pCodecBufferConf->cropRect.nTop = crop.top; + pCodecBufferConf->cropRect.nLeft = crop.left; + pCodecBufferConf->cropRect.nWidth = crop.width; + pCodecBufferConf->cropRect.nHeight = crop.height; + + ALOGV("%s: %s contents", __FUNCTION__, (pCodecBufferConf->eFilledDataType & (DATA_10BIT | DATA_10BIT_SBWC)? "10bit":"8bit")); + + /* HdrInfo in pBufferConf is not used by OMX component */ + memcpy(pBufferConf, pCodecBufferConf, sizeof(ExynosVideoGeometry)); + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Get BlackBarCrop (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Get_BlackBarCrop_Outbuf( + void *pHandle, + ExynosVideoRect *pBufferCrop) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_Crop crop; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pBufferCrop == NULL) { + ALOGE("%s: Buffer Crop must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&crop, 0, sizeof(crop)); + + crop.type = CODEC_OSAL_BUF_TYPE_DST; + if (Codec_OSAL_GetCrop(pCtx, &crop) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pBufferCrop->nTop = crop.top; + pBufferCrop->nLeft = crop.left; + pBufferCrop->nWidth = crop.width; + pBufferCrop->nHeight = crop.height; + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Setup (Input) + */ +static ExynosVideoErrorType MFC_Decoder_Setup_Inbuf( + void *pHandle, + unsigned int nBufferCount) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoPlane *pVideoPlane = NULL; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_ReqBuf reqBuf; + CodecOSAL_Buffer buf; + + int i; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (nBufferCount == 0) { + nBufferCount = MAX_INPUTBUFFER_COUNT; + ALOGV("%s: Change buffer count %d", __FUNCTION__, nBufferCount); + } + + ALOGV("%s: setting up inbufs(%d) shared = %s\n", __FUNCTION__, nBufferCount, + pCtx->videoCtx.bShareInbuf ? "true" : "false"); + + memset(&reqBuf, 0, sizeof(reqBuf)); + + reqBuf.type = CODEC_OSAL_BUF_TYPE_SRC; + reqBuf.count = nBufferCount; + if (pCtx->videoCtx.bShareInbuf == VIDEO_TRUE) + reqBuf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + reqBuf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + if (Codec_OSAL_RequestBuf(pCtx, &reqBuf) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + if (reqBuf.count != nBufferCount) { + ALOGE("%s: asked for %d, got %d\n", __FUNCTION__, nBufferCount, reqBuf.count); + ret = VIDEO_ERROR_NOMEM; + goto EXIT; + } + + pCtx->videoCtx.nInbufs = (int)reqBuf.count; + + pCtx->videoCtx.pInbuf = malloc(sizeof(*pCtx->videoCtx.pInbuf) * pCtx->videoCtx.nInbufs); + if (pCtx->videoCtx.pInbuf == NULL) { + ALOGE("Failed to allocate input buffer context"); + ret = VIDEO_ERROR_NOMEM; + goto EXIT; + } + memset(pCtx->videoCtx.pInbuf, 0, sizeof(*pCtx->videoCtx.pInbuf) * pCtx->videoCtx.nInbufs); + + memset(&buf, 0, sizeof(buf)); + + if (pCtx->videoCtx.bShareInbuf == VIDEO_FALSE) { + buf.type = CODEC_OSAL_BUF_TYPE_SRC; + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + buf.nPlane = pCtx->videoCtx.nInbufPlanes; + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + buf.index = i; + + if (Codec_OSAL_QueryBuf(pCtx, &buf) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pVideoPlane = &pCtx->videoCtx.pInbuf[i].planes[0]; + + pVideoPlane->addr = Codec_OSAL_MemoryMap(NULL, + buf.planes[0].bufferSize, PROT_READ | PROT_WRITE, + MAP_SHARED, (unsigned long)buf.planes[0].addr, buf.planes[0].offset); + if (pVideoPlane->addr == MAP_FAILED) { + ret = VIDEO_ERROR_MAPFAIL; + goto EXIT; + } + + pVideoPlane->allocSize = buf.planes[0].bufferSize; + pVideoPlane->dataSize = 0; + + pCtx->videoCtx.pInbuf[i].pGeometry = &pCtx->videoCtx.inbufGeometry; + pCtx->videoCtx.pInbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pInbuf[i].bRegistered = VIDEO_TRUE; + } + } + + return ret; + +EXIT: + if ((pCtx != NULL) && + (pCtx->videoCtx.pInbuf != NULL)) { + if (pCtx->videoCtx.bShareInbuf == VIDEO_FALSE) { + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + pVideoPlane = &pCtx->videoCtx.pInbuf[i].planes[0]; + if (pVideoPlane->addr == MAP_FAILED) { + pVideoPlane->addr = NULL; + break; + } + + Codec_OSAL_MemoryUnmap(pVideoPlane->addr, pVideoPlane->allocSize); + } + } + + free(pCtx->videoCtx.pInbuf); + pCtx->videoCtx.pInbuf = NULL; + pCtx->videoCtx.nInbufs = 0; + } + + return ret; +} + +/* + * [Decoder Buffer OPS] Setup (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Setup_Outbuf( + void *pHandle, + unsigned int nBufferCount) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoPlane *pVideoPlane = NULL; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_ReqBuf reqBuf; + CodecOSAL_Buffer buf; + + int i, j; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (nBufferCount == 0) { + nBufferCount = MAX_OUTPUTBUFFER_COUNT; + ALOGV("%s: Change buffer count %d", __FUNCTION__, nBufferCount); + } + + ALOGV("%s: setting up outbufs(%d) shared = %s\n", __FUNCTION__, nBufferCount, + pCtx->videoCtx.bShareOutbuf ? "true" : "false"); + + memset(&reqBuf, 0, sizeof(reqBuf)); + + reqBuf.type = CODEC_OSAL_BUF_TYPE_DST; + reqBuf.count = nBufferCount; + if (pCtx->videoCtx.bShareOutbuf == VIDEO_TRUE) + reqBuf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + reqBuf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + if (Codec_OSAL_RequestBuf(pCtx, &reqBuf) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + if (reqBuf.count != nBufferCount) { + ALOGE("%s: asked for %d, got %d\n", __FUNCTION__, nBufferCount, reqBuf.count); + ret = VIDEO_ERROR_NOMEM; + goto EXIT; + } + + pCtx->videoCtx.nOutbufs = reqBuf.count; + + pCtx->videoCtx.pOutbuf = malloc(sizeof(*pCtx->videoCtx.pOutbuf) * pCtx->videoCtx.nOutbufs); + if (pCtx->videoCtx.pOutbuf == NULL) { + ALOGE("Failed to allocate output buffer context"); + ret = VIDEO_ERROR_NOMEM; + goto EXIT; + } + memset(pCtx->videoCtx.pOutbuf, 0, sizeof(*pCtx->videoCtx.pOutbuf) * pCtx->videoCtx.nOutbufs); + + memset(&buf, 0, sizeof(buf)); + + if (pCtx->videoCtx.bShareOutbuf == VIDEO_FALSE) { + buf.type = CODEC_OSAL_BUF_TYPE_DST; + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + buf.nPlane = pCtx->videoCtx.nOutbufPlanes; + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + buf.index = i; + + if (Codec_OSAL_QueryBuf(pCtx, &buf) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + for (j = 0; j < pCtx->videoCtx.nOutbufPlanes; j++) { + pVideoPlane = &pCtx->videoCtx.pOutbuf[i].planes[j]; + + pVideoPlane->addr = Codec_OSAL_MemoryMap(NULL, + buf.planes[j].bufferSize, PROT_READ | PROT_WRITE, + MAP_SHARED, (unsigned long)buf.planes[j].addr, buf.planes[j].offset); + if (pVideoPlane->addr == MAP_FAILED) { + ret = VIDEO_ERROR_MAPFAIL; + goto EXIT; + } + + pVideoPlane->allocSize = buf.planes[j].bufferSize; + pVideoPlane->dataSize = 0; + } + + pCtx->videoCtx.pOutbuf[i].pGeometry = &pCtx->videoCtx.outbufGeometry; + pCtx->videoCtx.pOutbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pOutbuf[i].bSlotUsed = VIDEO_FALSE; + pCtx->videoCtx.pOutbuf[i].nIndexUseCnt = 0; + pCtx->videoCtx.pOutbuf[i].bRegistered = VIDEO_TRUE; + } + } else { + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + pCtx->videoCtx.pOutbuf[i].pGeometry = &pCtx->videoCtx.outbufGeometry; + pCtx->videoCtx.pOutbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pOutbuf[i].bSlotUsed = VIDEO_FALSE; + pCtx->videoCtx.pOutbuf[i].nIndexUseCnt = 0; + pCtx->videoCtx.pOutbuf[i].bRegistered = VIDEO_FALSE; + } + /* Initialize initial values */ + } + + return ret; + +EXIT: + if ((pCtx != NULL) && + (pCtx->videoCtx.pOutbuf != NULL)) { + if (pCtx->videoCtx.bShareOutbuf == VIDEO_FALSE) { + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + for (j = 0; j < pCtx->videoCtx.nOutbufPlanes; j++) { + pVideoPlane = &pCtx->videoCtx.pOutbuf[i].planes[j]; + if (pVideoPlane->addr == MAP_FAILED) { + pVideoPlane->addr = NULL; + break; + } + + Codec_OSAL_MemoryUnmap(pVideoPlane->addr, pVideoPlane->allocSize); + } + } + } + + free(pCtx->videoCtx.pOutbuf); + pCtx->videoCtx.pOutbuf = NULL; + } + + return ret; +} + +/* + * [Decoder Buffer OPS] Run (Input) + */ +static ExynosVideoErrorType MFC_Decoder_Run_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonInbuf == VIDEO_FALSE) { + if (Codec_OSAL_SetStreamOn(pCtx, CODEC_OSAL_BUF_TYPE_SRC) != 0) { + ALOGE("%s: Failed to streamon for input buffer", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.bStreamonInbuf = VIDEO_TRUE; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Run (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Run_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonOutbuf == VIDEO_FALSE) { + if (Codec_OSAL_SetStreamOn(pCtx, CODEC_OSAL_BUF_TYPE_DST) != 0) { + ALOGE("%s: Failed to streamon for output buffer", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.bStreamonOutbuf = VIDEO_TRUE; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Stop (Input) + */ +static ExynosVideoErrorType MFC_Decoder_Stop_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i = 0; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonInbuf == VIDEO_TRUE) { + if (Codec_OSAL_SetStreamOff(pCtx, CODEC_OSAL_BUF_TYPE_SRC) != 0) { + ALOGE("%s: Failed to streamoff for input buffer", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.bStreamonInbuf = VIDEO_FALSE; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) + pCtx->videoCtx.pInbuf[i].bQueued = VIDEO_FALSE; + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Stop (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Stop_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i = 0; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonOutbuf == VIDEO_TRUE) { + if (Codec_OSAL_SetStreamOff(pCtx, CODEC_OSAL_BUF_TYPE_DST) != 0) { + ALOGE("%s: Failed to streamoff for output buffer", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.bStreamonOutbuf = VIDEO_FALSE; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + pCtx->videoCtx.pOutbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pOutbuf[i].bSlotUsed = VIDEO_FALSE; + pCtx->videoCtx.pOutbuf[i].nIndexUseCnt = 0; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Wait (Input) + */ +static ExynosVideoErrorType MFC_Decoder_Wait_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + struct pollfd poll_events; + int poll_state; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + poll_events.fd = pCtx->videoCtx.hDevice; + poll_events.events = POLLOUT | POLLERR; + poll_events.revents = 0; + + do { + poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_DECODER_POLL_TIMEOUT); + if (poll_state > 0) { + if (poll_events.revents & POLLOUT) { + break; + } else { + ALOGE("%s: Poll return error", __FUNCTION__); + ret = VIDEO_ERROR_POLL; + break; + } + } else if (poll_state < 0) { + ALOGE("%s: Poll state error", __FUNCTION__); + ret = VIDEO_ERROR_POLL; + break; + } + } while (poll_state == 0); + +EXIT: + return ret; +} + +static ExynosVideoErrorType MFC_Decoder_Register_Inbuf( + void *pHandle, + ExynosVideoPlane *pPlanes, + int nPlanes) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i, j; + + if ((pCtx == NULL) || + (pPlanes == NULL) || + (nPlanes != pCtx->videoCtx.nInbufPlanes)) { + ALOGE("%s: params must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + if (pCtx->videoCtx.pInbuf[i].bRegistered == VIDEO_FALSE) { + for (j = 0; j < nPlanes; j++) { + pCtx->videoCtx.pInbuf[i].planes[j].addr = pPlanes[j].addr; + pCtx->videoCtx.pInbuf[i].planes[j].allocSize = pPlanes[j].allocSize; + pCtx->videoCtx.pInbuf[i].planes[j].fd = pPlanes[j].fd; + + ALOGV("%s: registered buf[%d][%d]: addr = %p, alloc_sz = %u, fd = %lu", + __FUNCTION__, i, j, pPlanes[j].addr, pPlanes[j].allocSize, pPlanes[j].fd); + } + + pCtx->videoCtx.pInbuf[i].bRegistered = VIDEO_TRUE; + break; + } + } + + if (i == pCtx->videoCtx.nInbufs) { + ALOGE("%s: can not find non-registered input buffer", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + } + +EXIT: + return ret; +} + +static ExynosVideoErrorType MFC_Decoder_Register_Outbuf( + void *pHandle, + ExynosVideoPlane *pPlanes, + int nPlanes) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i, j; + + if ((pCtx == NULL) || + (pPlanes == NULL) || + (nPlanes != pCtx->videoCtx.nOutbufPlanes)) { + ALOGE("%s: params must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + if (pCtx->videoCtx.pOutbuf[i].bRegistered == VIDEO_FALSE) { + for (j = 0; j < nPlanes; j++) { + pCtx->videoCtx.pOutbuf[i].planes[j].addr = pPlanes[j].addr; + pCtx->videoCtx.pOutbuf[i].planes[j].allocSize = pPlanes[j].allocSize; + pCtx->videoCtx.pOutbuf[i].planes[j].fd = pPlanes[j].fd; + + ALOGV("%s: registered buf[%d][%d]: addr = %p, alloc_sz = %d, fd = %lu", + __FUNCTION__, i, j, pPlanes[j].addr, pPlanes[j].allocSize, pPlanes[j].fd); + } + + /* this is for saving interlaced type or HDR info */ + if ((pCtx->videoCtx.outbufGeometry.bInterlaced == VIDEO_TRUE) || + (pCtx->videoCtx.outbufGeometry.eFilledDataType & DATA_10BIT)) { + pCtx->videoCtx.pOutbuf[i].planes[2].addr = pPlanes[2].addr; + pCtx->videoCtx.pOutbuf[i].planes[2].fd = pPlanes[2].fd; + } + + pCtx->videoCtx.pOutbuf[i].bRegistered = VIDEO_TRUE; + break; + } + } + + if (i == pCtx->videoCtx.nOutbufs) { + ALOGE("%s: can not find non-registered output buffer", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + } + +EXIT: + return ret; +} + +static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i, j; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + for (j = 0; j < pCtx->videoCtx.nInbufPlanes; j++) { + pCtx->videoCtx.pInbuf[i].planes[j].addr = NULL; + pCtx->videoCtx.pInbuf[i].planes[j].fd = 0; + } + + pCtx->videoCtx.pInbuf[i].bRegistered = VIDEO_FALSE; + } + +EXIT: + return ret; +} + +static ExynosVideoErrorType MFC_Decoder_Clear_RegisteredBuffer_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i, j; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + for (j = 0; j < pCtx->videoCtx.nOutbufPlanes; j++) { + pCtx->videoCtx.pOutbuf[i].planes[j].addr = NULL; + pCtx->videoCtx.pOutbuf[i].planes[j].fd = 0; + } + + /* this is for saving interlaced type or HDR info */ + if ((pCtx->videoCtx.outbufGeometry.bInterlaced == VIDEO_TRUE) || + (pCtx->videoCtx.outbufGeometry.eFilledDataType & DATA_10BIT)) { + pCtx->videoCtx.pOutbuf[i].planes[2].addr = NULL; + pCtx->videoCtx.pOutbuf[i].planes[2].fd = 0; + } + + pCtx->videoCtx.pOutbuf[i].bRegistered = VIDEO_FALSE; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Find (Input) + */ +static int MFC_Decoder_Find_Inbuf( + void *pHandle, + unsigned char *pBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int nIndex = -1, i; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + if (pCtx->videoCtx.pInbuf[i].bQueued == VIDEO_FALSE) { + if ((pBuffer == NULL) || + (pCtx->videoCtx.pInbuf[i].planes[0].addr == pBuffer)) { + nIndex = i; + break; + } + } + } + +EXIT: + return nIndex; +} + +/* + * [Decoder Buffer OPS] Find (Outnput) + */ +static int MFC_Decoder_Find_Outbuf( + void *pHandle, + unsigned char *pBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int nIndex = -1, i; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + if (pCtx->videoCtx.pOutbuf[i].bQueued == VIDEO_FALSE) { + if ((pBuffer == NULL) || + (pCtx->videoCtx.pOutbuf[i].planes[0].addr == pBuffer)) { + nIndex = i; + break; + } + } + } + +EXIT: + return nIndex; +} + +/* + * [Decoder Buffer OPS] Enqueue (Input) + */ +static ExynosVideoErrorType MFC_Decoder_Enqueue_Inbuf( + void *pHandle, + void *pBuffer[], + unsigned int nDataSize[], + int nPlanes, + void *pPrivate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + int index, i; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.nInbufPlanes < nPlanes) { + ALOGE("%s: Number of max planes : %d, nPlanes : %d", __FUNCTION__, + pCtx->videoCtx.nInbufPlanes, nPlanes); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_SRC; + buf.nPlane = pCtx->videoCtx.nInbufPlanes; + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pInMutex; + pthread_mutex_lock(pMutex); + + index = MFC_Decoder_Find_Inbuf(pCtx, pBuffer[0]); + if (index == -1) { + pthread_mutex_unlock(pMutex); + ALOGE("%s: Failed to get index", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + goto EXIT; + } + buf.index = index; + ALOGV("%s: index:%d pCtx->videoCtx.pInbuf[buf.index].bQueued:%d, pBuffer[0]:%p", + __FUNCTION__, index, pCtx->videoCtx.pInbuf[buf.index].bQueued, pBuffer[0]); + + if (pCtx->videoCtx.bShareInbuf == VIDEO_TRUE) { + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + for (i = 0; i < buf.nPlane; i++) { + if (buf.memory == CODEC_OSAL_MEM_TYPE_USERPTR) + buf.planes[i].addr = pBuffer[i]; + else + buf.planes[i].addr = (void *)(unsigned long)pCtx->videoCtx.pInbuf[index].planes[i].fd; + + buf.planes[i].bufferSize = pCtx->videoCtx.pInbuf[index].planes[i].allocSize; + buf.planes[i].dataLen = nDataSize[i]; + + ALOGV("%s: shared inbuf(%d) plane(%d) addr = %p len = %d used = %d", __FUNCTION__, + index, i, + buf.planes[i].addr, + buf.planes[i].bufferSize, + buf.planes[i].dataLen); + } + } else { + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + for (i = 0; i < nPlanes; i++) + buf.planes[i].dataLen = nDataSize[i]; + } + + if (nDataSize[0] <= 0) { + buf.flags = EMPTY_DATA | LAST_FRAME; + ALOGD("%s: EMPTY DATA", __FUNCTION__); + } else { + if ((((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) + buf.flags = LAST_FRAME; + + if ((((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == OMX_BUFFERFLAG_CODECCONFIG) + buf.flags |= CSD_FRAME; + + if (buf.flags & (CSD_FRAME | LAST_FRAME)) + ALOGD("%s: DATA with flags(0x%x)", __FUNCTION__, buf.flags); + } + + signed long long sec = (((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp / 1E6); + signed long long usec = (((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp) - (sec * 1E6); + buf.timestamp.tv_sec = (long)sec; + buf.timestamp.tv_usec = (long)usec; + + pCtx->videoCtx.pInbuf[buf.index].pPrivate = pPrivate; + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_TRUE; + pthread_mutex_unlock(pMutex); + + if (Codec_OSAL_EnqueueBuf(pCtx, &buf) != 0) { + ALOGE("%s: Failed to enqueue input buffer", __FUNCTION__); + pthread_mutex_lock(pMutex); + pCtx->videoCtx.pInbuf[buf.index].pPrivate = NULL; + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_FALSE; + pthread_mutex_unlock(pMutex); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Enqueue (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Enqueue_Outbuf( + void *pHandle, + void *pBuffer[], + unsigned int nDataSize[], + int nPlanes, + void *pPrivate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + int i, index, state = 0; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.nOutbufPlanes < nPlanes) { + ALOGE("%s: Number of max planes : %d, nPlanes : %d", __FUNCTION__, + pCtx->videoCtx.nOutbufPlanes, nPlanes); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_DST; + buf.nPlane = pCtx->videoCtx.nOutbufPlanes; + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pOutMutex; + pthread_mutex_lock(pMutex); + + index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]); + if (index == -1) { + pthread_mutex_unlock(pMutex); + ALOGE("%s: Failed to get index", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + goto EXIT; + } + buf.index = index; + ALOGV("%s: index:%d pCtx->videoCtx.pOutbuf[buf.index].bQueued:%d, pBuffer[0]:%p", + __FUNCTION__, index, pCtx->videoCtx.pOutbuf[buf.index].bQueued, pBuffer[0]); + + if (pCtx->videoCtx.bShareOutbuf == VIDEO_TRUE) { + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + for (i = 0; i < buf.nPlane; i++) { + if (buf.memory == CODEC_OSAL_MEM_TYPE_USERPTR) + buf.planes[i].addr = pBuffer[i]; + else + buf.planes[i].addr = (void *)(unsigned long)pCtx->videoCtx.pOutbuf[index].planes[i].fd; + + buf.planes[i].bufferSize = pCtx->videoCtx.pOutbuf[index].planes[i].allocSize; + buf.planes[i].dataLen = nDataSize[i]; + + ALOGV("%s: shared outbuf(%d) plane = %d addr = %p len = %d used = %d", __FUNCTION__, + index, i, + buf.planes[i].addr, + buf.planes[i].bufferSize, + buf.planes[i].dataLen); + } + } else { + ALOGV("%s: non-shared outbuf(%d)\n", __FUNCTION__, index); + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + } + + pCtx->videoCtx.pOutbuf[buf.index].pPrivate = pPrivate; + pCtx->videoCtx.pOutbuf[buf.index].bQueued = VIDEO_TRUE; + pthread_mutex_unlock(pMutex); + + if (Codec_OSAL_EnqueueBuf(pCtx, &buf) != 0) { + pthread_mutex_lock(pMutex); + pCtx->videoCtx.pOutbuf[buf.index].pPrivate = NULL; + pCtx->videoCtx.pOutbuf[buf.index].bQueued = VIDEO_FALSE; + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_DEC_CHECK_STATE, &state); + if (state == 1) { + /* The case of Resolution is changed */ + ret = VIDEO_ERROR_WRONGBUFFERSIZE; + } else { + ALOGE("%s: Failed to enqueue output buffer", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + } + pthread_mutex_unlock(pMutex); + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Dequeue (Input) + */ +static ExynosVideoBuffer *MFC_Decoder_Dequeue_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoBuffer *pInbuf = NULL; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonInbuf == VIDEO_FALSE) { + pInbuf = NULL; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_SRC; + buf.nPlane = pCtx->videoCtx.nInbufPlanes; + if (pCtx->videoCtx.bShareInbuf == VIDEO_TRUE) + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + if (Codec_OSAL_DequeueBuf(pCtx, &buf) != 0) { + pInbuf = NULL; + goto EXIT; + } + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pInMutex; + pthread_mutex_lock(pMutex); + + pInbuf = &pCtx->videoCtx.pInbuf[buf.index]; + if (pInbuf->bQueued == VIDEO_FALSE) { + pInbuf = NULL; + pthread_mutex_unlock(pMutex); + goto EXIT; + } + + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_FALSE; + + if (pCtx->videoCtx.bStreamonInbuf == VIDEO_FALSE) + pInbuf = NULL; + + pthread_mutex_unlock(pMutex); + +EXIT: + return pInbuf; +} + +/* + * [Decoder Buffer OPS] Dequeue (Output) + */ +static ExynosVideoBuffer *MFC_Decoder_Dequeue_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoBuffer *pOutbuf = NULL; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + int value = 0, state = 0; + int ret = 0; + int i; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonOutbuf == VIDEO_FALSE) { + pOutbuf = NULL; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_DST; + buf.nPlane = pCtx->videoCtx.nOutbufPlanes; + if (pCtx->videoCtx.bShareOutbuf == VIDEO_TRUE) + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */ + ret = Codec_OSAL_DequeueBuf(pCtx, &buf); + if (ret != 0) { + if (errno == EIO) + pOutbuf = (ExynosVideoBuffer *)VIDEO_ERROR_DQBUF_EIO; + else + pOutbuf = NULL; + goto EXIT; + } + + if (buf.frameType & VIDEO_FRAME_CORRUPT) { +#ifdef USE_ORIGINAL_HEADER + if (pCtx->videoCtx.instInfo.supportInfo.dec.bFrameErrorTypeSupport == VIDEO_TRUE) { + int corruptType = 0; + + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_VIDEO_FRAME_ERROR_TYPE, &corruptType); + switch(corruptType) { + case 3: /* BROKEN */ + /* nothing to do */ + break; + case 2: /* SYNC POINT */ + case 1: /* CONCEALMENT */ + buf.frameType = (buf.frameType & ~(VIDEO_FRAME_CORRUPT)) | VIDEO_FRAME_CONCEALMENT; + break; + default: + break; + } + } else +#endif + { + buf.frameType = (buf.frameType & ~(VIDEO_FRAME_CORRUPT)) | VIDEO_FRAME_CONCEALMENT; + } + } + + if (pCtx->videoCtx.bStreamonOutbuf == VIDEO_FALSE) { + pOutbuf = NULL; + goto EXIT; + } + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pOutMutex; + pthread_mutex_lock(pMutex); + + pOutbuf = &pCtx->videoCtx.pOutbuf[buf.index]; + if (pOutbuf->bQueued == VIDEO_FALSE) { + pOutbuf = NULL; + ret = VIDEO_ERROR_NOBUFFERS; + pthread_mutex_unlock(pMutex); + goto EXIT; + } + + for (i = 0; i < buf.nPlane; i++) + pOutbuf->planes[i].dataSize = buf.planes[i].dataLen; + + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_DEC_DISPLAY_STATUS, &value); + + switch (value) { + case 0: + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY; +#ifdef USE_HEVC_HWIP + if ((pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_HEVC) || + (pCtx->videoCtx.instInfo.HwVersion != (int)MFC_51)) { +#else + if (pCtx->videoCtx.instInfo.HwVersion != (int)MFC_51) { +#endif + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_DEC_CHECK_STATE, &state); + if (state == 4) /* DPB realloc for S3D SEI */ + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_ENABLED_S3D; + } + break; + case 1: + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING; + break; + case 2: + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY; + break; + case 3: + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_DEC_CHECK_STATE, &state); + if (state == 1) /* Resolution is changed */ + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL; + else /* Decoding is finished */ + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED; + break; + case 4: + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_LAST_FRAME; + break; + default: + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + break; + } + + pOutbuf->frameType = buf.frameType; + + if (pCtx->videoCtx.outbufGeometry.bInterlaced == VIDEO_TRUE) { + if ((buf.field == CODEC_OSAL_INTER_TYPE_TB) || + (buf.field == CODEC_OSAL_INTER_TYPE_BT)) { + pOutbuf->interlacedType = buf.field; + } else { + ALOGV("%s: buf.field's value is invald(%d)", __FUNCTION__, buf.field); + pOutbuf->interlacedType = CODEC_OSAL_INTER_TYPE_NONE; + } + } + + if (buf.flags & HAS_HDR_INFO) { + ExynosVideoHdrInfo *pHdrInfo = &(pCtx->videoCtx.outbufGeometry.HdrInfo); + + pHdrInfo->eChangedType = buf.flags; + + /* HDR Dynamic Info is obtained from shared buffer instead of ioctl call */ + if ((pCtx->videoCtx.instInfo.supportInfo.dec.bHDRDynamicInfoSupport == VIDEO_TRUE) && + (buf.flags & HAS_HDR_DYNAMIC_INFO)) { + ExynosVideoHdrDynamic *pHdrDynamic = ((ExynosVideoHdrDynamic *)pCtx->videoCtx.specificInfo.dec.pHDRInfoShareBufferAddr) + + buf.index; + if (pHdrDynamic->valid != 0) { + memcpy((char *)(&(pCtx->videoCtx.outbufGeometry.HdrInfo.sHdrDynamic)), + (char *)pHdrDynamic, + sizeof(ExynosVideoHdrDynamic)); + //} else { + //pCtx->videoCtx.outbufGeometry.HdrInfo.sHdrDynamic.valid = 0; + } + } + + pOutbuf->frameType |= VIDEO_FRAME_WITH_HDR_INFO; + } + + if (buf.flags & HAS_BLACK_BAR_CROP_INFO) + pOutbuf->frameType |= VIDEO_FRAME_WITH_BLACK_BAR; + + if (pCtx->videoCtx.outbufGeometry.eFilledDataType & (DATA_8BIT_SBWC | DATA_10BIT_SBWC)) { + if (buf.flags & HAS_UNCOMP_DATA) { + /* SBWC scenario, but data is not compressed by black bar */ + pOutbuf->frameType |= VIDEO_FRAME_NEED_ACTUAL_FORMAT; + } + } + + pOutbuf->bQueued = VIDEO_FALSE; + + pthread_mutex_unlock(pMutex); + +EXIT: + return pOutbuf; +} + +static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) + pCtx->videoCtx.pInbuf[i].bQueued = VIDEO_FALSE; + +EXIT: + return ret; +} + +static ExynosVideoErrorType MFC_Decoder_Clear_Queued_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) + pCtx->videoCtx.pOutbuf[i].bQueued = VIDEO_FALSE; + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Cleanup Buffer (Input) + */ +static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_ReqBuf reqBuf; + int nBufferCount = 0; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + nBufferCount = 0; /* for clean-up */ + + memset(&reqBuf, 0, sizeof(reqBuf)); + + reqBuf.type = CODEC_OSAL_BUF_TYPE_SRC; + reqBuf.count = nBufferCount; + if (pCtx->videoCtx.bShareInbuf == VIDEO_TRUE) + reqBuf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + reqBuf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + if (Codec_OSAL_RequestBuf(pCtx, &reqBuf) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.nInbufs = (int)reqBuf.count; + + if (pCtx->videoCtx.pInbuf != NULL) { + free(pCtx->videoCtx.pInbuf); + pCtx->videoCtx.pInbuf = NULL; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Cleanup Buffer (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Cleanup_Buffer_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_ReqBuf reqBuf; + int nBufferCount = 0; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + nBufferCount = 0; /* for clean-up */ + + memset(&reqBuf, 0, sizeof(reqBuf)); + + reqBuf.type = CODEC_OSAL_BUF_TYPE_DST; + reqBuf.count = nBufferCount; + if (pCtx->videoCtx.bShareOutbuf == VIDEO_TRUE) + reqBuf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + reqBuf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + if (Codec_OSAL_RequestBuf(pCtx, &reqBuf) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.nOutbufs = (int)reqBuf.count; + + if (pCtx->videoCtx.pOutbuf != NULL) { + free(pCtx->videoCtx.pOutbuf); + pCtx->videoCtx.pOutbuf = NULL; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] Apply Registered Buffer (Output) + */ +static ExynosVideoErrorType MFC_Decoder_Apply_RegisteredBuffer_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_DEC_WAIT_DECODING_START, 1) != 0) { + ALOGW("%s: The requested function is not implemented", __FUNCTION__); + //ret = VIDEO_ERROR_APIFAIL; + //goto EXIT; /* For Backward compatibility */ + } + + ret = MFC_Decoder_Run_Outbuf(pHandle); + if (VIDEO_ERROR_NONE != ret) + goto EXIT; + + ret = MFC_Decoder_Stop_Outbuf(pHandle); + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] FindIndex (Input) + */ +static int MFC_Decoder_FindEmpty_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int nIndex = -1, i; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + if (pCtx->videoCtx.pInbuf[i].bQueued == VIDEO_FALSE) { + nIndex = i; + break; + } + } + +EXIT: + return nIndex; +} + +/* + * [Decoder Buffer OPS] ExtensionEnqueue (Input) + */ +static ExynosVideoErrorType MFC_Decoder_ExtensionEnqueue_Inbuf( + void *pHandle, + void *pBuffer[], + unsigned long pFd[], + unsigned int nAllocLen[], + unsigned int nDataSize[], + int nPlanes, + void *pPrivate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + int index, i; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.nInbufPlanes < nPlanes) { + ALOGE("%s: Number of max planes : %d, nPlanes : %d", __FUNCTION__, + pCtx->videoCtx.nInbufPlanes, nPlanes); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_SRC; + buf.nPlane = pCtx->videoCtx.nInbufPlanes; + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pInMutex; + pthread_mutex_lock(pMutex); + + index = MFC_Decoder_FindEmpty_Inbuf(pCtx); + if (index == -1) { + pthread_mutex_unlock(pMutex); + ALOGE("%s: Failed to get index", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + goto EXIT; + } + buf.index = index; + ALOGV("%s: index:%d pCtx->videoCtx.pInbuf[buf.index].bQueued:%d, pFd[0]:%lu", + __FUNCTION__, index, pCtx->videoCtx.pInbuf[buf.index].bQueued, pFd[0]); + + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + for (i = 0; i < buf.nPlane; i++) { + if (buf.memory == CODEC_OSAL_MEM_TYPE_USERPTR) + buf.planes[i].addr = pBuffer[i]; + else + buf.planes[i].addr = (void *)pFd[i]; + + buf.planes[i].bufferSize = nAllocLen[i]; + buf.planes[i].dataLen = nDataSize[i]; + + /* Temporary storage for Dequeue */ + pCtx->videoCtx.pInbuf[buf.index].planes[i].addr = pBuffer[i]; + pCtx->videoCtx.pInbuf[buf.index].planes[i].fd = pFd[i]; + pCtx->videoCtx.pInbuf[buf.index].planes[i].allocSize = nAllocLen[i]; + + ALOGV("%s: shared inbuf(%d) plane=%d addr=%p fd=%lu len=%d used=%d", + __FUNCTION__, index, i, + pBuffer[i], pFd[i], + nAllocLen[i], nDataSize[i]); + } + + if (nDataSize[0] <= 0) { + buf.flags = EMPTY_DATA | LAST_FRAME; + ALOGD("%s: EMPTY DATA", __FUNCTION__); + } else { + if ((((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) + buf.flags = LAST_FRAME; + + if ((((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_CODECCONFIG) == OMX_BUFFERFLAG_CODECCONFIG) + buf.flags |= CSD_FRAME; + + if (buf.flags & (CSD_FRAME | LAST_FRAME)) + ALOGD("%s: DATA with flags(0x%x)", __FUNCTION__, buf.flags); + } + + signed long long sec = (((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp / 1E6); + signed long long usec = (((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp) - (sec * 1E6); + buf.timestamp.tv_sec = (long)sec; + buf.timestamp.tv_usec = (long)usec; + + pCtx->videoCtx.pInbuf[buf.index].pPrivate = pPrivate; + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_TRUE; + pthread_mutex_unlock(pMutex); + + if (Codec_OSAL_EnqueueBuf(pCtx, &buf) != 0) { + ALOGE("%s: Failed to enqueue input buffer", __FUNCTION__); + pthread_mutex_lock(pMutex); + pCtx->videoCtx.pInbuf[buf.index].pPrivate = NULL; + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_FALSE; + pthread_mutex_unlock(pMutex); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] ExtensionDequeue (Input) + */ +static ExynosVideoErrorType MFC_Decoder_ExtensionDequeue_Inbuf( + void *pHandle, + ExynosVideoBuffer *pVideoBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonInbuf == VIDEO_FALSE) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_SRC; + buf.nPlane = pCtx->videoCtx.nInbufPlanes; + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + + if (Codec_OSAL_DequeueBuf(pCtx, &buf) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pInMutex; + pthread_mutex_lock(pMutex); + + if (pCtx->videoCtx.pInbuf[buf.index].bQueued == VIDEO_TRUE) + memcpy(pVideoBuffer, &pCtx->videoCtx.pInbuf[buf.index], sizeof(ExynosVideoBuffer)); + else + ret = VIDEO_ERROR_NOBUFFERS; + memset(&pCtx->videoCtx.pInbuf[buf.index], 0, sizeof(ExynosVideoBuffer)); + + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_FALSE; + pthread_mutex_unlock(pMutex); + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] FindIndex (Output) + */ +static int MFC_Decoder_FindEmpty_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int nIndex = -1, i; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + if ((pCtx->videoCtx.pOutbuf[i].bQueued == VIDEO_FALSE) && + (pCtx->videoCtx.pOutbuf[i].bSlotUsed == VIDEO_FALSE)) { + nIndex = i; + break; + } + } + +EXIT: + return nIndex; +} + +/* + * [Decoder Buffer OPS] BufferIndexFree (Output) + */ +void MFC_Decoder_BufferIndexFree_Outbuf( + void *pHandle, + PrivateDataShareBuffer *pPDSB, + int nIndex) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int i, j; + + ALOGV("De-queue buf.index:%d, fd:%lu", nIndex, pCtx->videoCtx.pOutbuf[nIndex].planes[0].fd); + + if (pCtx->videoCtx.pOutbuf[nIndex].nIndexUseCnt == 0) + pCtx->videoCtx.pOutbuf[nIndex].bSlotUsed = VIDEO_FALSE; + + for (i = 0; i < VIDEO_BUFFER_MAX_NUM; i++) { + if (pPDSB->dpbFD[i].fd <= 0) + break; + + ALOGV("pPDSB->dpbFD[%d].fd:%d", i, pPDSB->dpbFD[i].fd); + for (j = 0; j < pCtx->videoCtx.nOutbufs; j++) { + if ((unsigned long)pPDSB->dpbFD[i].fd == pCtx->videoCtx.pOutbuf[j].planes[0].fd) { + if (pCtx->videoCtx.pOutbuf[j].bQueued == VIDEO_FALSE) { + if (pCtx->videoCtx.pOutbuf[j].nIndexUseCnt > 0) + pCtx->videoCtx.pOutbuf[j].nIndexUseCnt--; + } else if(pCtx->videoCtx.pOutbuf[j].bQueued == VIDEO_TRUE) { + if (pCtx->videoCtx.pOutbuf[j].nIndexUseCnt > 1) { + /* The buffer being used as the reference buffer came again. */ + pCtx->videoCtx.pOutbuf[j].nIndexUseCnt--; + } else { + /* Reference DPB buffer is internally reused. */ + } + } + + ALOGV("dec Cnt : FD:%d, pCtx->videoCtx.pOutbuf[%d].nIndexUseCnt:%d", + pPDSB->dpbFD[i].fd, j, pCtx->videoCtx.pOutbuf[j].nIndexUseCnt); + + if ((pCtx->videoCtx.pOutbuf[j].nIndexUseCnt == 0) && + (pCtx->videoCtx.pOutbuf[j].bQueued == VIDEO_FALSE)) { + pCtx->videoCtx.pOutbuf[j].bSlotUsed = VIDEO_FALSE; + } + } + } + } + + memset((char *)pPDSB, 0, sizeof(PrivateDataShareBuffer)); + + return; +} + +/* + * [Decoder Buffer OPS] ExtensionEnqueue (Output) + */ +static ExynosVideoErrorType MFC_Decoder_ExtensionEnqueue_Outbuf( + void *pHandle, + void *pBuffer[], + unsigned long pFd[], + unsigned int nAllocLen[], + unsigned int nDataSize[], + int nPlanes, + void *pPrivate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + int i, index, state = 0; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.nOutbufPlanes < nPlanes) { + ALOGE("%s: Number of max planes : %d, nPlanes : %d", __FUNCTION__, + pCtx->videoCtx.nOutbufPlanes, nPlanes); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_DST; + buf.nPlane = pCtx->videoCtx.nOutbufPlanes; + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pOutMutex; + pthread_mutex_lock(pMutex); + + index = MFC_Decoder_Find_Outbuf(pCtx, pBuffer[0]); + if (index == -1) { + ALOGV("%s: Failed to find index", __FUNCTION__); + index = MFC_Decoder_FindEmpty_Outbuf(pCtx); + if (index == -1) { + pthread_mutex_unlock(pMutex); + ALOGE("%s: Failed to get index", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + goto EXIT; + } + } + buf.index = index; + ALOGV("%s: index:%d pCtx->videoCtx.pOutbuf[buf.index].bQueued:%d, pFd[0]:%lu", + __FUNCTION__, index, pCtx->videoCtx.pOutbuf[buf.index].bQueued, pFd[0]); + + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + for (i = 0; i < buf.nPlane; i++) { + if (buf.memory == CODEC_OSAL_MEM_TYPE_USERPTR) + buf.planes[i].addr = pBuffer[i]; + else + buf.planes[i].addr = (void *)(unsigned long)pFd[i]; + + buf.planes[i].bufferSize = nAllocLen[i]; + buf.planes[i].dataLen = nDataSize[i]; + + /* Temporary storage for Dequeue */ + pCtx->videoCtx.pOutbuf[buf.index].planes[i].addr = pBuffer[i]; + pCtx->videoCtx.pOutbuf[buf.index].planes[i].fd = pFd[i]; + pCtx->videoCtx.pOutbuf[buf.index].planes[i].allocSize = nAllocLen[i]; + + ALOGV("%s: shared outbuf(%d) plane=%d addr=%p fd=%lu len=%d used=%d", + __FUNCTION__, index, i, + pBuffer[i], pFd[i], + nAllocLen[i], nDataSize[i]); + } + + /* this(private data buffer) is for saving interlaced type or HDR info */ + { + pCtx->videoCtx.pOutbuf[buf.index].planes[2].addr = pBuffer[2]; + pCtx->videoCtx.pOutbuf[buf.index].planes[2].fd = pFd[2]; + } + + pCtx->videoCtx.pOutbuf[buf.index].pPrivate = pPrivate; + pCtx->videoCtx.pOutbuf[buf.index].bQueued = VIDEO_TRUE; + + if (pCtx->videoCtx.instInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) { + pCtx->videoCtx.pOutbuf[buf.index].bSlotUsed = VIDEO_TRUE; + pCtx->videoCtx.pOutbuf[buf.index].nIndexUseCnt++; + } + + pthread_mutex_unlock(pMutex); + + if (Codec_OSAL_EnqueueBuf(pCtx, &buf) != 0) { + pthread_mutex_lock(pMutex); + pCtx->videoCtx.pOutbuf[buf.index].nIndexUseCnt--; + pCtx->videoCtx.pOutbuf[buf.index].pPrivate = NULL; + pCtx->videoCtx.pOutbuf[buf.index].bQueued = VIDEO_FALSE; + + if (pCtx->videoCtx.pOutbuf[buf.index].nIndexUseCnt == 0) + pCtx->videoCtx.pOutbuf[buf.index].bSlotUsed = VIDEO_FALSE; + + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_DEC_CHECK_STATE, &state); + if (state == 1) { + /* The case of Resolution is changed */ + ret = VIDEO_ERROR_WRONGBUFFERSIZE; + } else { + ALOGE("%s: Failed to enqueue output buffer", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + } + + pthread_mutex_unlock(pMutex); + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Decoder Buffer OPS] ExtensionDequeue (Output) + */ +static ExynosVideoErrorType MFC_Decoder_ExtensionDequeue_Outbuf( + void *pHandle, + ExynosVideoBuffer *pVideoBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + pthread_mutex_t *pMutex = NULL; + ExynosVideoBuffer *pOutbuf = NULL; + PrivateDataShareBuffer *pPDSB = NULL; + + CodecOSAL_Buffer buf; + + int value = 0, state = 0; + int i; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonOutbuf == VIDEO_FALSE) { + pOutbuf = NULL; + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_DST; + buf.nPlane = pCtx->videoCtx.nOutbufPlanes; + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + + /* HACK: pOutbuf return -1 means DECODING_ONLY for almost cases */ + if (Codec_OSAL_DequeueBuf(pCtx, &buf) != 0) { + if (errno == EIO) + ret = VIDEO_ERROR_DQBUF_EIO; + else + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + if (buf.frameType & VIDEO_FRAME_CORRUPT) { +#ifdef USE_ORIGINAL_HEADER + if (pCtx->videoCtx.instInfo.supportInfo.dec.bFrameErrorTypeSupport == VIDEO_TRUE) { + int corruptType = 0; + + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_VIDEO_FRAME_ERROR_TYPE, &corruptType); + switch(corruptType) { + case 3: /* BROKEN */ + /* nothing to do */ + break; + case 2: /* SYNC POINT */ + case 1: /* CONCEALMENT */ + buf.frameType = (buf.frameType & ~(VIDEO_FRAME_CORRUPT)) | VIDEO_FRAME_CONCEALMENT; + break; + default: + break; + } + } else +#endif + { + buf.frameType = (buf.frameType & ~(VIDEO_FRAME_CORRUPT)) | VIDEO_FRAME_CONCEALMENT; + } + } + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pOutMutex; + pthread_mutex_lock(pMutex); + + pOutbuf = &pCtx->videoCtx.pOutbuf[buf.index]; + if (pOutbuf->bQueued == VIDEO_FALSE) { + pOutbuf = NULL; + ret = VIDEO_ERROR_NOBUFFERS; + pthread_mutex_unlock(pMutex); + goto EXIT; + } + + for (i = 0; i < buf.nPlane; i++) + pOutbuf->planes[i].dataSize = buf.planes[i].dataLen; + + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_DEC_DISPLAY_STATUS, &value); + + switch (value) { + case 0: + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_ONLY; +#ifdef USE_HEVC_HWIP + if ((pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_HEVC) || + (pCtx->videoCtx.instInfo.HwVersion != (int)MFC_51)) { +#else + if (pCtx->videoCtx.instInfo.HwVersion != (int)MFC_51) { +#endif + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_DEC_CHECK_STATE, &state); + if (state == 4) /* DPB realloc for S3D SEI */ + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_ENABLED_S3D; + } + break; + case 1: + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_DECODING; + if (buf.flags & HAS_INTER_RESOLUTION_CHANGE) + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_INTER_RESOL_CHANGE; + break; + case 2: + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_ONLY; + if (buf.flags & HAS_INTER_RESOLUTION_CHANGE) + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DISPLAY_INTER_RESOL_CHANGE; + break; + case 3: + Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_DEC_CHECK_STATE, &state); + if (state == 1) /* Resolution is changed */ + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_CHANGE_RESOL; + else /* Decoding is finished */ + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_DECODING_FINISHED; + break; + case 4: + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_LAST_FRAME; + break; + default: + pOutbuf->displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + break; + } + + pOutbuf->frameType = buf.frameType; + + if (pCtx->videoCtx.outbufGeometry.bInterlaced == VIDEO_TRUE) { + if ((buf.field == CODEC_OSAL_INTER_TYPE_TB) || + (buf.field == CODEC_OSAL_INTER_TYPE_BT)) { + pOutbuf->interlacedType = buf.field; + } else { + ALOGV("%s: buf.field's value is invald(%d)", __FUNCTION__, buf.field); + pOutbuf->interlacedType = CODEC_OSAL_INTER_TYPE_NONE; + } + } + + if (buf.flags & HAS_HDR_INFO) { + ExynosVideoHdrInfo *pHdrInfo = &(pCtx->videoCtx.outbufGeometry.HdrInfo); + + pHdrInfo->eValidType = buf.flags; + pHdrInfo->eChangedType = HDR_INFO_NO_CHANGES; + + /* HDR Dynamic Info is obtained from shared buffer instead of ioctl call */ + if ((pCtx->videoCtx.instInfo.supportInfo.dec.bHDRDynamicInfoSupport == VIDEO_TRUE) && + (buf.flags & HAS_HDR_DYNAMIC_INFO)) { + ExynosVideoHdrDynamic *pHdrDynamic = ((ExynosVideoHdrDynamic *)pCtx->videoCtx.specificInfo.dec.pHDRInfoShareBufferAddr) + + buf.index; + if (memcmp(pHdrDynamic, &pCtx->videoCtx.outbufGeometry.HdrInfo.sHdrDynamic, sizeof(ExynosVideoHdrDynamic))) { + pHdrInfo->eChangedType |= HDR_INFO_DYNAMIC_META; + } + + if (pHdrDynamic->valid != 0) { + memcpy((char *)(&(pCtx->videoCtx.outbufGeometry.HdrInfo.sHdrDynamic)), + (char *)pHdrDynamic, + sizeof(ExynosVideoHdrDynamic)); + //} else { + //pCtx->videoCtx.outbufGeometry.HdrInfo.sHdrDynamic.valid = 0; + } + } + + pOutbuf->frameType |= VIDEO_FRAME_WITH_HDR_INFO; + } + + if (buf.flags & HAS_BLACK_BAR_CROP_INFO) + pOutbuf->frameType |= VIDEO_FRAME_WITH_BLACK_BAR; + + if (pCtx->videoCtx.outbufGeometry.eFilledDataType & (DATA_8BIT_SBWC | DATA_10BIT_SBWC)) { + if (buf.flags & HAS_UNCOMP_DATA) { + /* SBWC scenario, but data is not compressed by black bar */ + pOutbuf->frameType |= VIDEO_FRAME_NEED_ACTUAL_FORMAT; + } + } + + if (buf.flags & HAS_ACTUAL_FRAMERATE) { + /* for PowerHint: framerate from app can be invalid */ + pOutbuf->frameType |= VIDEO_FRAME_NEED_ACTUAL_FRAMERATE; + } + + if (pCtx->videoCtx.instInfo.supportInfo.dec.bDrvDPBManageSupport != VIDEO_TRUE) + pPDSB = ((PrivateDataShareBuffer *)pCtx->videoCtx.specificInfo.dec.pPrivateDataShareAddress) + buf.index; + + if (pCtx->videoCtx.pOutbuf[buf.index].bQueued == VIDEO_TRUE) { + memcpy(pVideoBuffer, pOutbuf, sizeof(ExynosVideoBuffer)); + if (pPDSB != NULL) + memcpy((char *)(&(pVideoBuffer->PDSB)), (char *)pPDSB, sizeof(PrivateDataShareBuffer)); + } else { + ret = VIDEO_ERROR_NOBUFFERS; + } + + if (pPDSB != NULL) + MFC_Decoder_BufferIndexFree_Outbuf(pHandle, pPDSB, buf.index); + + pCtx->videoCtx.pOutbuf[buf.index].bQueued = VIDEO_FALSE; + pthread_mutex_unlock(pMutex); + +EXIT: + return ret; +} + +/* + * [Decoder OPS] Common + */ +static ExynosVideoDecOps defDecOps = { + .nSize = 0, + .Init = MFC_Decoder_Init, + .Finalize = MFC_Decoder_Finalize, + .Set_DisplayDelay = MFC_Decoder_Set_DisplayDelay, + .Set_IFrameDecoding = MFC_Decoder_Set_IFrameDecoding, + .Enable_PackedPB = MFC_Decoder_Enable_PackedPB, + .Enable_LoopFilter = MFC_Decoder_Enable_LoopFilter, + .Enable_SliceMode = MFC_Decoder_Enable_SliceMode, + .Get_ActualBufferCount = MFC_Decoder_Get_ActualBufferCount, + .Set_FrameTag = MFC_Decoder_Set_FrameTag, + .Get_FrameTag = MFC_Decoder_Get_FrameTag, + .Enable_SEIParsing = MFC_Decoder_Enable_SEIParsing, + .Get_FramePackingInfo = MFC_Decoder_Get_FramePackingInfo, + .Set_ImmediateDisplay = MFC_Decoder_Set_ImmediateDisplay, + .Enable_DTSMode = MFC_Decoder_Enable_DTSMode, + .Set_QosRatio = MFC_Decoder_Set_QosRatio, + .Enable_DiscardRcvHeader = MFC_Decoder_Enable_DiscardRcvHeader, + .Enable_DualDPBMode = MFC_Decoder_Enable_DualDPBMode, + .Enable_DynamicDPB = MFC_Decoder_Enable_DynamicDPB, + .Get_HDRInfo = MFC_Decoder_Get_HDRInfo, + .Set_SearchBlackBar = MFC_Decoder_Set_SearchBlackBar, + .Get_ActualFormat = MFC_Decoder_Get_ActualFormat, + .Get_ActualFramerate = MFC_Decoder_Get_ActualFramerate, + .Set_OperatingRate = MFC_Decoder_Set_OperatingRate, + .Set_Priority = MFC_Decoder_Set_Priority, +}; + +/* + * [Decoder Buffer OPS] Input + */ +static ExynosVideoDecBufferOps defInbufOps = { + .nSize = 0, + .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Inbuf, + .Set_Shareable = MFC_Decoder_Set_Shareable_Inbuf, + .Get_Buffer = NULL, + .Set_Geometry = MFC_Decoder_Set_Geometry_Inbuf, + .Get_Geometry = NULL, + .Get_BlackBarCrop = NULL, + .Setup = MFC_Decoder_Setup_Inbuf, + .Run = MFC_Decoder_Run_Inbuf, + .Stop = MFC_Decoder_Stop_Inbuf, + .Enqueue = MFC_Decoder_Enqueue_Inbuf, + .Enqueue_All = NULL, + .Dequeue = MFC_Decoder_Dequeue_Inbuf, + .Register = MFC_Decoder_Register_Inbuf, + .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Inbuf, + .Clear_Queue = MFC_Decoder_Clear_Queued_Inbuf, + .Cleanup_Buffer = MFC_Decoder_Cleanup_Buffer_Inbuf, + .Apply_RegisteredBuffer = NULL, + .ExtensionEnqueue = MFC_Decoder_ExtensionEnqueue_Inbuf, + .ExtensionDequeue = MFC_Decoder_ExtensionDequeue_Inbuf, +}; + +/* + * [Decoder Buffer OPS] Output + */ +static ExynosVideoDecBufferOps defOutbufOps = { + .nSize = 0, + .Enable_Cacheable = MFC_Decoder_Enable_Cacheable_Outbuf, + .Set_Shareable = MFC_Decoder_Set_Shareable_Outbuf, + .Get_Buffer = MFC_Decoder_Get_Buffer_Outbuf, + .Set_Geometry = MFC_Decoder_Set_Geometry_Outbuf, + .Get_Geometry = MFC_Decoder_Get_Geometry_Outbuf, + .Get_BlackBarCrop = MFC_Decoder_Get_BlackBarCrop_Outbuf, + .Setup = MFC_Decoder_Setup_Outbuf, + .Run = MFC_Decoder_Run_Outbuf, + .Stop = MFC_Decoder_Stop_Outbuf, + .Enqueue = MFC_Decoder_Enqueue_Outbuf, + .Enqueue_All = NULL, + .Dequeue = MFC_Decoder_Dequeue_Outbuf, + .Register = MFC_Decoder_Register_Outbuf, + .Clear_RegisteredBuffer = MFC_Decoder_Clear_RegisteredBuffer_Outbuf, + .Clear_Queue = MFC_Decoder_Clear_Queued_Outbuf, + .Cleanup_Buffer = MFC_Decoder_Cleanup_Buffer_Outbuf, + .Apply_RegisteredBuffer = MFC_Decoder_Apply_RegisteredBuffer_Outbuf, + .ExtensionEnqueue = MFC_Decoder_ExtensionEnqueue_Outbuf, + .ExtensionDequeue = MFC_Decoder_ExtensionDequeue_Outbuf, +}; + +ExynosVideoErrorType MFC_Exynos_Video_GetInstInfo_Decoder( + ExynosVideoInstInfo *pVideoInstInfo) +{ + CodecOSALVideoContext videoCtx; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + int codecRet = 0; + int mode = 0, version = 0; + + if (pVideoInstInfo == NULL) { + ALOGE("%s: bad parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&videoCtx, 0, sizeof(videoCtx)); + +#ifdef USE_HEVC_HWIP + if (pVideoInstInfo->eCodecType == VIDEO_CODING_HEVC) + codecRet = Codec_OSAL_DevOpen(VIDEO_HEVC_DECODER_NAME, O_RDWR, &videoCtx); + else +#endif + codecRet = Codec_OSAL_DevOpen(VIDEO_MFC_DECODER_NAME, O_RDWR, &videoCtx); + + if (codecRet < 0) { + ALOGE("%s: Failed to open decoder device", __FUNCTION__); + ret = VIDEO_ERROR_OPENFAIL; + goto EXIT; + } + + if (Codec_OSAL_GetControl(&videoCtx, CODEC_OSAL_CID_VIDEO_GET_VERSION_INFO, &version) != 0) { + ALOGW("%s: HW version information is not available", __FUNCTION__); +#ifdef USE_HEVC_HWIP + if (pVideoInstInfo->eCodecType == VIDEO_CODING_HEVC) + pVideoInstInfo->HwVersion = (int)HEVC_10; + else +#endif + pVideoInstInfo->HwVersion = (int)MFC_65; + } else { + pVideoInstInfo->HwVersion = version; + } + + if (Codec_OSAL_GetControl(&videoCtx, CODEC_OSAL_CID_VIDEO_GET_EXT_INFO, &mode) != 0) { + pVideoInstInfo->supportInfo.dec.bSkypeSupport = VIDEO_FALSE; + goto EXIT; + } + + pVideoInstInfo->supportInfo.dec.bPrioritySupport = (mode & (0x1 << 23))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->bVideoBufFlagCtrl = (mode & (0x1 << 16))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.dec.bOperatingRateSupport = (mode & (0x1 << 8))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.dec.bFrameErrorTypeSupport = (mode & (0x1 << 7))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.dec.bDrvDPBManageSupport = (mode & (0x1 << 5))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.dec.bHDRDynamicInfoSupport = (mode & (0x1 << 4))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.dec.bSkypeSupport = (mode & (0x1 << 3))? VIDEO_TRUE:VIDEO_FALSE; + + pVideoInstInfo->SwVersion = 0; + if (pVideoInstInfo->supportInfo.dec.bSkypeSupport == VIDEO_TRUE) { + int swVersion = 0; + + if (Codec_OSAL_GetControl(&videoCtx, CODEC_OSAL_CID_VIDEO_GET_DRIVER_VERSION, &swVersion) != 0) { + ALOGE("%s: g_ctrl is failed(CODEC_OSAL_CID_VIDEO_GET_DRIVER_VERSION)", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pVideoInstInfo->SwVersion = (unsigned int)swVersion; + } + + __Set_SupportFormat(pVideoInstInfo); + +EXIT: + Codec_OSAL_DevClose(&videoCtx); + + return ret; +} + +ExynosVideoErrorType MFC_Exynos_Video_Register_Decoder( + ExynosVideoDecOps *pDecOps, + ExynosVideoDecBufferOps *pInbufOps, + ExynosVideoDecBufferOps *pOutbufOps) +{ + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if ((pDecOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + defDecOps.nSize = sizeof(defDecOps); + defInbufOps.nSize = sizeof(defInbufOps); + defOutbufOps.nSize = sizeof(defOutbufOps); + + memcpy((char *)pDecOps + sizeof(pDecOps->nSize), (char *)&defDecOps + sizeof(defDecOps.nSize), + pDecOps->nSize - sizeof(pDecOps->nSize)); + + memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize), + pInbufOps->nSize - sizeof(pInbufOps->nSize)); + + memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize), + pOutbufOps->nSize - sizeof(pOutbufOps->nSize)); + +EXIT: + return ret; +} diff --git a/videocodec/enc/ExynosVideoEncoder.c b/videocodec/enc/ExynosVideoEncoder.c new file mode 100644 index 0000000..c518e6e --- /dev/null +++ b/videocodec/enc/ExynosVideoEncoder.c @@ -0,0 +1,3662 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file ExynosVideoEncoder.c + * @brief + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.01.15: Initial Version + * 2016.01.28: Update Version to support OSAL + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "ExynosVideoApi.h" +#include "ExynosVideoEnc.h" +#include "ExynosVideo_OSAL_Enc.h" +#include "OMX_Core.h" + +/* #define LOG_NDEBUG 0 */ +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "ExynosVideoEncoder" + +#define MAX_INPUTBUFFER_COUNT 32 +#define MAX_OUTPUTBUFFER_COUNT 32 + +static struct { + int eColorFormat; + int nFormatFlag; +} SBWC_LOSSY_TABLE[] = { + /* 8Bit multi plane format */ + {VIDEO_COLORFORMAT_NV12M_SBWC_L50 , 0}, + {VIDEO_COLORFORMAT_NV12M_SBWC_L75 , 2}, + /* 10Bit multi plane format */ + {VIDEO_COLORFORMAT_NV12M_10B_SBWC_L60, 1}, + {VIDEO_COLORFORMAT_NV12M_10B_SBWC_L80, 3}, + /* 8Bit single plane format */ + {VIDEO_COLORFORMAT_NV12_SBWC_L50 , 0}, + {VIDEO_COLORFORMAT_NV12_10B_SBWC_L60, 2}, + /* 10Bit single plane format */ + {VIDEO_COLORFORMAT_NV12_10B_SBWC_L60, 1}, + {VIDEO_COLORFORMAT_NV12_10B_SBWC_L80, 3}, +}; + +static struct { + int eSBWCFormat; + int eNormalFormat; +} SBWC_NONCOMP_TABLE[] = { + {VIDEO_COLORFORMAT_NV12_SBWC, VIDEO_COLORFORMAT_NV12}, + {VIDEO_COLORFORMAT_NV12M_SBWC, VIDEO_COLORFORMAT_NV12M}, + {VIDEO_COLORFORMAT_NV12_10B_SBWC, VIDEO_COLORFORMAT_NV12_S10B}, + {VIDEO_COLORFORMAT_NV12M_10B_SBWC, VIDEO_COLORFORMAT_NV12M_P010}, + {VIDEO_COLORFORMAT_NV21M_SBWC, VIDEO_COLORFORMAT_NV21M}, + {VIDEO_COLORFORMAT_NV21M_10B_SBWC, VIDEO_COLORFORMAT_NV21M_P010}, +}; + +/* + * [Common] __Set_SupportFormat + */ +static void __Set_SupportFormat(ExynosVideoInstInfo *pVideoInstInfo) +{ + int nLastIndex = 0; + + if (pVideoInstInfo == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + goto EXIT; + } + + memset(pVideoInstInfo->supportFormat, (int)VIDEO_COLORFORMAT_UNKNOWN, sizeof(pVideoInstInfo->supportFormat)); + + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M; + + switch ((int)pVideoInstInfo->HwVersion) { + case MFC_1501: + case MFC_150: + case MFC_1410: /* NV12, NV21, I420, YV12, BGRA, RGBA, ARGB, NV12_S10B, NV21_S10B, SBWC(NV12, NV21, NV12_10B, NV21_10B), SBWC Lossy */ + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_YV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_BGRA8888; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_RGBA8888; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_ARGB8888; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_SBWC_L50; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_SBWC_L75; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_SBWC_L50; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_SBWC_L75; + + if ((pVideoInstInfo->eCodecType == VIDEO_CODING_HEVC) || + (pVideoInstInfo->eCodecType == VIDEO_CODING_VP9)) { + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_P010; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_P010; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_10B_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_10B_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_10B_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_10B_SBWC_L40; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_10B_SBWC_L60; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_10B_SBWC_L80; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_10B_SBWC_L40; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_10B_SBWC_L60; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_10B_SBWC_L80; + } + break; + case MFC_140: /* NV12, NV21, I420, YV12, BGRA, RGBA, ARGB, NV12_S10B, NV21_S10B, SBWC(NV12, NV21, NV12_10B, NV21_10B) */ + case MFC_1400: + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_YV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_BGRA8888; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_RGBA8888; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_ARGB8888; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_SBWC; + + if ((pVideoInstInfo->eCodecType == VIDEO_CODING_HEVC) || + (pVideoInstInfo->eCodecType == VIDEO_CODING_VP9)) { + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_P010; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_P010; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_10B_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_10B_SBWC; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_10B_SBWC; + } + break; + case MFC_130: /* NV12, NV21, I420, YV12, NV12_S10B, NV21_S10B */ + case MFC_120: + case MFC_1220: + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_YV12M; + + if ((pVideoInstInfo->eCodecType == VIDEO_CODING_HEVC) || + (pVideoInstInfo->eCodecType == VIDEO_CODING_VP9)) { + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_P010; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_S10B; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV21M_P010; + } + break; + case MFC_110: /* NV12, NV21, I420, YV12 */ + case MFC_1120: + case MFC_101: + case MFC_100: + case MFC_1010: + case MFC_1011: + case MFC_1020: + case MFC_1021: + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_YV12M; + break; + case MFC_90: /* NV12, NV21, BGRA, RGBA, I420, YV12, ARGB */ + case MFC_80: +#ifdef USE_HEVC_HWIP + case HEVC_10: +#endif + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_BGRA8888; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_RGBA8888; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_YV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_ARGB8888; + break; + case MFC_723: /* NV12, NV21, BGRA, RGBA, I420, YV12, ARGB, NV12T */ + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_BGRA8888; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_RGBA8888; + case MFC_72: /* NV12, NV21, I420, YV12, ARGB, NV12T */ + case MFC_77: + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_I420M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_YV12M; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_ARGB8888; + case MFC_78: /* NV12, NV21, NV12T */ + case MFC_65: + case MFC_61: + case MFC_51: + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12_TILED; + pVideoInstInfo->supportFormat[nLastIndex++] = VIDEO_COLORFORMAT_NV12M_TILED; + break; + default: + break; + } + +EXIT: + return; +} + +/* + * [Encoder OPS] Init + */ +static void *MFC_Encoder_Init(ExynosVideoInstInfo *pVideoInfo) +{ + CodecOSALVideoContext *pCtx = NULL; + pthread_mutex_t *pMutex = NULL; + + int ret = 0; + int hIonClient = -1; + int fd = -1; + + if (pVideoInfo == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + goto EXIT_ALLOC_FAIL; + } + + pCtx = (CodecOSALVideoContext *)malloc(sizeof(*pCtx)); + if (pCtx == NULL) { + ALOGE("%s: Failed to allocate encoder context buffer", __FUNCTION__); + goto EXIT_ALLOC_FAIL; + } + + memset(pCtx, 0, sizeof(*pCtx)); + + pCtx->videoCtx.hDevice = -1; + pCtx->videoCtx.hIONHandle = -1; + pCtx->videoCtx.specificInfo.enc.nTemporalLayerShareBufferFD = -1; + pCtx->videoCtx.specificInfo.enc.nRoiShareBufferFD = -1; + pCtx->videoCtx.specificInfo.enc.nHDRInfoShareBufferFD = -1; + + /* node open */ +#ifdef USE_HEVC_HWIP + if (pVideoInfo->eCodecType == VIDEO_CODING_HEVC) { + if (pVideoInfo->eSecurityType == VIDEO_SECURE) + ret = Codec_OSAL_DevOpen(VIDEO_HEVC_SECURE_ENCODER_NAME, O_RDWR, pCtx); + else + ret = Codec_OSAL_DevOpen(VIDEO_HEVC_ENCODER_NAME, O_RDWR, pCtx); + } else +#endif + { + if (pVideoInfo->bOTFMode == VIDEO_TRUE) { + if (pVideoInfo->eSecurityType == VIDEO_SECURE) + ret = Codec_OSAL_DevOpen(VIDEO_MFC_OTF_SECURE_ENCODER_NAME, O_RDWR, pCtx); + else + ret = Codec_OSAL_DevOpen(VIDEO_MFC_OTF_ENCODER_NAME, O_RDWR, pCtx); + } else { + if (pVideoInfo->eSecurityType == VIDEO_SECURE) + ret = Codec_OSAL_DevOpen(VIDEO_MFC_SECURE_ENCODER_NAME, O_RDWR, pCtx); + else + ret = Codec_OSAL_DevOpen(VIDEO_MFC_ENCODER_NAME, O_RDWR, pCtx); + } + } + + if (ret < 0) { + ALOGE("%s: Failed to open encoder device", __FUNCTION__); + goto EXIT_OPEN_FAIL; + } + + memcpy(&pCtx->videoCtx.instInfo, pVideoInfo, sizeof(pCtx->videoCtx.instInfo)); + + ALOGV("%s: MFC version is %x", __FUNCTION__, pCtx->videoCtx.instInfo.HwVersion); + + if (Codec_OSAL_QueryCap(pCtx) != 0) { + ALOGE("%s: Failed to QueryCap", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + + pCtx->videoCtx.bStreamonInbuf = VIDEO_FALSE; + pCtx->videoCtx.bStreamonOutbuf = VIDEO_FALSE; + + /* mutex for input */ + pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + if (pMutex == NULL) { + ALOGE("%s: Failed to allocate mutex about input buffer", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + if (pthread_mutex_init(pMutex, NULL) != 0) { + free(pMutex); + goto EXIT_QUERYCAP_FAIL; + } + pCtx->videoCtx.pInMutex = (void*)pMutex; + + /* mutex for output */ + pMutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); + if (pMutex == NULL) { + ALOGE("%s: Failed to allocate mutex about output buffer", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + if (pthread_mutex_init(pMutex, NULL) != 0) { + free(pMutex); + goto EXIT_QUERYCAP_FAIL; + } + pCtx->videoCtx.pOutMutex = (void*)pMutex; + + /* for shared memory : temporal svc info, ROI info */ + hIonClient = exynos_ion_open(); + + if (hIonClient < 0) { + ALOGE("%s: Failed to create ion_client", __FUNCTION__); + pCtx->videoCtx.hIONHandle = -1; + goto EXIT_QUERYCAP_FAIL; + } + + pCtx->videoCtx.hIONHandle = hIonClient; + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_TRUE) { + fd = exynos_ion_alloc(pCtx->videoCtx.hIONHandle, sizeof(TemporalLayerShareBuffer), + EXYNOS_ION_HEAP_SYSTEM_MASK, ION_FLAG_CACHED); + if (fd < 0) { + ALOGE("%s: Failed to exynos_ion_alloc() for nTemporalLayerShareBufferFD", __FUNCTION__); + pCtx->videoCtx.specificInfo.enc.nTemporalLayerShareBufferFD = -1; + goto EXIT_QUERYCAP_FAIL; + } + pCtx->videoCtx.specificInfo.enc.nTemporalLayerShareBufferFD = fd; + pCtx->videoCtx.specificInfo.enc.pTemporalLayerShareBufferAddr = Codec_OSAL_MemoryMap(NULL, sizeof(TemporalLayerShareBuffer), + PROT_READ | PROT_WRITE, MAP_SHARED, pCtx->videoCtx.specificInfo.enc.nTemporalLayerShareBufferFD, 0); + if (pCtx->videoCtx.specificInfo.enc.pTemporalLayerShareBufferAddr == MAP_FAILED) { + ALOGE("%s: Failed to mmap for nTemporalLayerShareBufferFD", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + + memset(pCtx->videoCtx.specificInfo.enc.pTemporalLayerShareBufferAddr, 0, sizeof(TemporalLayerShareBuffer)); + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bRoiInfoSupport == VIDEO_TRUE) { + fd = exynos_ion_alloc(pCtx->videoCtx.hIONHandle, sizeof(RoiInfoShareBuffer), + EXYNOS_ION_HEAP_SYSTEM_MASK, ION_FLAG_CACHED); + if (fd < 0) { + ALOGE("%s: Failed to exynos_ion_alloc() for nRoiShareBufferFD", __FUNCTION__); + pCtx->videoCtx.specificInfo.enc.nRoiShareBufferFD = -1; + goto EXIT_QUERYCAP_FAIL; + } + pCtx->videoCtx.specificInfo.enc.nRoiShareBufferFD = fd; + pCtx->videoCtx.specificInfo.enc.pRoiShareBufferAddr = Codec_OSAL_MemoryMap(NULL, sizeof(RoiInfoShareBuffer), + PROT_READ | PROT_WRITE, MAP_SHARED, pCtx->videoCtx.specificInfo.enc.nRoiShareBufferFD, 0); + if (pCtx->videoCtx.specificInfo.enc.pRoiShareBufferAddr == MAP_FAILED) { + ALOGE("%s: Failed to mmap for nRoiShareBufferFD", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + + memset(pCtx->videoCtx.specificInfo.enc.pRoiShareBufferAddr, 0, sizeof(RoiInfoShareBuffer)); + } + + /* for HDR Dynamic Info */ + if (pCtx->videoCtx.instInfo.supportInfo.enc.bHDRDynamicInfoSupport == VIDEO_TRUE) { + fd = exynos_ion_alloc(pCtx->videoCtx.hIONHandle, sizeof(ExynosVideoHdrDynamic) * VIDEO_BUFFER_MAX_NUM, + EXYNOS_ION_HEAP_SYSTEM_MASK, ION_FLAG_CACHED); + if (fd < 0) { + ALOGE("%s: Failed to exynos_ion_alloc() for nHDRInfoShareBufferFD", __FUNCTION__); + pCtx->videoCtx.specificInfo.enc.nHDRInfoShareBufferFD = -1; + goto EXIT_QUERYCAP_FAIL; + } + + pCtx->videoCtx.specificInfo.enc.nHDRInfoShareBufferFD = fd; + + pCtx->videoCtx.specificInfo.enc.pHDRInfoShareBufferAddr = + Codec_OSAL_MemoryMap(NULL, (sizeof(ExynosVideoHdrDynamic) * VIDEO_BUFFER_MAX_NUM), + PROT_READ | PROT_WRITE, MAP_SHARED, + pCtx->videoCtx.specificInfo.enc.nHDRInfoShareBufferFD, 0); + if (pCtx->videoCtx.specificInfo.enc.pHDRInfoShareBufferAddr == MAP_FAILED) { + ALOGE("%s: Failed to mmap for pHDRInfoShareBufferAddr", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + + memset(pCtx->videoCtx.specificInfo.enc.pHDRInfoShareBufferAddr, + 0, sizeof(ExynosVideoHdrDynamic) * VIDEO_BUFFER_MAX_NUM); + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_SET_HDR_USER_SHARED_HANDLE, + pCtx->videoCtx.specificInfo.enc.nHDRInfoShareBufferFD) != 0) { + ALOGE("[%s] Failed to Codec_OSAL_SetControl(CODEC_OSAL_CID_VIDEO_SET_HDR_USER_SHARED_HANDLE)", __FUNCTION__); + goto EXIT_QUERYCAP_FAIL; + } + } + + if (pCtx->videoCtx.instInfo.bVideoBufFlagCtrl == VIDEO_TRUE) { + pCtx->videoCtx.bVideoBufFlagCtrl = VIDEO_TRUE; + } + + return (void *)pCtx; + +EXIT_QUERYCAP_FAIL: + if (pCtx->videoCtx.pInMutex != NULL) { + pthread_mutex_destroy(pCtx->videoCtx.pInMutex); + free(pCtx->videoCtx.pInMutex); + } + + if (pCtx->videoCtx.pOutMutex != NULL) { + pthread_mutex_destroy(pCtx->videoCtx.pOutMutex); + free(pCtx->videoCtx.pOutMutex); + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_TRUE) { + if (pCtx->videoCtx.specificInfo.enc.pTemporalLayerShareBufferAddr != NULL) { + Codec_OSAL_MemoryUnmap(pCtx->videoCtx.specificInfo.enc.pTemporalLayerShareBufferAddr, sizeof(TemporalLayerShareBuffer)); + pCtx->videoCtx.specificInfo.enc.pTemporalLayerShareBufferAddr = NULL; + } + + /* free a ion_buffer */ + if (pCtx->videoCtx.specificInfo.enc.nTemporalLayerShareBufferFD >= 0) { + close(pCtx->videoCtx.specificInfo.enc.nTemporalLayerShareBufferFD); + pCtx->videoCtx.specificInfo.enc.nTemporalLayerShareBufferFD = -1; + } + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bRoiInfoSupport == VIDEO_TRUE) { + if (pCtx->videoCtx.specificInfo.enc.pRoiShareBufferAddr != NULL) { + Codec_OSAL_MemoryUnmap(pCtx->videoCtx.specificInfo.enc.pRoiShareBufferAddr, sizeof(RoiInfoShareBuffer)); + pCtx->videoCtx.specificInfo.enc.pRoiShareBufferAddr = NULL; + } + + /* free a ion_buffer */ + if (pCtx->videoCtx.specificInfo.enc.nRoiShareBufferFD >= 0) { + close(pCtx->videoCtx.specificInfo.enc.nRoiShareBufferFD); + pCtx->videoCtx.specificInfo.enc.nRoiShareBufferFD = -1; + } + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bHDRDynamicInfoSupport == VIDEO_TRUE) { + if (pCtx->videoCtx.specificInfo.enc.pHDRInfoShareBufferAddr != NULL) { + Codec_OSAL_MemoryUnmap(pCtx->videoCtx.specificInfo.enc.pHDRInfoShareBufferAddr, + sizeof(ExynosVideoHdrDynamic) * VIDEO_BUFFER_MAX_NUM); + pCtx->videoCtx.specificInfo.enc.pHDRInfoShareBufferAddr = NULL; + } + + /* free a ion_buffer */ + if (pCtx->videoCtx.specificInfo.enc.nHDRInfoShareBufferFD >= 0) { + close(pCtx->videoCtx.specificInfo.enc.nHDRInfoShareBufferFD); + pCtx->videoCtx.specificInfo.enc.nHDRInfoShareBufferFD = -1; + } + } + + /* free a ion_client */ + if (pCtx->videoCtx.hIONHandle >= 0) { + exynos_ion_close(pCtx->videoCtx.hIONHandle); + pCtx->videoCtx.hIONHandle = -1; + } + + Codec_OSAL_DevClose(pCtx); + +EXIT_OPEN_FAIL: + free(pCtx); + +EXIT_ALLOC_FAIL: + return NULL; +} + +/* + * [Encoder OPS] Finalize + */ +static ExynosVideoErrorType MFC_Encoder_Finalize(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoPlane *pVideoPlane = NULL; + pthread_mutex_t *pMutex = NULL; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i, j; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_TRUE) { + if (pCtx->videoCtx.specificInfo.enc.pTemporalLayerShareBufferAddr != NULL) { + Codec_OSAL_MemoryUnmap(pCtx->videoCtx.specificInfo.enc.pTemporalLayerShareBufferAddr, sizeof(TemporalLayerShareBuffer)); + pCtx->videoCtx.specificInfo.enc.pTemporalLayerShareBufferAddr = NULL; + } + + /* free a ion_buffer */ + if (pCtx->videoCtx.specificInfo.enc.nTemporalLayerShareBufferFD >= 0) { + close(pCtx->videoCtx.specificInfo.enc.nTemporalLayerShareBufferFD); + pCtx->videoCtx.specificInfo.enc.nTemporalLayerShareBufferFD = -1; + } + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bRoiInfoSupport == VIDEO_TRUE) { + if (pCtx->videoCtx.specificInfo.enc.pRoiShareBufferAddr != NULL) { + Codec_OSAL_MemoryUnmap(pCtx->videoCtx.specificInfo.enc.pRoiShareBufferAddr, sizeof(RoiInfoShareBuffer)); + pCtx->videoCtx.specificInfo.enc.pRoiShareBufferAddr = NULL; + } + + /* free a ion_buffer */ + if (pCtx->videoCtx.specificInfo.enc.nRoiShareBufferFD >= 0) { + close(pCtx->videoCtx.specificInfo.enc.nRoiShareBufferFD); + pCtx->videoCtx.specificInfo.enc.nRoiShareBufferFD = -1; + } + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bHDRDynamicInfoSupport == VIDEO_TRUE) { + if (pCtx->videoCtx.specificInfo.enc.pHDRInfoShareBufferAddr != NULL) { + Codec_OSAL_MemoryUnmap(pCtx->videoCtx.specificInfo.enc.pHDRInfoShareBufferAddr, + sizeof(ExynosVideoHdrDynamic) * VIDEO_BUFFER_MAX_NUM); + pCtx->videoCtx.specificInfo.enc.pHDRInfoShareBufferAddr = NULL; + } + + /* free a ion_buffer */ + if (pCtx->videoCtx.specificInfo.enc.nHDRInfoShareBufferFD >= 0) { + close(pCtx->videoCtx.specificInfo.enc.nHDRInfoShareBufferFD); + pCtx->videoCtx.specificInfo.enc.nHDRInfoShareBufferFD = -1; + } + } + + /* free a ion_client */ + if (pCtx->videoCtx.hIONHandle >= 0) { + exynos_ion_close(pCtx->videoCtx.hIONHandle); + pCtx->videoCtx.hIONHandle = -1; + } + + if (pCtx->videoCtx.pOutMutex != NULL) { + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pOutMutex; + pthread_mutex_destroy(pMutex); + free(pMutex); + pCtx->videoCtx.pOutMutex = NULL; + } + + if (pCtx->videoCtx.pInMutex != NULL) { + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pInMutex; + pthread_mutex_destroy(pMutex); + free(pMutex); + pCtx->videoCtx.pInMutex = NULL; + } + + if (pCtx->videoCtx.bShareInbuf == VIDEO_FALSE) { + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + for (j = 0; j < pCtx->videoCtx.nInbufPlanes; j++) { + pVideoPlane = &pCtx->videoCtx.pInbuf[i].planes[j]; + if (pVideoPlane->addr != NULL) { + Codec_OSAL_MemoryUnmap(pVideoPlane->addr, pVideoPlane->allocSize); + pVideoPlane->addr = NULL; + pVideoPlane->allocSize = 0; + pVideoPlane->dataSize = 0; + } + + pCtx->videoCtx.pInbuf[i].pGeometry = NULL; + pCtx->videoCtx.pInbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pInbuf[i].bRegistered = VIDEO_FALSE; + } + } + } + + if (pCtx->videoCtx.bShareOutbuf == VIDEO_FALSE) { + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + for (j = 0; j < pCtx->videoCtx.nOutbufPlanes; j++) { + pVideoPlane = &pCtx->videoCtx.pOutbuf[i].planes[j]; + if (pVideoPlane->addr != NULL) { + Codec_OSAL_MemoryUnmap(pVideoPlane->addr, pVideoPlane->allocSize); + pVideoPlane->addr = NULL; + pVideoPlane->allocSize = 0; + pVideoPlane->dataSize = 0; + } + + pCtx->videoCtx.pOutbuf[i].pGeometry = NULL; + pCtx->videoCtx.pOutbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pOutbuf[i].bRegistered = VIDEO_FALSE; + } + } + } + + if (pCtx->videoCtx.pInbuf != NULL) { + free(pCtx->videoCtx.pInbuf); + pCtx->videoCtx.pInbuf = NULL; + } + + if (pCtx->videoCtx.pOutbuf != NULL) { + free(pCtx->videoCtx.pOutbuf); + pCtx->videoCtx.pOutbuf = NULL; + } + + Codec_OSAL_DevClose(pCtx); + + free(pCtx); + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Extended Control + */ +static ExynosVideoErrorType MFC_Encoder_Set_EncParam ( + void *pHandle, + ExynosVideoEncParam *pEncParam) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if ((pCtx == NULL) || + (pEncParam == NULL)) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControls(pCtx, CODEC_OSAL_CID_ENC_SET_PARAMS, (void *)pEncParam) != 0) { + ALOGE("%s: Failed to SetControls", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Frame Tag + */ +static ExynosVideoErrorType MFC_Encoder_Set_FrameTag( + void *pHandle, + int nFrameTag) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_FRAME_TAG, nFrameTag) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, nFrameTag); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Get Frame Tag + */ +static int MFC_Encoder_Get_FrameTag(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + + int nFrameTag = -1; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (Codec_OSAL_GetControl(pCtx, CODEC_OSAL_CID_VIDEO_FRAME_TAG, &nFrameTag) != 0) { + ALOGE("%s: Failed to GetControl(val : 0x%x)", __FUNCTION__, nFrameTag); + goto EXIT; + } + +EXIT: + return nFrameTag; +} + +/* + * [Encoder OPS] Set Frame Type + */ +static ExynosVideoErrorType MFC_Encoder_Set_FrameType( + void *pHandle, + ExynosVideoFrameType eFrameType) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_FRAME_TYPE, eFrameType) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, eFrameType); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Frame Rate + */ +static ExynosVideoErrorType MFC_Encoder_Set_FrameRate( + void *pHandle, + int nFramerate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_FRAME_RATE, nFramerate) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, nFramerate); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Bit Rate + */ +static ExynosVideoErrorType MFC_Encoder_Set_BitRate( + void *pHandle, + int nBitrate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_BIT_RATE, nBitrate) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, nBitrate); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Quantization Min/Max + */ +static ExynosVideoErrorType MFC_Encoder_Set_QuantizationRange( + void *pHandle, + ExynosVideoQPRange qpRange) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (qpRange.QpMin_I > qpRange.QpMax_I) { + ALOGE("%s: QP(I) range(%d, %d) is wrong", __FUNCTION__, qpRange.QpMin_I, qpRange.QpMax_I); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControls(pCtx, CODEC_OSAL_CID_ENC_QP_RANGE, &qpRange) != 0) { + ALOGE("%s: Failed to SetControl", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Frame Skip + */ +static ExynosVideoErrorType MFC_Encoder_Set_FrameSkip( + void *pHandle, + int nFrameSkip) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_FRAME_SKIP_MODE, nFrameSkip) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, nFrameSkip); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set IDR Period + */ +static ExynosVideoErrorType MFC_Encoder_Set_IDRPeriod( + void *pHandle, + int nIDRPeriod) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_IDR_PERIOD, (nIDRPeriod < 0)? 0:nIDRPeriod) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, nIDRPeriod); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Slice Mode + */ +static ExynosVideoErrorType MFC_Encoder_Set_SliceMode( + void *pHandle, + int nSliceMode, + int nSliceArgument) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int value; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + value = (((nSliceMode << 16) & 0xffff0000) | (nSliceArgument & 0xffff)); + +#if 0 // TODO + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_SLICE_MODE, value) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, value); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } +#else + ALOGW("%s: not implemented yet", __FUNCTION__); +#endif + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Enable Prepend SPS and PPS to every IDR Frames + */ +static ExynosVideoErrorType MFC_Encoder_Enable_PrependSpsPpsToIdr(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + switch ((int)pCtx->videoCtx.instInfo.eCodecType) { + case VIDEO_CODING_AVC: + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_H264_PREPEND_SPSPPS_TO_IDR, 1) != 0) { + ALOGE("%s: Failed to SetControl", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + break; + case VIDEO_CODING_HEVC: + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_HEVC_PREPEND_SPSPPS_TO_IDR, 1) != 0) { + ALOGE("%s: Failed to SetControl", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + break; + default: + ALOGE("%s: codec(%x) can't support PrependSpsPpsToIdr", __FUNCTION__, pCtx->videoCtx.instInfo.eCodecType); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Qos Ratio + */ +static ExynosVideoErrorType MFC_Encoder_Set_QosRatio( + void *pHandle, + int nRatio) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_QOS_RATIO, nRatio) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, nRatio); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Layer Change + */ +static ExynosVideoErrorType MFC_Encoder_Set_LayerChange( + void *pHandle, + TemporalLayerShareBuffer TemporalSVC) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + TemporalLayerShareBuffer *pTLSB = NULL; + + unsigned int CID = 0; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + pTLSB = (TemporalLayerShareBuffer *)pCtx->videoCtx.specificInfo.enc.pTemporalLayerShareBufferAddr; + + switch ((int)pCtx->videoCtx.instInfo.eCodecType) { + case VIDEO_CODING_AVC: + CID = CODEC_OSAL_CID_ENC_H264_TEMPORAL_SVC_LAYER_CH; + break; + case VIDEO_CODING_HEVC: + CID = CODEC_OSAL_CID_ENC_HEVC_TEMPORAL_SVC_LAYER_CH; + break; + case VIDEO_CODING_VP8: + CID = CODEC_OSAL_CID_ENC_VP8_TEMPORAL_SVC_LAYER_CH; + break; + case VIDEO_CODING_VP9: + CID = CODEC_OSAL_CID_ENC_VP9_TEMPORAL_SVC_LAYER_CH; + break; + default: + ALOGE("%s: this codec type is not supported(%x), F/W ver(%x)", + __FUNCTION__, pCtx->videoCtx.instInfo.eCodecType, pCtx->videoCtx.instInfo.HwVersion); + ret = VIDEO_ERROR_NOSUPPORT; + goto EXIT; + break; + } + + memcpy(pTLSB, &TemporalSVC, sizeof(TemporalLayerShareBuffer)); + if (Codec_OSAL_SetControl(pCtx, CID, + pCtx->videoCtx.specificInfo.enc.nTemporalLayerShareBufferFD) != 0) { + ALOGE("%s: Failed to SetControl", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Dynamic QP Control + */ +static ExynosVideoErrorType MFC_Encoder_Set_DynamicQpControl( + void *pHandle, + int nQp) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_SET_CONFIG_QP, nQp) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, nQp); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Mark LTR-frame + */ +static ExynosVideoErrorType MFC_Encoder_Set_MarkLTRFrame( + void *pHandle, + int nLongTermFrmIdx) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_H264_LTR_MARK_INDEX, nLongTermFrmIdx) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, nLongTermFrmIdx); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Used LTR-frame + */ +static ExynosVideoErrorType MFC_Encoder_Set_UsedLTRFrame( + void *pHandle, + int nUsedLTRFrameNum) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_H264_LTR_USE_INDEX, nUsedLTRFrameNum) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, nUsedLTRFrameNum); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Base PID + */ +static ExynosVideoErrorType MFC_Encoder_Set_BasePID( + void *pHandle, + int nPID) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_H264_LTR_BASE_PID, nPID) != 0) { + ALOGE("%s: Failed to SetControl(val : 0x%x)", __FUNCTION__, nPID); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Roi Information + */ +static ExynosVideoErrorType MFC_Encoder_Set_RoiInfo( + void *pHandle, + RoiInfoShareBuffer *pRoiInfo) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + RoiInfoShareBuffer *pRISB = NULL; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + pRISB = (RoiInfoShareBuffer *)pCtx->videoCtx.specificInfo.enc.pRoiShareBufferAddr; + if (pCtx->videoCtx.instInfo.supportInfo.enc.bRoiInfoSupport == VIDEO_FALSE) { + ALOGE("%s: ROI Info setting is not supported :: codec type(%x), F/W ver(%x)", + __FUNCTION__, pCtx->videoCtx.instInfo.eCodecType, pCtx->videoCtx.instInfo.HwVersion); + ret = VIDEO_ERROR_NOSUPPORT; + goto EXIT; + } + + memcpy(pRISB, pRoiInfo, sizeof(RoiInfoShareBuffer)); + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_ROI_INFO, + pCtx->videoCtx.specificInfo.enc.nRoiShareBufferFD) != 0) { + ALOGE("%s: Failed to SetControl", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Enable Weighted Prediction Encoding + */ +static ExynosVideoErrorType MFC_Encoder_Enable_WeightedPrediction(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_WP_ENABLE, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Y-SUM Data + */ +static ExynosVideoErrorType MFC_Encoder_Set_YSumData( + void *pHandle, + unsigned int nHighData, + unsigned int nLowData) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + unsigned long long nYSumData = 0; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + nYSumData = (((unsigned long long)nHighData) << 32) | nLowData; /* 64bit data */ + + /* MFC D/D just want a LowData */ + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_YSUM_DATA, (int)nLowData) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set I-frame ratio (It is applied only CBR mode) + */ +static ExynosVideoErrorType MFC_Encoder_Set_IFrameRatio( + void *pHandle, + int nRatio) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + switch ((int)pCtx->videoCtx.instInfo.eCodecType) { + case VIDEO_CODING_AVC: + case VIDEO_CODING_HEVC: + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_I_FRAME_RATIO, nRatio) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + ret = VIDEO_ERROR_NONE; + break; + default: + ALOGE("%s: codec(%x) can't support Set_IFrameRatio", __FUNCTION__, pCtx->videoCtx.instInfo.eCodecType); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Color Aspects + */ +ExynosVideoErrorType MFC_Encoder_Set_ColorAspects( + void *pHandle, + ExynosVideoColorAspects *pColorAspects) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if ((pCtx == NULL) || + (pColorAspects == NULL)) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bColorAspectsSupport == VIDEO_FALSE) { + ALOGE("%s: can't support Set_ColorAspects. // codec type(%x), F/W ver(%x)", + __FUNCTION__, pCtx->videoCtx.instInfo.eCodecType, pCtx->videoCtx.instInfo.HwVersion); + ret = VIDEO_ERROR_NOSUPPORT; + goto EXIT; + } + + if (Codec_OSAL_SetControls(pCtx, CODEC_OSAL_CID_ENC_COLOR_ASPECTS, (void *)pColorAspects) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + memcpy(&(pCtx->videoCtx.inbufGeometry.HdrInfo.sColorAspects), pColorAspects, sizeof(ExynosVideoColorAspects)); + ret = VIDEO_ERROR_NONE; + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Enable Adaptive Layer Bitrate mode + */ +static ExynosVideoErrorType MFC_Encoder_Enable_AdaptiveLayerBitrate( + void *pHandle, + int bEnable) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + switch ((int)pCtx->videoCtx.instInfo.eCodecType) { + case VIDEO_CODING_AVC: + case VIDEO_CODING_HEVC: + case VIDEO_CODING_VP8: + case VIDEO_CODING_VP9: + if (pCtx->videoCtx.instInfo.supportInfo.enc.bAdaptiveLayerBitrateSupport == VIDEO_TRUE) { + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_ENABLE_ADAPTIVE_LAYER_BITRATE, bEnable) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + } + + ret = VIDEO_ERROR_NONE; + break; + default: + ALOGE("%s: codec(%x) can't support Enable_AdaptiveLayerBitrate", __FUNCTION__, pCtx->videoCtx.instInfo.eCodecType); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set HDR Static Info + */ +ExynosVideoErrorType MFC_Encoder_Set_HDRStaticInfo( + void *pHandle, + ExynosVideoHdrStatic *pHDRStaticInfo) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if ((pCtx == NULL) || + (pHDRStaticInfo == NULL)) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bHDRStaticInfoSupport == VIDEO_FALSE) { + ALOGE("%s: can't support Set_HDRStaticInfo. // codec type(%x), F/W ver(%x)", + __FUNCTION__, pCtx->videoCtx.instInfo.eCodecType, pCtx->videoCtx.instInfo.HwVersion); + ret = VIDEO_ERROR_NOSUPPORT; + goto EXIT; + } + + switch ((int)pCtx->videoCtx.instInfo.eCodecType) { + case VIDEO_CODING_HEVC: + if (Codec_OSAL_SetControls(pCtx, CODEC_OSAL_CID_ENC_HDR_STATIC_INFO, (void *)pHDRStaticInfo) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + memcpy(&(pCtx->videoCtx.inbufGeometry.HdrInfo.sHdrStatic), pHDRStaticInfo, sizeof(ExynosVideoHdrStatic)); + ret = VIDEO_ERROR_NONE; + break; + default: + ALOGE("%s: codec(%x) can't support Set_HDRStaticInfo", __FUNCTION__, pCtx->videoCtx.instInfo.eCodecType); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set HDR Dynamic Info + */ +ExynosVideoErrorType MFC_Encoder_Set_HDRDynamicInfo( + void *pHandle, + ExynosVideoHdrDynamic *pHDRDynamicInfo) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if ((pCtx == NULL) || + (pHDRDynamicInfo == NULL)) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bHDRDynamicInfoSupport == VIDEO_FALSE) { + ALOGE("%s: can't support Set_HDRStaticInfo. // codec type(%x), F/W ver(%x)", + __FUNCTION__, pCtx->videoCtx.instInfo.eCodecType, pCtx->videoCtx.instInfo.HwVersion); + ret = VIDEO_ERROR_NOSUPPORT; + goto EXIT; + } + + memcpy(&(pCtx->videoCtx.inbufGeometry.HdrInfo.sHdrDynamic), pHDRDynamicInfo, sizeof(ExynosVideoHdrDynamic)); + +EXIT: + return ret; +} + + +/* + * [Encoder OPS] Set Header Mode + */ +ExynosVideoErrorType MFC_Encoder_Set_HeaderMode( + void *pHandle, + ExynosVideoBoolType bSeparated) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_HEADER_MODE, + ((bSeparated == VIDEO_TRUE)? CODEC_OSAL_HEADER_MODE_SEPARATE:CODEC_OSAL_HEADER_WITH_1ST_IDR)) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Drop Control + */ +ExynosVideoErrorType MFC_Encoder_Set_DropControl( + void *pHandle, + ExynosVideoBoolType bEnable) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bDropControlSupport == VIDEO_FALSE) { + ALOGE("%s: can't support Set_DropControl. // codec type(%x), F/W ver(%x)", + __FUNCTION__, pCtx->videoCtx.instInfo.eCodecType, pCtx->videoCtx.instInfo.HwVersion); + ret = VIDEO_ERROR_NOSUPPORT; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_ENABLE_DROP_CTRL, (bEnable == VIDEO_TRUE)? 1:0) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Disable DFR + */ +ExynosVideoErrorType MFC_Encoder_Disable_DynamicFrameRate( + void *pHandle, + ExynosVideoBoolType bEnable) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + pCtx->videoCtx.instInfo.bDisableDFR = bEnable; + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set ActualFormat + */ +ExynosVideoErrorType MFC_Encoder_Set_ActualFormat( + void *pHandle, + int nFormat) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + int i; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < (int)(sizeof(SBWC_NONCOMP_TABLE)/sizeof(SBWC_NONCOMP_TABLE[0])); i++) { + if (SBWC_NONCOMP_TABLE[i].eSBWCFormat == pCtx->videoCtx.inbufGeometry.eColorFormat) { + if (SBWC_NONCOMP_TABLE[i].eNormalFormat == nFormat) { + pCtx->videoCtx.specificInfo.enc.actualFormat = (ExynosVideoColorFormatType)nFormat; + ALOGV("%s: actual format is 0x%x", __FUNCTION__, pCtx->videoCtx.specificInfo.enc.actualFormat); + goto EXIT; + } + } + } + + /* start with non SBWC, discard nFormat */ + //ret = VIDEO_ERROR_BADPARAM; + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Operating Rate + */ +static ExynosVideoErrorType MFC_Encoder_Set_OperatingRate( + void *pHandle, + unsigned int framerate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bOperatingRateSupport != VIDEO_TRUE) { + ret = VIDEO_ERROR_NOSUPPORT; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ACTUAL_FRAMERATE, framerate) != 0) { + ALOGE("%s: Failed to set operating rate", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Set Priority + */ +static ExynosVideoErrorType MFC_Encoder_Set_Priority( + void *pHandle, + unsigned int priority) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bPrioritySupport != VIDEO_TRUE) { + ret = VIDEO_ERROR_NOSUPPORT; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_PRIOTIY, priority) != 0) { + ALOGE("%s: Failed to set priority", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Enable Cacheable (Input) + */ +static ExynosVideoErrorType MFC_Encoder_Enable_Cacheable_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_CACHEABLE_BUFFER, 2) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Enable Cacheable (Output) + */ +static ExynosVideoErrorType MFC_Encoder_Enable_Cacheable_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_VIDEO_CACHEABLE_BUFFER, 1) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Set Shareable Buffer (Input) + */ +static ExynosVideoErrorType MFC_Encoder_Set_Shareable_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + pCtx->videoCtx.bShareInbuf = VIDEO_TRUE; + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Set Shareable Buffer (Output) + */ +static ExynosVideoErrorType MFC_Encoder_Set_Shareable_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + pCtx->videoCtx.bShareOutbuf = VIDEO_TRUE; + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Get Buffer (Input) + */ +static ExynosVideoErrorType MFC_Encoder_Get_Buffer_Inbuf( + void *pHandle, + int nIndex, + ExynosVideoBuffer **pBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + *pBuffer = NULL; + ret = VIDEO_ERROR_NOBUFFERS; + goto EXIT; + } + + if ((nIndex < 0) || + (pCtx->videoCtx.nInbufs <= nIndex)) { + *pBuffer = NULL; + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + *pBuffer = (ExynosVideoBuffer *)&pCtx->videoCtx.pInbuf[nIndex]; + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Get Buffer (Output) + */ +static ExynosVideoErrorType MFC_Encoder_Get_Buffer_Outbuf( + void *pHandle, + int nIndex, + ExynosVideoBuffer **pBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + *pBuffer = NULL; + ret = VIDEO_ERROR_NOBUFFERS; + goto EXIT; + } + + if ((nIndex < 0) || + (pCtx->videoCtx.nOutbufs <= nIndex)) { + *pBuffer = NULL; + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + *pBuffer = (ExynosVideoBuffer *)&pCtx->videoCtx.pOutbuf[nIndex]; + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Set Geometry (Src) + */ +static ExynosVideoErrorType MFC_Encoder_Set_Geometry_Inbuf( + void *pHandle, + ExynosVideoGeometry *pBufferConf) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_Format fmt; + int i; + + if ((pCtx == NULL) || + (pBufferConf == NULL)) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&fmt, 0, sizeof(fmt)); + + fmt.type = CODEC_OSAL_BUF_TYPE_SRC; + fmt.format = Codec_OSAL_ColorFormatToPixelFormat(pBufferConf->eColorFormat, pCtx->videoCtx.instInfo.HwVersion); + fmt.width = pBufferConf->nFrameWidth; + fmt.height = pBufferConf->nFrameHeight; + fmt.stride = pBufferConf->nStride; + fmt.nPlane = pBufferConf->nPlaneCnt; + + for (i = 0; i < (int)(sizeof(SBWC_LOSSY_TABLE)/sizeof(SBWC_LOSSY_TABLE[0])); i++) { + if (pBufferConf->eColorFormat == SBWC_LOSSY_TABLE[i].eColorFormat) + fmt.field |= (1 << SBWC_LOSSY_TABLE[i].nFormatFlag); + } + + if (Codec_OSAL_SetFormat(pCtx, &fmt) != 0) { + ALOGE("%s: Failed to SetFormat", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + memcpy(&pCtx->videoCtx.inbufGeometry, pBufferConf, sizeof(pCtx->videoCtx.inbufGeometry)); + pCtx->videoCtx.nInbufPlanes = pBufferConf->nPlaneCnt; + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Get Geometry (Src) + */ +static ExynosVideoErrorType MFC_Encoder_Get_Geometry_Inbuf( + void *pHandle, + ExynosVideoGeometry *pBufferConf) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_Format fmt; + + if ((pCtx == NULL) || + (pBufferConf == NULL)) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memcpy(pBufferConf, &pCtx->videoCtx.inbufGeometry, sizeof(pCtx->videoCtx.inbufGeometry)); + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = CODEC_OSAL_BUF_TYPE_SRC; + + if (Codec_OSAL_GetFormat(pCtx, &fmt) != 0) { + ALOGE("%s: Failed to GetFormat", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pBufferConf->nFrameWidth = fmt.width; + pBufferConf->nFrameHeight = fmt.height; + pBufferConf->nSizeImage = fmt.planeSize[0]; + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Set Geometry (Dst) + */ +static ExynosVideoErrorType MFC_Encoder_Set_Geometry_Outbuf( + void *pHandle, + ExynosVideoGeometry *pBufferConf) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_Format fmt; + + if ((pCtx == NULL) || + (pBufferConf == NULL)) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = CODEC_OSAL_BUF_TYPE_DST; + fmt.format = Codec_OSAL_CodingTypeToCompressdFormat(pBufferConf->eCompressionFormat); + fmt.planeSize[0] = pBufferConf->nSizeImage; + fmt.nPlane = pBufferConf->nPlaneCnt; + + if (Codec_OSAL_SetFormat(pCtx, &fmt) != 0) { + ALOGE("%s: Failed to SetFormat", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + memcpy(&pCtx->videoCtx.outbufGeometry, pBufferConf, sizeof(pCtx->videoCtx.outbufGeometry)); + pCtx->videoCtx.nOutbufPlanes = pBufferConf->nPlaneCnt; + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Get Geometry (Dst) + */ +static ExynosVideoErrorType MFC_Encoder_Get_Geometry_Outbuf( + void *pHandle, + ExynosVideoGeometry *pBufferConf) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_Format fmt; + + if ((pCtx == NULL) || + (pBufferConf == NULL)) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = CODEC_OSAL_BUF_TYPE_DST; + + if (Codec_OSAL_GetFormat(pCtx, &fmt) != 0) { + ALOGE("%s: Failed to GetFormat", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pBufferConf->nSizeImage = fmt.planeSize[0]; + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Setup (Src) + */ +static ExynosVideoErrorType MFC_Encoder_Setup_Inbuf( + void *pHandle, + unsigned int nBufferCount) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoPlane *pVideoPlane = NULL; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_ReqBuf reqBuf; + CodecOSAL_Buffer buf; + + int i, j; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (nBufferCount == 0) { + nBufferCount = MAX_INPUTBUFFER_COUNT; + ALOGV("%s: Change buffer count %d", __FUNCTION__, nBufferCount); + } + + memset(&reqBuf, 0, sizeof(reqBuf)); + + reqBuf.type = CODEC_OSAL_BUF_TYPE_SRC; + reqBuf.count = nBufferCount; + if (pCtx->videoCtx.bShareInbuf == VIDEO_TRUE) + reqBuf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + reqBuf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + if (Codec_OSAL_RequestBuf(pCtx, &reqBuf) != 0) { + ALOGE("Failed to RequestBuf"); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.nInbufs = (int)reqBuf.count; + + pCtx->videoCtx.pInbuf = malloc(sizeof(*pCtx->videoCtx.pInbuf) * pCtx->videoCtx.nInbufs); + if (pCtx->videoCtx.pInbuf == NULL) { + ALOGE("%s: Failed to allocate input buffer context", __FUNCTION__); + ret = VIDEO_ERROR_NOMEM; + goto EXIT; + } + memset(pCtx->videoCtx.pInbuf, 0, sizeof(*pCtx->videoCtx.pInbuf) * pCtx->videoCtx.nInbufs); + + memset(&buf, 0, sizeof(buf)); + + if (pCtx->videoCtx.bShareInbuf == VIDEO_FALSE) { + buf.type = CODEC_OSAL_BUF_TYPE_SRC; + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + buf.nPlane = pCtx->videoCtx.nInbufPlanes; + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + buf.index = i; + + if (Codec_OSAL_QueryBuf(pCtx, &buf) != 0) { + ALOGE("%s: Failed to QueryBuf", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + for (j = 0; j < pCtx->videoCtx.nInbufPlanes; j++) { + pVideoPlane = &pCtx->videoCtx.pInbuf[i].planes[j]; + + pVideoPlane->addr = Codec_OSAL_MemoryMap(NULL, + buf.planes[j].bufferSize, PROT_READ | PROT_WRITE, + MAP_SHARED, (unsigned long)buf.planes[j].addr, buf.planes[j].offset); + if (pVideoPlane->addr == MAP_FAILED) { + ALOGE("%s: Failed to map", __FUNCTION__); + ret = VIDEO_ERROR_MAPFAIL; + goto EXIT; + } + + pVideoPlane->allocSize = buf.planes[j].bufferSize; + pVideoPlane->dataSize = 0; + } + + pCtx->videoCtx.pInbuf[i].pGeometry = &pCtx->videoCtx.inbufGeometry; + pCtx->videoCtx.pInbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pInbuf[i].bRegistered = VIDEO_TRUE; + + } + } else { + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + pCtx->videoCtx.pInbuf[i].pGeometry = &pCtx->videoCtx.inbufGeometry; + pCtx->videoCtx.pInbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pInbuf[i].bRegistered = VIDEO_FALSE; + } + } + + return ret; + +EXIT: + if ((pCtx != NULL) && (pCtx->videoCtx.pInbuf != NULL)) { + if (pCtx->videoCtx.bShareInbuf == VIDEO_FALSE) { + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + for (j = 0; j < pCtx->videoCtx.nInbufPlanes; j++) { + pVideoPlane = &pCtx->videoCtx.pInbuf[i].planes[j]; + + if (pVideoPlane->addr == MAP_FAILED) { + pVideoPlane->addr = NULL; + break; + } + + Codec_OSAL_MemoryUnmap(pVideoPlane->addr, pVideoPlane->allocSize); + } + } + } + + free(pCtx->videoCtx.pInbuf); + pCtx->videoCtx.pInbuf = NULL; + } + + return ret; +} + +/* + * [Encoder Buffer OPS] Setup (Dst) + */ +static ExynosVideoErrorType MFC_Encoder_Setup_Outbuf( + void *pHandle, + unsigned int nBufferCount) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoPlane *pVideoPlane = NULL; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_ReqBuf reqBuf; + CodecOSAL_Buffer buf; + + int i, j; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (nBufferCount == 0) { + nBufferCount = MAX_OUTPUTBUFFER_COUNT; + ALOGV("%s: Change buffer count %d", __FUNCTION__, nBufferCount); + } + + memset(&reqBuf, 0, sizeof(reqBuf)); + + reqBuf.type = CODEC_OSAL_BUF_TYPE_DST; + reqBuf.count = nBufferCount; + if (pCtx->videoCtx.bShareOutbuf == VIDEO_TRUE) + reqBuf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + reqBuf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + if (Codec_OSAL_RequestBuf(pCtx, &reqBuf) != 0) { + ALOGE("%s: Failed to RequestBuf", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.nOutbufs = reqBuf.count; + + pCtx->videoCtx.pOutbuf = malloc(sizeof(*pCtx->videoCtx.pOutbuf) * pCtx->videoCtx.nOutbufs); + if (pCtx->videoCtx.pOutbuf == NULL) { + ALOGE("%s: Failed to allocate output buffer context", __FUNCTION__); + ret = VIDEO_ERROR_NOMEM; + goto EXIT; + } + memset(pCtx->videoCtx.pOutbuf, 0, sizeof(*pCtx->videoCtx.pOutbuf) * pCtx->videoCtx.nOutbufs); + + memset(&buf, 0, sizeof(buf)); + + if (pCtx->videoCtx.bShareOutbuf == VIDEO_FALSE) { + buf.type = CODEC_OSAL_BUF_TYPE_DST; + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + buf.nPlane = pCtx->videoCtx.nOutbufPlanes; + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + buf.index = i; + + if (Codec_OSAL_QueryBuf(pCtx, &buf) != 0) { + ALOGE("%s: Failed to QueryBuf", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + for (j = 0; j < pCtx->videoCtx.nOutbufPlanes; j++) { + pVideoPlane = &pCtx->videoCtx.pOutbuf[i].planes[j]; + + pVideoPlane->addr = Codec_OSAL_MemoryMap(NULL, + buf.planes[j].bufferSize, PROT_READ | PROT_WRITE, + MAP_SHARED, (unsigned long)buf.planes[j].addr, buf.planes[j].offset); + if (pVideoPlane->addr == MAP_FAILED) { + ALOGE("%s: Failed to map", __FUNCTION__); + ret = VIDEO_ERROR_MAPFAIL; + goto EXIT; + } + + pVideoPlane->allocSize = buf.planes[j].bufferSize; + pVideoPlane->dataSize = 0; + } + + pCtx->videoCtx.pOutbuf[i].pGeometry = &pCtx->videoCtx.outbufGeometry; + pCtx->videoCtx.pOutbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pOutbuf[i].bRegistered = VIDEO_TRUE; + } + } else { + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++ ) { + pCtx->videoCtx.pOutbuf[i].pGeometry = &pCtx->videoCtx.outbufGeometry; + pCtx->videoCtx.pOutbuf[i].bQueued = VIDEO_FALSE; + pCtx->videoCtx.pOutbuf[i].bRegistered = VIDEO_FALSE; + } + } + + return ret; + +EXIT: + if ((pCtx != NULL) && (pCtx->videoCtx.pOutbuf != NULL)) { + if (pCtx->videoCtx.bShareOutbuf == VIDEO_FALSE) { + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + for (j = 0; j < pCtx->videoCtx.nOutbufPlanes; j++) { + pVideoPlane = &pCtx->videoCtx.pOutbuf[i].planes[j]; + + if (pVideoPlane->addr == MAP_FAILED) { + pVideoPlane->addr = NULL; + break; + } + + Codec_OSAL_MemoryUnmap(pVideoPlane->addr, pVideoPlane->allocSize); + } + } + } + + free(pCtx->videoCtx.pOutbuf); + pCtx->videoCtx.pOutbuf = NULL; + } + + return ret; +} + +/* + * [Encoder Buffer OPS] Run (src) + */ +static ExynosVideoErrorType MFC_Encoder_Run_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonInbuf == VIDEO_FALSE) { + if (Codec_OSAL_SetStreamOn(pCtx, CODEC_OSAL_BUF_TYPE_SRC) != 0) { + ALOGE("%s: Failed to streamon for input buffer", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.bStreamonInbuf = VIDEO_TRUE; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Run (Dst) + */ +static ExynosVideoErrorType MFC_Encoder_Run_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonOutbuf == VIDEO_FALSE) { + if (Codec_OSAL_SetStreamOn(pCtx, CODEC_OSAL_BUF_TYPE_DST) != 0) { + ALOGE("%s: Failed to streamon for output buffer", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.bStreamonOutbuf = VIDEO_TRUE; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Stop (Src) + */ +static ExynosVideoErrorType MFC_Encoder_Stop_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i = 0; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonInbuf == VIDEO_TRUE) { + if (Codec_OSAL_SetStreamOff(pCtx, CODEC_OSAL_BUF_TYPE_SRC) != 0) { + ALOGE("%s: Failed to streamoff for input buffer", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.bStreamonInbuf = VIDEO_FALSE; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) + pCtx->videoCtx.pInbuf[i].bQueued = VIDEO_FALSE; + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Stop (Dst) + */ +static ExynosVideoErrorType MFC_Encoder_Stop_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i = 0; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonOutbuf == VIDEO_TRUE) { + if (Codec_OSAL_SetStreamOff(pCtx, CODEC_OSAL_BUF_TYPE_DST) != 0) { + ALOGE("%s: Failed to streamoff for output buffer", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.bStreamonOutbuf = VIDEO_FALSE; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) + pCtx->videoCtx.pOutbuf[i].bQueued = VIDEO_FALSE; + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Wait (Src) + */ +static ExynosVideoErrorType MFC_Encoder_Wait_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + struct pollfd poll_events; + int poll_state; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + poll_events.fd = pCtx->videoCtx.hDevice; + poll_events.events = POLLOUT | POLLERR; + poll_events.revents = 0; + + do { + poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_ENCODER_POLL_TIMEOUT); + if (poll_state > 0) { + if (poll_events.revents & POLLOUT) { + break; + } else { + ALOGE("%s: Poll return error", __FUNCTION__); + ret = VIDEO_ERROR_POLL; + break; + } + } else if (poll_state < 0) { + ALOGE("%s: Poll state error", __FUNCTION__); + ret = VIDEO_ERROR_POLL; + break; + } + } while (poll_state == 0); + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Wait (Dst) + */ +static ExynosVideoErrorType MFC_Encoder_Wait_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + struct pollfd poll_events; + int poll_state; + int bframe_count = 0; // FIXME + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + poll_events.fd = pCtx->videoCtx.hDevice; + poll_events.events = POLLIN | POLLERR; + poll_events.revents = 0; + + do { + poll_state = poll((struct pollfd*)&poll_events, 1, VIDEO_ENCODER_POLL_TIMEOUT); + if (poll_state > 0) { + if (poll_events.revents & POLLIN) { + break; + } else { + ALOGE("%s: Poll return error", __FUNCTION__); + ret = VIDEO_ERROR_POLL; + break; + } + } else if (poll_state < 0) { + ALOGE("%s: Poll state error", __FUNCTION__); + ret = VIDEO_ERROR_POLL; + break; + } else { + bframe_count++; // FIXME + } + } while (poll_state == 0 && bframe_count < 5); // FIXME + +EXIT: + return ret; +} + +static ExynosVideoErrorType MFC_Encoder_Register_Inbuf( + void *pHandle, + ExynosVideoPlane *pPlanes, + int nPlanes) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i, j; + + if ((pCtx == NULL) || + (pPlanes == NULL) || + (nPlanes != pCtx->videoCtx.nInbufPlanes)) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + if (pCtx->videoCtx.pInbuf[i].bRegistered == VIDEO_FALSE) { + for (j = 0; j < nPlanes; j++) { + pCtx->videoCtx.pInbuf[i].planes[j].addr = pPlanes[j].addr; + pCtx->videoCtx.pInbuf[i].planes[j].allocSize = pPlanes[j].allocSize; + pCtx->videoCtx.pInbuf[i].planes[j].fd = pPlanes[j].fd; + + ALOGV("%s: registered buf[%d][%d]: addr = %p, alloc_sz = %u, fd = %lu", + __FUNCTION__, i, j, pPlanes[j].addr, pPlanes[j].allocSize, pPlanes[j].fd); + } + + pCtx->videoCtx.pInbuf[i].bRegistered = VIDEO_TRUE; + break; + } + } + + if (i == pCtx->videoCtx.nInbufs) { + ALOGE("%s: can not find non-registered input buffer", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + } + +EXIT: + return ret; +} + +static ExynosVideoErrorType MFC_Encoder_Register_Outbuf( + void *pHandle, + ExynosVideoPlane *pPlanes, + int nPlanes) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i, j; + + if ((pCtx == NULL) || + (pPlanes == NULL) || + (nPlanes != pCtx->videoCtx.nOutbufPlanes)) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + if (pCtx->videoCtx.pOutbuf[i].bRegistered == VIDEO_FALSE) { + for (j = 0; j < nPlanes; j++) { + pCtx->videoCtx.pOutbuf[i].planes[j].addr = pPlanes[j].addr; + pCtx->videoCtx.pOutbuf[i].planes[j].allocSize = pPlanes[j].allocSize; + pCtx->videoCtx.pOutbuf[i].planes[j].fd = pPlanes[j].fd; + + ALOGV("%s: registered buf[%d][%d]: addr = %p, alloc_sz = %d, fd = %lu", + __FUNCTION__, i, j, pPlanes[j].addr, pPlanes[j].allocSize, pPlanes[j].fd); + } + + pCtx->videoCtx.pOutbuf[i].bRegistered = VIDEO_TRUE; + break; + } + } + + if (i == pCtx->videoCtx.nOutbufs) { + ALOGE("%s: can not find non-registered output buffer", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + } + +EXIT: + return ret; +} + +static ExynosVideoErrorType MFC_Encoder_Clear_RegisteredBuffer_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i, j; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + for (j = 0; j < pCtx->videoCtx.nInbufPlanes; j++) { + pCtx->videoCtx.pInbuf[i].planes[j].addr = NULL; + pCtx->videoCtx.pInbuf[i].planes[j].fd = 0; + } + + pCtx->videoCtx.pInbuf[i].bRegistered = VIDEO_FALSE; + } + +EXIT: + return ret; +} + +static ExynosVideoErrorType MFC_Encoder_Clear_RegisteredBuffer_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i, j; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + for (j = 0; j < pCtx->videoCtx.nOutbufPlanes; j++) { + pCtx->videoCtx.pOutbuf[i].planes[j].addr = NULL; + pCtx->videoCtx.pOutbuf[i].planes[j].fd = 0; + } + + pCtx->videoCtx.pOutbuf[i].bRegistered = VIDEO_FALSE; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Find (Input) + */ +static int MFC_Encoder_Find_Inbuf( + void *pHandle, + unsigned char *pBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int nIndex = -1, i; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + if (pCtx->videoCtx.pInbuf[i].bQueued == VIDEO_FALSE) { + if ((pBuffer == NULL) || + (pCtx->videoCtx.pInbuf[i].planes[0].addr == pBuffer)) { + nIndex = i; + break; + } + } + } + +EXIT: + return nIndex; +} + +/* + * [Encoder Buffer OPS] Find (Output) + */ +static int MFC_Encoder_Find_Outbuf( + void *pHandle, + unsigned char *pBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int nIndex = -1, i; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + if (pCtx->videoCtx.pOutbuf[i].bQueued == VIDEO_FALSE) { + if ((pBuffer == NULL) || + (pCtx->videoCtx.pOutbuf[i].planes[0].addr == pBuffer)) { + nIndex = i; + break; + } + } + } + +EXIT: + return nIndex; +} + +/* + * [Encoder Buffer OPS] Enqueue (Input) + */ +static ExynosVideoErrorType MFC_Encoder_Enqueue_Inbuf( + void *pHandle, + void *pBuffer[], + unsigned int nDataSize[], + int nPlanes, + void *pPrivate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + int index, i; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.nInbufPlanes < nPlanes) { + ALOGE("%s: Number of max planes : %d, nPlanes : %d", __FUNCTION__, + pCtx->videoCtx.nInbufPlanes, nPlanes); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_SRC; + buf.nPlane = pCtx->videoCtx.nInbufPlanes; + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pInMutex; + pthread_mutex_lock(pMutex); + + index = MFC_Encoder_Find_Inbuf(pCtx, pBuffer[0]); + if (index == -1) { + pthread_mutex_unlock(pMutex); + ALOGW("%s: Matching Buffer index not found", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + goto EXIT; + } + buf.index = index; + ALOGV("%s: index:%d pCtx->videoCtx.pInbuf[buf.index].bQueued:%d, pBuffer[0]:%p", + __FUNCTION__, index, pCtx->videoCtx.pInbuf[buf.index].bQueued, pBuffer[0]); + + if (pCtx->videoCtx.bShareInbuf == VIDEO_TRUE) { + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + for (i = 0; i < buf.nPlane; i++) { + if (buf.memory == CODEC_OSAL_MEM_TYPE_USERPTR) + buf.planes[i].addr = pBuffer[i]; + else + buf.planes[i].addr = (void *)(unsigned long)pCtx->videoCtx.pInbuf[buf.index].planes[i].fd; + + buf.planes[i].bufferSize = pCtx->videoCtx.pInbuf[index].planes[i].allocSize; + buf.planes[i].dataLen = pCtx->videoCtx.pInbuf[index].planes[i].allocSize; /* for exact cache flush size */ + + ALOGV("%s: shared inbuf(%d) plane=%d addr=%p len=%d used=%d\n", __FUNCTION__, + index, i, + buf.planes[i].addr, + buf.planes[i].bufferSize, + buf.planes[i].dataLen); + } + } else { + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + for (i = 0; i < nPlanes; i++) + buf.planes[i].dataLen = nDataSize[i]; + } + + if (nDataSize[0] <= 0) { + buf.flags = EMPTY_DATA | LAST_FRAME; + ALOGD("%s: EMPTY DATA", __FUNCTION__); + } else { + if ((((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) + buf.flags = LAST_FRAME; + + if (buf.flags & LAST_FRAME) + ALOGD("%s: DATA with flags(0x%x)", __FUNCTION__, buf.flags); + } + + signed long long sec = (((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp / 1E6); + signed long long usec = (((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp) - (sec * 1E6); + buf.timestamp.tv_sec = (long)sec; + buf.timestamp.tv_usec = (long)usec; + + pCtx->videoCtx.pInbuf[buf.index].pPrivate = pPrivate; + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_TRUE; + + if ((pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_VP8) || + (pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_VP9) || + (pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_AVC) || + (pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_HEVC)) { + if (pCtx->videoCtx.instInfo.bDisableDFR != VIDEO_TRUE) { + int oldFrameRate = 0; + int curFrameRate = 0; + int64_t curDuration = 0; + + curDuration = ((int64_t)((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp - pCtx->videoCtx.specificInfo.enc.oldTimeStamp); + if ((curDuration > 0) && (pCtx->videoCtx.specificInfo.enc.oldDuration > 0)) { + oldFrameRate = ROUND_UP(1E6 / pCtx->videoCtx.specificInfo.enc.oldDuration); + curFrameRate = ROUND_UP(1E6 / curDuration); + + if (CHECK_FRAMERATE_VALIDITY(curFrameRate, oldFrameRate)) { + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_FRAME_RATE, curFrameRate) != 0) { + ALOGE("%s: Failed to SetControl", __FUNCTION__); + pthread_mutex_unlock(pMutex); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + pCtx->videoCtx.specificInfo.enc.oldFrameRate = curFrameRate; + } else { + ALOGV("%s: current ts: %lld, old ts: %lld, curFrameRate: %d, oldFrameRate: %d", __FUNCTION__, + (long long)((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp, + (long long)pCtx->videoCtx.specificInfo.enc.oldTimeStamp, + curFrameRate, oldFrameRate); + } + } + + if (curDuration > 0) + pCtx->videoCtx.specificInfo.enc.oldDuration = curDuration; + pCtx->videoCtx.specificInfo.enc.oldTimeStamp = (int64_t)((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp; + } + } + + /* save HDR Dynamic Info to shared buffer instead of ioctl call */ + if (pCtx->videoCtx.instInfo.supportInfo.enc.bHDRDynamicInfoSupport == VIDEO_TRUE) { + ExynosVideoHdrDynamic *pHdrDynamic = ((ExynosVideoHdrDynamic *)pCtx->videoCtx.specificInfo.enc.pHDRInfoShareBufferAddr) + buf.index; + memcpy(pHdrDynamic, &(pCtx->videoCtx.inbufGeometry.HdrInfo.sHdrDynamic), sizeof(ExynosVideoHdrDynamic)); + } + + pthread_mutex_unlock(pMutex); + + if (Codec_OSAL_EnqueueBuf(pCtx, &buf) != 0) { + ALOGE("%s: Failed to enqueue input buffer", __FUNCTION__); + pthread_mutex_lock(pMutex); + pCtx->videoCtx.pInbuf[buf.index].pPrivate = NULL; + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_FALSE; + pthread_mutex_unlock(pMutex); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Enqueue (Output) + */ +static ExynosVideoErrorType MFC_Encoder_Enqueue_Outbuf( + void *pHandle, + void *pBuffer[], + unsigned int nDataSize[], + int nPlanes, + void *pPrivate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + int i, index; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.nOutbufPlanes < nPlanes) { + ALOGE("%s: Number of max planes : %d, nPlanes : %d", __FUNCTION__, + pCtx->videoCtx.nOutbufPlanes, nPlanes); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_DST; + buf.nPlane = pCtx->videoCtx.nOutbufPlanes; + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pOutMutex; + pthread_mutex_lock(pMutex); + + index = MFC_Encoder_Find_Outbuf(pCtx, pBuffer[0]); + if (index == -1) { + pthread_mutex_unlock(pMutex); + ALOGE("%s: Failed to get index", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + goto EXIT; + } + buf.index = index; + ALOGV("%s: index:%d pCtx->videoCtx.pOutbuf[buf.index].bQueued:%d, pBuffer[0]:%p", + __FUNCTION__, index, pCtx->videoCtx.pOutbuf[buf.index].bQueued, pBuffer[0]); + + if (pCtx->videoCtx.bShareOutbuf == VIDEO_TRUE) { + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + for (i = 0; i < nPlanes; i++) { + if (buf.memory == CODEC_OSAL_MEM_TYPE_USERPTR) + buf.planes[i].addr = pBuffer[i]; + else + buf.planes[i].addr = (void *)(unsigned long)pCtx->videoCtx.pOutbuf[index].planes[i].fd; + + buf.planes[i].bufferSize = pCtx->videoCtx.pOutbuf[index].planes[i].allocSize; + buf.planes[i].dataLen = nDataSize[i]; + + ALOGV("%s: shared outbuf(%d) plane=%d addr=%p len=%d used=%d\n", __FUNCTION__, + index, i, + buf.planes[i].addr, + buf.planes[i].bufferSize, + buf.planes[i].dataLen); + } + } else { + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + } + + pCtx->videoCtx.pOutbuf[buf.index].pPrivate = pPrivate; + pCtx->videoCtx.pOutbuf[buf.index].bQueued = VIDEO_TRUE; + pthread_mutex_unlock(pMutex); + + if (Codec_OSAL_EnqueueBuf(pCtx, &buf) != 0) { + ALOGE("%s: Failed to enqueue output buffer", __FUNCTION__); + pthread_mutex_lock(pMutex); + pCtx->videoCtx.pOutbuf[buf.index].pPrivate = NULL; + pCtx->videoCtx.pOutbuf[buf.index].bQueued = VIDEO_FALSE; + pthread_mutex_unlock(pMutex); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Enqueue All (Output) + */ +static ExynosVideoErrorType MFC_Encoder_Enqueue_All_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + void *pBuffer[VIDEO_BUFFER_MAX_PLANES] = {NULL, }; + unsigned int nDataSize[VIDEO_BUFFER_MAX_PLANES] = {0, }; + + int i; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + ret = MFC_Encoder_Enqueue_Outbuf(pCtx, pBuffer, nDataSize, 1, NULL); + if (ret != VIDEO_ERROR_NONE) + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Dequeue (Input) + */ +static ExynosVideoBuffer *MFC_Encoder_Dequeue_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoBuffer *pInbuf = NULL; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonInbuf == VIDEO_FALSE) { + pInbuf = NULL; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + + buf.type = CODEC_OSAL_BUF_TYPE_SRC; + buf.nPlane = pCtx->videoCtx.nInbufPlanes; + if (pCtx->videoCtx.bShareInbuf == VIDEO_TRUE) + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + if (Codec_OSAL_DequeueBuf(pCtx, &buf) != 0) { + pInbuf = NULL; + goto EXIT; + } + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pInMutex; + pthread_mutex_lock(pMutex); + + pInbuf = &pCtx->videoCtx.pInbuf[buf.index]; + if (pInbuf->bQueued == VIDEO_FALSE) { + pInbuf = NULL; + pthread_mutex_unlock(pMutex); + goto EXIT; + } + + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_FALSE; + pthread_mutex_unlock(pMutex); + +EXIT: + return pInbuf; +} + +/* + * [Encoder Buffer OPS] Dequeue (Output) + */ +static ExynosVideoBuffer *MFC_Encoder_Dequeue_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoBuffer *pOutbuf = NULL; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + int ret = 0; + int i; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonOutbuf == VIDEO_FALSE) { + pOutbuf = NULL; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_DST; + buf.nPlane = pCtx->videoCtx.nOutbufPlanes; + if (pCtx->videoCtx.bShareOutbuf == VIDEO_TRUE) + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + /* returning DQBUF_EIO means MFC H/W status is invalid */ + ret = Codec_OSAL_DequeueBuf(pCtx, &buf); + if (ret != 0) { + if (errno == EIO) + pOutbuf = (ExynosVideoBuffer *)VIDEO_ERROR_DQBUF_EIO; + else + pOutbuf = NULL; + goto EXIT; + } + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pOutMutex; + pthread_mutex_lock(pMutex); + + pOutbuf = &pCtx->videoCtx.pOutbuf[buf.index]; + if (pOutbuf->bQueued == VIDEO_FALSE) { + pOutbuf = NULL; + pthread_mutex_unlock(pMutex); + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufPlanes; i++) + pOutbuf->planes[i].dataSize = buf.planes[i].dataLen; + + pOutbuf->frameType = buf.frameType; + + { + int64_t sec = (int64_t)(buf.timestamp.tv_sec * 1E6); + int64_t usec = (int64_t)buf.timestamp.tv_usec; + pOutbuf->timestamp = sec + usec; + } + + pOutbuf->bQueued = VIDEO_FALSE; + pthread_mutex_unlock(pMutex); + +EXIT: + return pOutbuf; +} + +static ExynosVideoErrorType MFC_Encoder_Clear_Queued_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i = 0; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) + pCtx->videoCtx.pInbuf[i].bQueued = VIDEO_FALSE; + +EXIT: + return ret; +} + +static ExynosVideoErrorType MFC_Encoder_Clear_Queued_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + int i = 0; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) + pCtx->videoCtx.pOutbuf[i].bQueued = VIDEO_FALSE; + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Cleanup Buffer (Input) + */ +static ExynosVideoErrorType MFC_Encoder_Cleanup_Buffer_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_ReqBuf reqBuf; + int nBufferCount = 0; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + nBufferCount = 0; /* for clean-up */ + + memset(&reqBuf, 0, sizeof(reqBuf)); + + reqBuf.type = CODEC_OSAL_BUF_TYPE_SRC; + reqBuf.count = nBufferCount; + if (pCtx->videoCtx.bShareInbuf == VIDEO_TRUE) + reqBuf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + reqBuf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + if (Codec_OSAL_RequestBuf(pCtx, &reqBuf) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.nInbufs = (int)reqBuf.count; + + if (pCtx->videoCtx.pInbuf != NULL) { + free(pCtx->videoCtx.pInbuf); + pCtx->videoCtx.pInbuf = NULL; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] Cleanup Buffer (Output) + */ +static ExynosVideoErrorType MFC_Encoder_Cleanup_Buffer_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + CodecOSAL_ReqBuf reqBuf; + int nBufferCount = 0; + + if (pCtx == NULL) { + ALOGE("%s: Video context info must be supplied", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + nBufferCount = 0; /* for clean-up */ + + memset(&reqBuf, 0, sizeof(reqBuf)); + + reqBuf.type = CODEC_OSAL_BUF_TYPE_DST; + reqBuf.count = nBufferCount; + if (pCtx->videoCtx.bShareOutbuf == VIDEO_TRUE) + reqBuf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + reqBuf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + if (Codec_OSAL_RequestBuf(pCtx, &reqBuf) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pCtx->videoCtx.nOutbufs = (int)reqBuf.count; + + if (pCtx->videoCtx.pOutbuf != NULL) { + free(pCtx->videoCtx.pOutbuf); + pCtx->videoCtx.pOutbuf = NULL; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] FindIndex (Input) + */ +static int MFC_Encoder_FindEmpty_Inbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int nIndex = -1, i; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nInbufs; i++) { + if (pCtx->videoCtx.pInbuf[i].bQueued == VIDEO_FALSE) { + nIndex = i; + break; + } + } + +EXIT: + return nIndex; +} + +/* + * [Encoder Buffer OPS] FindIndex (Output) + */ +static int MFC_Encoder_FindEmpty_Outbuf(void *pHandle) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + int nIndex = -1, i; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + goto EXIT; + } + + for (i = 0; i < pCtx->videoCtx.nOutbufs; i++) { + if (pCtx->videoCtx.pOutbuf[i].bQueued == VIDEO_FALSE) { + nIndex = i; + break; + } + } + +EXIT: + return nIndex; +} + +/* + * [Encoder Buffer OPS] ExtensionEnqueue (Input) + */ +static ExynosVideoErrorType MFC_Encoder_ExtensionEnqueue_Inbuf( + void *pHandle, + void *pBuffer[], + unsigned long pFd[], + unsigned int nAllocLen[], + unsigned int nDataSize[], + int nPlanes, + void *pPrivate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + int index, i; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.nInbufPlanes < nPlanes) { + ALOGE("%s: Number of max planes : %d, nPlanes : %d", __FUNCTION__, + pCtx->videoCtx.nInbufPlanes, nPlanes); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_SRC; + buf.nPlane = pCtx->videoCtx.nInbufPlanes; + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pInMutex; + pthread_mutex_lock(pMutex); + + index = MFC_Encoder_FindEmpty_Inbuf(pCtx); + if (index == -1) { + pthread_mutex_unlock(pMutex); + ALOGE("%s: Failed to get index", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + goto EXIT; + } + buf.index = index; + ALOGV("%s: index:%d pCtx->videoCtx.pInbuf[buf.index].bQueued:%d, pFd[0]:%lu", + __FUNCTION__, index, pCtx->videoCtx.pInbuf[buf.index].bQueued, pFd[0]); + + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + for (i = 0; i < nPlanes; i++) { + if (buf.memory == CODEC_OSAL_MEM_TYPE_USERPTR) + buf.planes[i].addr = pBuffer[i]; + else + buf.planes[i].addr = (void *)pFd[i]; + + buf.planes[i].bufferSize = nAllocLen[i]; + buf.planes[i].dataLen = nAllocLen[i]; /* for exact cache flush size */ + + /* Temporary storage for Dequeue */ + pCtx->videoCtx.pInbuf[buf.index].planes[i].addr = pBuffer[i]; + pCtx->videoCtx.pInbuf[buf.index].planes[i].fd = pFd[i]; + pCtx->videoCtx.pInbuf[buf.index].planes[i].allocSize = nAllocLen[i]; + + ALOGV("%s: shared inbuf(%d) plane = %d addr = %p len = %d used = %d\n", __FUNCTION__, + index, i, + buf.planes[i].addr, + buf.planes[i].bufferSize, + buf.planes[i].dataLen); + } + + if (nDataSize[0] <= 0) { + buf.flags = EMPTY_DATA | LAST_FRAME; + ALOGD("%s: EMPTY DATA", __FUNCTION__); + } else { + if ((((OMX_BUFFERHEADERTYPE *)pPrivate)->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) + buf.flags = LAST_FRAME; + + if (buf.flags & LAST_FRAME) + ALOGD("%s: DATA with flags(0x%x)", __FUNCTION__, buf.flags); + + if ((pCtx->videoCtx.specificInfo.enc.actualFormat >= VIDEO_COLORFORMAT_NV12) && + (pCtx->videoCtx.specificInfo.enc.actualFormat <= VIDEO_COLORFORMAT_RGBA8888)) { + buf.flags |= UNCOMP_FORMAT; + pCtx->videoCtx.specificInfo.enc.actualFormat = VIDEO_COLORFORMAT_UNKNOWN; + } + } + + signed long long sec = (((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp / 1E6); + signed long long usec = (((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp) - (sec * 1E6); + buf.timestamp.tv_sec = (long)sec; + buf.timestamp.tv_usec = (long)usec; + + pCtx->videoCtx.pInbuf[buf.index].pPrivate = pPrivate; + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_TRUE; + + if ((pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_VP8) || + (pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_VP9) || + (pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_AVC) || + (pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_HEVC)) { + if (pCtx->videoCtx.instInfo.bDisableDFR != VIDEO_TRUE) { + int oldFrameRate = 0; + int curFrameRate = 0; + int64_t curDuration = 0; + + + curDuration = ((int64_t)((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp - pCtx->videoCtx.specificInfo.enc.oldTimeStamp); + if ((curDuration > 0) && (pCtx->videoCtx.specificInfo.enc.oldDuration > 0)) { + oldFrameRate = ROUND_UP(1E6 / pCtx->videoCtx.specificInfo.enc.oldDuration); + curFrameRate = ROUND_UP(1E6 / curDuration); + + if (CHECK_FRAMERATE_VALIDITY(curFrameRate, oldFrameRate)) { + if (Codec_OSAL_SetControl(pCtx, CODEC_OSAL_CID_ENC_FRAME_RATE, curFrameRate) != 0) { + ALOGE("%s: Failed to SetControl(oldts: %lld, curts: %lld, oldfps: %d, curfps: %d)", __FUNCTION__, + pCtx->videoCtx.specificInfo.enc.oldTimeStamp, + ((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp, + oldFrameRate, + curFrameRate); + + pthread_mutex_unlock(pMutex); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + pCtx->videoCtx.specificInfo.enc.oldFrameRate = curFrameRate; + } else { + ALOGV("%s: current ts: %lld, old ts: %lld, curFrameRate: %d, oldFrameRate: %d", __FUNCTION__, + (long long)((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp, + (long long)pCtx->videoCtx.specificInfo.enc.oldTimeStamp, + curFrameRate, oldFrameRate); + } + } + + if (curDuration > 0) + pCtx->videoCtx.specificInfo.enc.oldDuration = curDuration; + pCtx->videoCtx.specificInfo.enc.oldTimeStamp = (int64_t)((OMX_BUFFERHEADERTYPE *)pPrivate)->nTimeStamp; + } + } + + /* save HDR Dynamic Info to shared buffer instead of ioctl call */ + if (pCtx->videoCtx.instInfo.supportInfo.enc.bHDRDynamicInfoSupport == VIDEO_TRUE) { + ExynosVideoHdrDynamic *pHdrDynamic = ((ExynosVideoHdrDynamic *)pCtx->videoCtx.specificInfo.enc.pHDRInfoShareBufferAddr) + buf.index; + memcpy(pHdrDynamic, &(pCtx->videoCtx.inbufGeometry.HdrInfo.sHdrDynamic), sizeof(ExynosVideoHdrDynamic)); + } + + pthread_mutex_unlock(pMutex); + + if (Codec_OSAL_EnqueueBuf(pCtx, &buf) != 0) { + ALOGE("%s: Failed to enqueue input buffer", __FUNCTION__); + pthread_mutex_lock(pMutex); + pCtx->videoCtx.pInbuf[buf.index].pPrivate = NULL; + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_FALSE; + pthread_mutex_unlock(pMutex); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] ExtensionDequeue (Input) + */ +static ExynosVideoErrorType MFC_Encoder_ExtensionDequeue_Inbuf( + void *pHandle, + ExynosVideoBuffer *pVideoBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonInbuf == VIDEO_FALSE) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_SRC; + buf.nPlane = pCtx->videoCtx.nInbufPlanes; + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + + if (Codec_OSAL_DequeueBuf(pCtx, &buf) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pInMutex; + + if (buf.index >= 0) { + pthread_mutex_lock(pMutex); + + if (pCtx->videoCtx.pInbuf[buf.index].bQueued == VIDEO_TRUE) + memcpy(pVideoBuffer, &pCtx->videoCtx.pInbuf[buf.index], sizeof(ExynosVideoBuffer)); + else + ret = VIDEO_ERROR_NOBUFFERS; + memset(&pCtx->videoCtx.pInbuf[buf.index], 0, sizeof(ExynosVideoBuffer)); + + pCtx->videoCtx.pInbuf[buf.index].bQueued = VIDEO_FALSE; + + pthread_mutex_unlock(pMutex); + } else { + ALOGE("[%s] tag is (%d)", __FUNCTION__, buf.index); + ret = VIDEO_ERROR_NOBUFFERS; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] ExtensionEnqueue (Output) + */ +static ExynosVideoErrorType MFC_Encoder_ExtensionEnqueue_Outbuf( + void *pHandle, + void *pBuffer[], + unsigned long pFd[], + unsigned int nAllocLen[], + unsigned int nDataSize[], + int nPlanes, + void *pPrivate) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + int index, i; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.nOutbufPlanes < nPlanes) { + ALOGE("%s: Number of max planes : %d, nPlanes : %d", __FUNCTION__, + pCtx->videoCtx.nOutbufPlanes, nPlanes); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_DST; + buf.nPlane = pCtx->videoCtx.nOutbufPlanes; + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pOutMutex; + pthread_mutex_lock(pMutex); + + index = MFC_Encoder_FindEmpty_Outbuf(pCtx); + if (index == -1) { + pthread_mutex_unlock(pMutex); + ALOGE("%s: Failed to get index", __FUNCTION__); + ret = VIDEO_ERROR_NOBUFFERS; + goto EXIT; + } + buf.index = index; + ALOGV("%s: index:%d pCtx->videoCtx.pOutbuf[buf.index].bQueued:%d, pFd[0]:%lu", + __FUNCTION__, index, pCtx->videoCtx.pOutbuf[buf.index].bQueued, pFd[0]); + + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + for (i = 0; i < nPlanes; i++) { + if (buf.memory == CODEC_OSAL_MEM_TYPE_USERPTR) + buf.planes[i].addr = pBuffer[i]; + else + buf.planes[i].addr = (void *)pFd[i]; + + buf.planes[i].bufferSize = nAllocLen[i]; + buf.planes[i].dataLen = nDataSize[i]; + + /* Temporary storage for Dequeue */ + pCtx->videoCtx.pOutbuf[buf.index].planes[i].addr = pBuffer[i]; + pCtx->videoCtx.pOutbuf[buf.index].planes[i].fd = pFd[i]; + pCtx->videoCtx.pOutbuf[buf.index].planes[i].allocSize = nAllocLen[i]; + + ALOGV("%s: shared outbuf(%d) plane = %d addr = %p len = %d used = %d\n", __FUNCTION__, + index, i, + buf.planes[i].addr, + buf.planes[i].bufferSize, + buf.planes[i].dataLen); + } + + pCtx->videoCtx.pOutbuf[buf.index].pPrivate = pPrivate; + pCtx->videoCtx.pOutbuf[buf.index].bQueued = VIDEO_TRUE; + pthread_mutex_unlock(pMutex); + + if (Codec_OSAL_EnqueueBuf(pCtx, &buf) != 0) { + ALOGE("%s: Failed to enqueue output buffer", __FUNCTION__); + pthread_mutex_lock(pMutex); + pCtx->videoCtx.pOutbuf[buf.index].pPrivate = NULL; + pCtx->videoCtx.pOutbuf[buf.index].bQueued = VIDEO_FALSE; + pthread_mutex_unlock(pMutex); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + +EXIT: + return ret; +} + +/* + * [Encoder Buffer OPS] ExtensionDequeue (Output) + */ +static ExynosVideoErrorType MFC_Encoder_ExtensionDequeue_Outbuf( + void *pHandle, + ExynosVideoBuffer *pVideoBuffer) +{ + CodecOSALVideoContext *pCtx = (CodecOSALVideoContext *)pHandle; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + ExynosVideoBuffer *pOutbuf = NULL; + pthread_mutex_t *pMutex = NULL; + + CodecOSAL_Buffer buf; + + int i; + + if (pCtx == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + if (pCtx->videoCtx.bStreamonOutbuf == VIDEO_FALSE) { + pOutbuf = NULL; + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + memset(&buf, 0, sizeof(buf)); + buf.type = CODEC_OSAL_BUF_TYPE_DST; + buf.nPlane = pCtx->videoCtx.nOutbufPlanes; + if (pCtx->videoCtx.bShareOutbuf == VIDEO_TRUE) + buf.memory = Codec_OSAL_VideoMemoryToSystemMemory(pCtx->videoCtx.instInfo.nMemoryType); + else + buf.memory = CODEC_OSAL_MEM_TYPE_MMAP; + + /* returning DQBUF_EIO means MFC H/W status is invalid */ + if (Codec_OSAL_DequeueBuf(pCtx, &buf) != 0) { + if (errno == EIO) + ret = VIDEO_ERROR_DQBUF_EIO; + else + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pMutex = (pthread_mutex_t*)pCtx->videoCtx.pOutMutex; + pthread_mutex_lock(pMutex); + + pOutbuf = &pCtx->videoCtx.pOutbuf[buf.index]; + for (i = 0; i < pCtx->videoCtx.nOutbufPlanes; i++) + pOutbuf->planes[i].dataSize = buf.planes[i].dataLen; + + pOutbuf->frameType = buf.frameType; + + { + int64_t sec = (int64_t)(buf.timestamp.tv_sec * 1E6); + int64_t usec = (int64_t)buf.timestamp.tv_usec; + pOutbuf->timestamp = sec + usec; + } + + if (pCtx->videoCtx.pOutbuf[buf.index].bQueued == VIDEO_TRUE) + memcpy(pVideoBuffer, pOutbuf, sizeof(ExynosVideoBuffer)); + else + ret = VIDEO_ERROR_NOBUFFERS; + memset(pOutbuf, 0, sizeof(ExynosVideoBuffer)); + + pCtx->videoCtx.pOutbuf[buf.index].bQueued = VIDEO_FALSE; + pthread_mutex_unlock(pMutex); + +EXIT: + return ret; +} + +/* + * [Encoder OPS] Common + */ +static ExynosVideoEncOps defEncOps = { + .nSize = 0, + .Init = MFC_Encoder_Init, + .Finalize = MFC_Encoder_Finalize, + .Set_EncParam = MFC_Encoder_Set_EncParam, + .Set_FrameType = MFC_Encoder_Set_FrameType, + .Set_FrameRate = MFC_Encoder_Set_FrameRate, + .Set_BitRate = MFC_Encoder_Set_BitRate, + .Set_QpRange = MFC_Encoder_Set_QuantizationRange, + .Set_FrameSkip = MFC_Encoder_Set_FrameSkip, + .Set_IDRPeriod = MFC_Encoder_Set_IDRPeriod, + .Set_SliceMode = MFC_Encoder_Set_SliceMode, + .Set_FrameTag = MFC_Encoder_Set_FrameTag, + .Get_FrameTag = MFC_Encoder_Get_FrameTag, + .Enable_PrependSpsPpsToIdr = MFC_Encoder_Enable_PrependSpsPpsToIdr, + .Set_QosRatio = MFC_Encoder_Set_QosRatio, + .Set_LayerChange = MFC_Encoder_Set_LayerChange, + .Set_DynamicQpControl = MFC_Encoder_Set_DynamicQpControl, + .Set_MarkLTRFrame = MFC_Encoder_Set_MarkLTRFrame, + .Set_UsedLTRFrame = MFC_Encoder_Set_UsedLTRFrame, + .Set_BasePID = MFC_Encoder_Set_BasePID, + .Set_RoiInfo = MFC_Encoder_Set_RoiInfo, + .Enable_WeightedPrediction = MFC_Encoder_Enable_WeightedPrediction, + .Set_YSumData = MFC_Encoder_Set_YSumData, + .Set_IFrameRatio = MFC_Encoder_Set_IFrameRatio, + .Set_ColorAspects = MFC_Encoder_Set_ColorAspects, + .Enable_AdaptiveLayerBitrate = MFC_Encoder_Enable_AdaptiveLayerBitrate, + .Set_HDRStaticInfo = MFC_Encoder_Set_HDRStaticInfo, + .Set_HDRDynamicInfo = MFC_Encoder_Set_HDRDynamicInfo, + .Set_HeaderMode = MFC_Encoder_Set_HeaderMode, + .Set_DropControl = MFC_Encoder_Set_DropControl, + .Disable_DynamicFrameRate = MFC_Encoder_Disable_DynamicFrameRate, + .Set_ActualFormat = MFC_Encoder_Set_ActualFormat, + .Set_OperatingRate = MFC_Encoder_Set_OperatingRate, + .Set_Priority = MFC_Encoder_Set_Priority, +}; + +/* + * [Encoder Buffer OPS] Input + */ +static ExynosVideoEncBufferOps defInbufOps = { + .nSize = 0, + .Enable_Cacheable = MFC_Encoder_Enable_Cacheable_Inbuf, + .Set_Shareable = MFC_Encoder_Set_Shareable_Inbuf, + .Get_Buffer = NULL, + .Set_Geometry = MFC_Encoder_Set_Geometry_Inbuf, + .Get_Geometry = MFC_Encoder_Get_Geometry_Inbuf, + .Setup = MFC_Encoder_Setup_Inbuf, + .Run = MFC_Encoder_Run_Inbuf, + .Stop = MFC_Encoder_Stop_Inbuf, + .Enqueue = MFC_Encoder_Enqueue_Inbuf, + .Enqueue_All = NULL, + .Dequeue = MFC_Encoder_Dequeue_Inbuf, + .Register = MFC_Encoder_Register_Inbuf, + .Clear_RegisteredBuffer = MFC_Encoder_Clear_RegisteredBuffer_Inbuf, + .Clear_Queue = MFC_Encoder_Clear_Queued_Inbuf, + .Cleanup_Buffer = MFC_Encoder_Cleanup_Buffer_Inbuf, + .ExtensionEnqueue = MFC_Encoder_ExtensionEnqueue_Inbuf, + .ExtensionDequeue = MFC_Encoder_ExtensionDequeue_Inbuf, +}; + +/* + * [Encoder Buffer OPS] Output + */ +static ExynosVideoEncBufferOps defOutbufOps = { + .nSize = 0, + .Enable_Cacheable = MFC_Encoder_Enable_Cacheable_Outbuf, + .Set_Shareable = MFC_Encoder_Set_Shareable_Outbuf, + .Get_Buffer = MFC_Encoder_Get_Buffer_Outbuf, + .Set_Geometry = MFC_Encoder_Set_Geometry_Outbuf, + .Get_Geometry = MFC_Encoder_Get_Geometry_Outbuf, + .Setup = MFC_Encoder_Setup_Outbuf, + .Run = MFC_Encoder_Run_Outbuf, + .Stop = MFC_Encoder_Stop_Outbuf, + .Enqueue = MFC_Encoder_Enqueue_Outbuf, + .Enqueue_All = NULL, + .Dequeue = MFC_Encoder_Dequeue_Outbuf, + .Register = MFC_Encoder_Register_Outbuf, + .Clear_RegisteredBuffer = MFC_Encoder_Clear_RegisteredBuffer_Outbuf, + .Clear_Queue = MFC_Encoder_Clear_Queued_Outbuf, + .Cleanup_Buffer = MFC_Encoder_Cleanup_Buffer_Outbuf, + .ExtensionEnqueue = MFC_Encoder_ExtensionEnqueue_Outbuf, + .ExtensionDequeue = MFC_Encoder_ExtensionDequeue_Outbuf, +}; + +ExynosVideoErrorType MFC_Exynos_Video_GetInstInfo_Encoder( + ExynosVideoInstInfo *pVideoInstInfo) +{ + CodecOSALVideoContext videoCtx; + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + int codecRet = -1; + int mode = 0, version = 0; + + if (pVideoInstInfo == NULL) { + ALOGE("%s: invalid parameter", __FUNCTION__); + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + memset(&videoCtx, 0, sizeof(videoCtx)); + +#ifdef USE_HEVC_HWIP + if (pVideoInstInfo->eCodecType == VIDEO_CODING_HEVC) + codecRet = Codec_OSAL_DevOpen(VIDEO_HEVC_ENCODER_NAME, O_RDWR, &videoCtx); + else +#endif + if (pVideoInstInfo->bOTFMode == VIDEO_TRUE) + codecRet = Codec_OSAL_DevOpen(VIDEO_MFC_OTF_ENCODER_NAME, O_RDWR, &videoCtx); + else + codecRet = Codec_OSAL_DevOpen(VIDEO_MFC_ENCODER_NAME, O_RDWR, &videoCtx); + + if (codecRet < 0) { + ALOGE("%s: Failed to open encoder device", __FUNCTION__); + ret = VIDEO_ERROR_OPENFAIL; + goto EXIT; + } + + if (Codec_OSAL_GetControl(&videoCtx, CODEC_OSAL_CID_VIDEO_GET_VERSION_INFO, &version) != 0) { + ALOGW("%s: MFC version information is not available", __FUNCTION__); +#ifdef USE_HEVC_HWIP + if (pVideoInstInfo->eCodecType == VIDEO_CODING_HEVC) + pVideoInstInfo->HwVersion = (int)HEVC_10; + else +#endif + pVideoInstInfo->HwVersion = (int)MFC_65; + } else { + pVideoInstInfo->HwVersion = version; + } + + if (Codec_OSAL_GetControl(&videoCtx, CODEC_OSAL_CID_VIDEO_GET_EXT_INFO, &mode) != 0) { + memset(&(pVideoInstInfo->supportInfo.enc), 0, sizeof(pVideoInstInfo->supportInfo.enc)); + goto EXIT; + } + + pVideoInstInfo->supportInfo.enc.bPrioritySupport = (mode & (0x1 << 23))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bOperatingRateSupport = (mode & (0x1 << 18))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->bVideoBufFlagCtrl = (mode & (0x1 << 16))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bChromaQpSupport = (mode & (0x1 << 15))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bDropControlSupport = (mode & (0x1 << 14))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bHDRDynamicInfoSupport = (mode & (0x1 << 12))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bHDRStaticInfoSupport = (mode & (0x1 << 11))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bAdaptiveLayerBitrateSupport = (mode & (0x1 << 10))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bColorAspectsSupport = (mode & (0x1 << 9))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bIFrameRatioSupport = (mode & (0x1 << 8))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bPVCSupport = (mode & (0x1 << 7))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bFixedSliceSupport = (mode & (0x1 << 6))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bQpRangePBSupport = (mode & (0x1 << 5))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bRoiInfoSupport = (mode & (0x1 << 4))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bSkypeSupport = (mode & (0x1 << 3))? VIDEO_TRUE:VIDEO_FALSE; + pVideoInstInfo->supportInfo.enc.bTemporalSvcSupport = (mode & (0x1 << 2))? VIDEO_TRUE:VIDEO_FALSE; + if (mode & (0x1 << 1)) { + if (Codec_OSAL_GetControl(&videoCtx, CODEC_OSAL_CID_ENC_EXT_BUFFER_SIZE, &(pVideoInstInfo->supportInfo.enc.nSpareSize)) != 0) { + ALOGE("%s: Failed to GetControl(CODEC_OSAL_CID_ENC_EXT_BUFFER_SIZE)", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + } + + pVideoInstInfo->SwVersion = 0; + if (pVideoInstInfo->supportInfo.enc.bSkypeSupport == VIDEO_TRUE) { + int swVersion = 0; + + if (Codec_OSAL_GetControl(&videoCtx, CODEC_OSAL_CID_VIDEO_GET_DRIVER_VERSION, &swVersion) != 0) { + ALOGE("%s: Failed to GetControl(CODEC_OSAL_CID_VIDEO_GET_DRIVER_VERSION)", __FUNCTION__); + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + pVideoInstInfo->SwVersion = (unsigned int)swVersion; + } + + __Set_SupportFormat(pVideoInstInfo); + +EXIT: + Codec_OSAL_DevClose(&videoCtx); + + return ret; +} + +ExynosVideoErrorType MFC_Exynos_Video_Register_Encoder( + ExynosVideoEncOps *pEncOps, + ExynosVideoEncBufferOps *pInbufOps, + ExynosVideoEncBufferOps *pOutbufOps) +{ + ExynosVideoErrorType ret = VIDEO_ERROR_NONE; + + if ((pEncOps == NULL) || (pInbufOps == NULL) || (pOutbufOps == NULL)) { + ret = VIDEO_ERROR_BADPARAM; + goto EXIT; + } + + defEncOps.nSize = sizeof(defEncOps); + defInbufOps.nSize = sizeof(defInbufOps); + defOutbufOps.nSize = sizeof(defOutbufOps); + + memcpy((char *)pEncOps + sizeof(pEncOps->nSize), (char *)&defEncOps + sizeof(defEncOps.nSize), + pEncOps->nSize - sizeof(pEncOps->nSize)); + + memcpy((char *)pInbufOps + sizeof(pInbufOps->nSize), (char *)&defInbufOps + sizeof(defInbufOps.nSize), + pInbufOps->nSize - sizeof(pInbufOps->nSize)); + + memcpy((char *)pOutbufOps + sizeof(pOutbufOps->nSize), (char *)&defOutbufOps + sizeof(defOutbufOps.nSize), + pOutbufOps->nSize - sizeof(pOutbufOps->nSize)); + +EXIT: + return ret; +} diff --git a/videocodec/include/ExynosVideoApi.h b/videocodec/include/ExynosVideoApi.h new file mode 100644 index 0000000..30188e9 --- /dev/null +++ b/videocodec/include/ExynosVideoApi.h @@ -0,0 +1,881 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _EXYNOS_VIDEO_API_H_ +#define _EXYNOS_VIDEO_API_H_ + +#define VIDEO_BUFFER_MAX_PLANES 3 +#define VIDEO_BUFFER_MAX_NUM 32 + +#define LAST_FRAME 0x80000000 +#define EMPTY_DATA 0x40000000 +#define CSD_FRAME 0x20000000 +#define UNCOMP_FORMAT 0x10000000 + +/* Temporal SVC */ +#define VIDEO_MIN_TEMPORAL_LAYERS 1 +#define VIDEO_MAX_TEMPORAL_LAYERS 7 + + +typedef enum _ExynosVideoBoolType { + VIDEO_FALSE = 0, + VIDEO_TRUE = 1, +} ExynosVideoBoolType; + +typedef enum _ExynosVideoMemoryType { + VIDEO_MEMORY_DMABUF = 0, + VIDEO_MEMORY_USERPTR = 1, + VIDEO_MEMORY_MMAP = 2, +} ExynosVideoMemoryType; + +typedef enum _ExynosVideoErrorType { + VIDEO_ERROR_NONE = 1, + VIDEO_ERROR_BADPARAM = -1, + VIDEO_ERROR_OPENFAIL = -2, + VIDEO_ERROR_NOMEM = -3, + VIDEO_ERROR_APIFAIL = -4, + VIDEO_ERROR_MAPFAIL = -5, + VIDEO_ERROR_NOBUFFERS = -6, + VIDEO_ERROR_POLL = -7, + VIDEO_ERROR_DQBUF_EIO = -8, + VIDEO_ERROR_NOSUPPORT = -9, + VIDEO_ERROR_HEADERINFO = -10, + VIDEO_ERROR_WRONGBUFFERSIZE = -11, +} ExynosVideoErrorType; + +typedef enum _ExynosVideoCodingType { + VIDEO_CODING_UNKNOWN = 0, + VIDEO_CODING_MPEG2, + VIDEO_CODING_H263, + VIDEO_CODING_MPEG4, + VIDEO_CODING_VC1, + VIDEO_CODING_VC1_RCV, + VIDEO_CODING_AVC, + VIDEO_CODING_MVC, + VIDEO_CODING_VP8, + VIDEO_CODING_HEVC, + VIDEO_CODING_VP9, + VIDEO_CODING_XVID, + VIDEO_CODING_FIMV1, + VIDEO_CODING_FIMV2, + VIDEO_CODING_FIMV3, + VIDEO_CODING_FIMV4, + VIDEO_CODING_RESERVED, +} ExynosVideoCodingType; + +typedef enum _ExynosVideoColorFormatType { + VIDEO_COLORFORMAT_UNKNOWN = 0, + VIDEO_COLORFORMAT_NV12, + VIDEO_COLORFORMAT_NV12_S10B, + VIDEO_COLORFORMAT_NV12M, + VIDEO_COLORFORMAT_NV12M_S10B, + VIDEO_COLORFORMAT_NV12M_P010, + VIDEO_COLORFORMAT_NV21M, + VIDEO_COLORFORMAT_NV21M_S10B, + VIDEO_COLORFORMAT_NV21M_P010, + VIDEO_COLORFORMAT_NV12_TILED, + VIDEO_COLORFORMAT_NV12M_TILED, + VIDEO_COLORFORMAT_I420, + VIDEO_COLORFORMAT_I420M, + VIDEO_COLORFORMAT_YV12M, + VIDEO_COLORFORMAT_ARGB8888, + VIDEO_COLORFORMAT_BGRA8888, + VIDEO_COLORFORMAT_RGBA8888, + VIDEO_COLORFORMAT_NV12_SBWC, + VIDEO_COLORFORMAT_NV12M_SBWC, + VIDEO_COLORFORMAT_NV12_10B_SBWC, + VIDEO_COLORFORMAT_NV12M_10B_SBWC, + VIDEO_COLORFORMAT_NV21M_SBWC, + VIDEO_COLORFORMAT_NV21M_10B_SBWC, + VIDEO_COLORFORMAT_NV12_SBWC_L50, + VIDEO_COLORFORMAT_NV12_SBWC_L75, + VIDEO_COLORFORMAT_NV12M_SBWC_L50, + VIDEO_COLORFORMAT_NV12M_SBWC_L75, + VIDEO_COLORFORMAT_NV12_10B_SBWC_L40, + VIDEO_COLORFORMAT_NV12_10B_SBWC_L60, + VIDEO_COLORFORMAT_NV12_10B_SBWC_L80, + VIDEO_COLORFORMAT_NV12M_10B_SBWC_L40, + VIDEO_COLORFORMAT_NV12M_10B_SBWC_L60, + VIDEO_COLORFORMAT_NV12M_10B_SBWC_L80, + VIDEO_COLORFORMAT_MAX, +} ExynosVideoColorFormatType; + +typedef enum _ExynosVideoFrameType { + VIDEO_FRAME_NOT_CODED = 0, + VIDEO_FRAME_I = 0x1 << 0, + VIDEO_FRAME_P = 0x1 << 1, + VIDEO_FRAME_B = 0x1 << 2, + VIDEO_FRAME_SKIPPED = 0x1 << 3, + VIDEO_FRAME_CORRUPT = 0x1 << 4, + VIDEO_FRAME_OTHERS = 0x1 << 5, + VIDEO_FRAME_WITH_HDR_INFO = 0x1 << 6, + VIDEO_FRAME_WITH_BLACK_BAR = 0x1 << 7, + VIDEO_FRAME_NEED_ACTUAL_FORMAT = 0x1 << 8, + VIDEO_FRAME_NEED_ACTUAL_FRAMERATE = 0x1 << 9, + VIDEO_FRAME_CONCEALMENT = 0x1 << 10, +} ExynosVideoFrameType; + +typedef enum _ExynosVideoFrameStatusType { + VIDEO_FRAME_STATUS_UNKNOWN = 0, + VIDEO_FRAME_STATUS_DECODING_ONLY, + VIDEO_FRAME_STATUS_DISPLAY_DECODING, + VIDEO_FRAME_STATUS_DISPLAY_ONLY, + VIDEO_FRAME_STATUS_DECODING_FINISHED, + VIDEO_FRAME_STATUS_CHANGE_RESOL, + VIDEO_FRAME_STATUS_ENABLED_S3D, + VIDEO_FRAME_STATUS_LAST_FRAME, + VIDEO_FRAME_STATUS_DISPLAY_INTER_RESOL_CHANGE, +} ExynosVideoFrameStatusType; + +typedef enum _ExynosVideoFrameSkipMode { + VIDEO_FRAME_SKIP_DISABLED = 0, + VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT, + VIDEO_FRAME_SKIP_MODE_BUF_LIMIT, +} ExynosVideoFrameSkipMode; + +typedef enum _ExynosVideoMFCVersion { + MFC_ERROR = 0, + MFC_51 = 0x51, + MFC_61 = 0x61, + MFC_65 = 0x65, + MFC_72 = 0x72, + MFC_723 = 0x723, + MFC_77 = 0x77, + MFC_78 = 0x78, + MFC_78D = 0x78D, + MFC_80 = 0x80, + MFC_90 = 0x90, + MFC_92 = 0x92, + MFC_100 = 0xA0, + MFC_101 = 0xA01, + MFC_1010 = 0xA0A0, + MFC_1011 = 0xA0B0, + MFC_1020 = 0xA140, + MFC_1021 = 0x1021, + MFC_110 = 0x1100, + MFC_1120 = 0x1120, + MFC_120 = 0x1200, + MFC_1220 = 0x1202, + MFC_130 = 0x1300, + MFC_140 = 0x14000000, + MFC_1400 = 0x14000100, + MFC_1410 = 0x14100000, + MFC_150 = 0x1500000C, + MFC_1501 = 0x1500010C, +} ExynosVideoMFCVersion; + +typedef enum _ExynosVideoHEVCVersion { + HEVC_ERROR = 0, + HEVC_10 = 0x10, +} ExynosVideoHEVCVersion; + +typedef enum _ExynosVideoSecurityType { + VIDEO_NORMAL = 0, + VIDEO_SECURE = 1, +} ExynosVideoSecurityType; + +typedef enum _ExynosFilledDataType { + DATA_8BIT = 0x00, + DATA_10BIT = 0x01, + DATA_8BIT_WITH_2BIT = 0x11, + DATA_8BIT_SBWC = 0x100, + DATA_10BIT_SBWC = 0x101, +} ExynosFilledDataType; + +typedef enum _ExynosHdrInfoType { + HDR_INFO_NO_CHANGES = 0, + HDR_INFO_LIGHT = 0x1 << 0, /* SEI(StaticMeta-CTA.861.3) */ + HDR_INFO_LUMINANCE = 0x1 << 1, /* SEI(StaticMeta-CTA.861.3), Luminance, Display primariy 0, 1, 2, White point */ + HDR_INFO_MATRIX_COEFF_ONLY = 0x1 << 2, /* SPS */ + HDR_INFO_COLOR_ASPECTS = 0x1 << 3, /* SPS, MaxtixCoeff + Primaries + Transfer */ + HDR_INFO_RANGE = 0x1 << 4, /* SPS */ + HDR_INFO_DYNAMIC_META = 0x1 << 6, /* SEI(DynamicMeta-ST.2094-40) */ +} ExynosHdrInfoType; + +typedef struct _ExynosVideoRect { + unsigned int nTop; + unsigned int nLeft; + unsigned int nWidth; + unsigned int nHeight; +} ExynosVideoRect; + +typedef enum _ExynosRangeType { + RANGE_UNSPECIFIED = 0, + RANGE_FULL = 1, + RANGE_LIMITED = 2, +} ExynosRangeType; + +typedef enum _ExynosPrimariesType { + PRIMARIES_RESERVED = 0, + PRIMARIES_BT709_5 = 1, + PRIMARIES_UNSPECIFIED = 2, + PRIMARIES_BT470_6M = 4, + PRIMARIES_BT601_6_625 = 5, + PRIMARIES_BT601_6_525 = 6, + PRIMARIES_SMPTE_240M = 7, + PRIMARIES_GENERIC_FILM = 8, + PRIMARIES_BT2020 = 9, +} ExynosPrimariesType; + +typedef enum _ExynosTransferType { + TRANSFER_RESERVED = 0, + TRANSFER_BT709 = 1, + TRANSFER_UNSPECIFIED = 2, + TRANSFER_GAMMA_22 = 4, /* Assumed display gamma 2.2 */ + TRANSFER_GAMMA_28 = 5, /* Assumed display gamma 2.8 */ + TRANSFER_SMPTE_170M = 6, + TRANSFER_SMPTE_240M = 7, + TRANSFER_LINEAR = 8, + TRANSFER_XvYCC = 11, + TRANSFER_BT1361 = 12, + TRANSFER_SRGB = 13, + TRANSFER_BT2020_1 = 14, /* functionally the same as the 1, 6, 15 */ + TRANSFER_BT2020_2 = 15, /* functionally the same as the 1, 6, 14 */ + TRANSFER_ST2084 = 16, + TRANSFER_ST428 = 17, + TRANSFER_HLG = 18, +} ExynosTransferType; + +typedef enum _ExynosMatrixCoeffType { + MATRIX_COEFF_IDENTITY = 0, + MATRIX_COEFF_REC709 = 1, + MATRIX_COEFF_UNSPECIFIED = 2, + MATRIX_COEFF_RESERVED = 3, + MATRIX_COEFF_470_SYSTEM_M = 4, + MATRIX_COEFF_470_SYSTEM_BG = 5, + MATRIX_COEFF_SMPTE170M = 6, + MATRIX_COEFF_SMPTE240M = 7, + MATRIX_COEFF_BT2020 = 9, + MATRIX_COEFF_BT2020_CONSTANT = 10, +} ExynosMatrixCoeffType; + +typedef struct _ExynosVideoPrimaries { + unsigned short x; + unsigned short y; +} ExynosVideoPrimaries; + +typedef struct _ExynosVideoHdrStatic { + int max_pic_average_light; + int max_content_light; + int max_display_luminance; + int min_display_luminance; + ExynosVideoPrimaries red; + ExynosVideoPrimaries green; + ExynosVideoPrimaries blue; + ExynosVideoPrimaries white; +} ExynosVideoHdrStatic; + +#define HDR_MAX_SCL 3 +#define HDR_MAX_DISTRIBUTION 15 +#define HDR_MAX_CURVEANCHORS 15 + +typedef struct _ExynosVideoHdrWindowInfo { + unsigned int maxscl[HDR_MAX_SCL]; + unsigned int average_maxrgb; /* unused */ + + unsigned char num_distribution_maxrgb_percentiles; + unsigned char distribution_maxrgb_percentages[HDR_MAX_DISTRIBUTION]; + unsigned int distribution_maxrgb_percentiles[HDR_MAX_DISTRIBUTION]; + + unsigned int fraction_bright_pixels; /* unused */ + + unsigned short tone_mapping_flag; + unsigned short knee_point_x; + unsigned short knee_point_y; + unsigned short num_bezier_curve_anchors; + unsigned short bezier_curve_anchors[HDR_MAX_CURVEANCHORS]; + + unsigned char color_saturation_mapping_flag; /* unused */ + unsigned char color_saturation_weight; /* unused */ + + /* + * This field is reserved for ST2094-40 SEI below or the others + * window_upper_left_corner_x + * window_upper_left_corner_y + * window_lower_right_corner_x + * window_lower_right_corner_y + * center_of_ellipse_x + * center_of_ellipse_y + * rotation_angle + * semimajor_axis_internal_ellipse + * semimajor_axis_external_ellipse + * semiminor_axis_external_ellipse + * overlap_process_option + */ + unsigned int reserved[11]; +} ExynosVideoHdrWindowInfo; + + +/* HDR dynamic meta(ST.2094-40) */ +#define HDR_MAX_WINDOW 3 +typedef struct _ExynosVideoHdrDynamic { + unsigned int valid; + + unsigned char itu_t_t35_country_code; + unsigned short itu_t_t35_terminal_provider_code; + unsigned short itu_t_t35_terminal_provider_oriented_code; + + unsigned char application_identifier; + unsigned short application_version; + + unsigned char num_windows; /* HDR_MAX_WINDOW(3) */ + + unsigned int targeted_system_display_maximum_luminance; + unsigned char targeted_system_display_actual_peak_luminance_flag; /* unused */ + + unsigned char num_rows_targeted_system_display_actual_peak_luminance; /* unused */ + unsigned char num_cols_targeted_system_display_actual_peak_luminance; /* unused */ + + unsigned char mastering_display_actual_peak_luminance_flag; /* unused */ + unsigned char num_rows_mastering_display_actual_peak_luminance; /* unused */ + unsigned char num_cols_mastering_display_actual_peak_luminance; /* unused */ + + ExynosVideoHdrWindowInfo window_info[HDR_MAX_WINDOW]; + + /* + * This field is reserved for ST2094-40 SEI below or the others + * targeted_system_display_actual_peak_luminance[rows][cols] + * mastering_display_actual_peak_luminance[rows][cols] + */ + unsigned int reserved[11]; +} ExynosVideoHdrDynamic; + +typedef struct _ExynosVideoColorAspects { + ExynosRangeType eRangeType; + ExynosPrimariesType ePrimariesType; + ExynosTransferType eTransferType; + ExynosMatrixCoeffType eCoeffType; +} ExynosVideoColorAspects; + +typedef struct _ExynosVideoHdrInfo { + ExynosHdrInfoType eChangedType; + ExynosHdrInfoType eValidType; + ExynosVideoHdrDynamic sHdrDynamic; + ExynosVideoHdrStatic sHdrStatic; + ExynosVideoColorAspects sColorAspects; +} ExynosVideoHdrInfo; + +typedef struct _ExynosVideoGeometry { + unsigned int nFrameWidth; + unsigned int nFrameHeight; + unsigned int nStride; + unsigned int nSizeImage; + unsigned int nAlignPlaneSize[VIDEO_BUFFER_MAX_PLANES]; + unsigned int nPlaneCnt; + ExynosVideoRect cropRect; + ExynosVideoCodingType eCompressionFormat; + ExynosVideoColorFormatType eColorFormat; + ExynosVideoBoolType bInterlaced; + ExynosFilledDataType eFilledDataType; + ExynosVideoHdrInfo HdrInfo; +} ExynosVideoGeometry; + +typedef struct _ExynosVideoPlane { + void *addr; + unsigned int allocSize; + unsigned int dataSize; + unsigned long offset; + unsigned long fd; +} ExynosVideoPlane; + +typedef struct _ReleaseDPB { + int fd; + int fd1; + int fd2; +} ReleaseDPB; + +typedef struct _PrivateDataShareBuffer { + int index; + ReleaseDPB dpbFD[VIDEO_BUFFER_MAX_NUM]; +} PrivateDataShareBuffer; + +typedef struct _ExynosVideoBuffer { + ExynosVideoPlane planes[VIDEO_BUFFER_MAX_PLANES]; + ExynosVideoGeometry *pGeometry; + ExynosVideoFrameStatusType displayStatus; + ExynosVideoFrameType frameType; + int interlacedType; + ExynosVideoBoolType bQueued; + ExynosVideoBoolType bSlotUsed; + ExynosVideoBoolType bRegistered; + void *pPrivate; + PrivateDataShareBuffer PDSB; + int nIndexUseCnt; + int64_t timestamp; +} ExynosVideoBuffer; + +typedef struct _ExynosVideoFramePacking{ + int available; + unsigned int arrangement_id; + int arrangement_cancel_flag; + unsigned char arrangement_type; + int quincunx_sampling_flag; + unsigned char content_interpretation_type; + int spatial_flipping_flag; + int frame0_flipped_flag; + int field_views_flag; + int current_frame_is_frame0_flag; + unsigned char frame0_grid_pos_x; + unsigned char frame0_grid_pos_y; + unsigned char frame1_grid_pos_x; + unsigned char frame1_grid_pos_y; +} ExynosVideoFramePacking; + +typedef struct _ExynosVideoQPRange { + int QpMin_I; + int QpMax_I; + int QpMin_P; + int QpMax_P; + int QpMin_B; + int QpMax_B; +} ExynosVideoQPRange; + +/* for Temporal SVC */ +typedef struct _TemporalLayerShareBuffer { + /* In case of H.264 codec, + * nTemporalLayerCount contains the following data format. + * -------------------------------------------------------------------- + * | Temporal SVC Coding Style (16bit) | Temporal Layer Count (16bit) | + * -------------------------------------------------------------------- + * - Temporal SVC Coding Style Value + * 0 : default + * 1 : custom Temporal SVC mode(for MCD) + * + * - Temporal Layer Count Value + * 0 : Temporal SVC is disabled + * 1 ~ MAX : Temporal SVC is enabled + */ + unsigned int nTemporalLayerCount; + unsigned int nTemporalLayerBitrateRatio[VIDEO_MAX_TEMPORAL_LAYERS]; +} TemporalLayerShareBuffer; + +/* for Roi Info */ +typedef struct _RoiInfoShareBuffer { + unsigned long long pRoiMBInfo; /* For 32/64 bit compatibility */ + int nRoiMBInfoSize; + int nUpperQpOffset; + int nLowerQpOffset; + ExynosVideoBoolType bUseRoiInfo; +} RoiInfoShareBuffer; + +/* for Chroma QP Offset */ +typedef struct _ChromaQPOffset { + int Cr; + int Cb; +} ChromaQPOffset; + +typedef struct _ExynosVideoEncInitParam{ + /* Initial parameters */ + ExynosVideoFrameSkipMode FrameSkip; /* [IN] frame skip mode */ + int FMO; + int ASO; +}ExynosVideoEncInitParam; + +typedef struct _ExynosVideoEncCommonParam{ + /* common parameters */ + int SourceWidth; /* [IN] width of video to be encoded */ + int SourceHeight; /* [IN] height of video to be encoded */ + int IDRPeriod; /* [IN] GOP number(interval of I-frame) */ + int SliceMode; /* [IN] Multi slice mode */ + int RandomIntraMBRefresh; /* [IN] cyclic intra refresh */ + int EnableFRMRateControl; /* [IN] frame based rate control enable */ + int EnableMBRateControl; /* [IN] Enable macroblock-level rate control */ + int Bitrate; /* [IN] rate control parameter(bit rate) */ + int FrameQp; /* [IN] The quantization parameter of the frame */ + int FrameQp_P; /* [IN] The quantization parameter of the P frame */ + int EnableFRMQpControl; /* [IN] Enable quantization parameter per frame */ + ExynosVideoQPRange QpRange; /* [IN] Quantization range */ + int CBRPeriodRf; /* [IN] Reaction coefficient parameter for rate control */ + int PadControlOn; /* [IN] Enable padding control */ + int LumaPadVal; /* [IN] Luma pel value used to fill padding area */ + int CbPadVal; /* [IN] CB pel value used to fill padding area */ + int CrPadVal; /* [IN] CR pel value used to fill padding area */ + int FrameMap; /* [IN] Encoding input mode(tile mode or linear mode) */ + ExynosVideoBoolType PerceptualMode; /* [IN] Enable Perceptual video coding */ + ExynosVideoBoolType bFixedSlice; /* [IN] Whether Slice(MBs or bytes) size is fixed or not */ + ExynosVideoBoolType bDropControl; + ExynosVideoBoolType bDisableDFR; +}ExynosVideoEncCommonParam; + +typedef struct _ExynosVideoEncH264Param{ + /* H.264 specific parameters */ + int ProfileIDC; /* [IN] profile */ + int LevelIDC; /* [IN] level */ + int FrameQp_B; /* [IN] The quantization parameter of the B frame */ + int FrameRate; /* [IN] rate control parameter(frame rate) */ + int SliceArgument; /* [IN] MB number or byte number */ + int NumberBFrames; /* [IN] The number of consecutive B frame inserted */ + int NumberReferenceFrames; /* [IN] The number of reference pictures used */ + int NumberRefForPframes; /* [IN] The number of reference pictures used for encoding P pictures */ + int LoopFilterDisable; /* [IN] disable the loop filter */ + int LoopFilterAlphaC0Offset; /* [IN] Alpha & C0 offset for H.264 loop filter */ + int LoopFilterBetaOffset; /* [IN] Beta offset for H.264 loop filter */ + int SymbolMode; /* [IN] The mode of entropy coding(CABAC, CAVLC) */ + int PictureInterlace; /* [IN] Enables the interlace mode */ + int Transform8x8Mode; /* [IN] Allow 8x8 transform(This is allowed only for high profile) */ + int DarkDisable; /* [IN] Disable adaptive rate control on dark region */ + int SmoothDisable; /* [IN] Disable adaptive rate control on smooth region */ + int StaticDisable; /* [IN] Disable adaptive rate control on static region */ + int ActivityDisable; /* [IN] Disable adaptive rate control on high activity region */ + TemporalLayerShareBuffer TemporalSVC; /* [IN] Temporal SVC */ + int MaxTemporalLayerCount; /* [IN] Max Temporal Layer count */ + int HierarType; /* [IN] Hierarchal P & B */ + int VuiRestrictionEnable; /* [IN] Num Reorder Frames 0 enable */ + int HeaderWithIFrame; /* [IN] Header With I-Frame 0:disable, 1:enable*/ + int SarEnable; /* [IN] SarEnable */ + int SarIndex; /* [IN] SarIndex */ + int SarWidth; /* [IN] SarWidth */ + int SarHeight; /* [IN] SarHeight */ + int LTRFrames; /* [IN] LTR frames */ + int ROIEnable; /* [IN] ROIEnable */ + ChromaQPOffset chromaQPOffset; /* [IN] Chroma QP Offset */ +} ExynosVideoEncH264Param; + +typedef struct _ExynosVideoEncMpeg4Param { + /* MPEG4 specific parameters */ + int ProfileIDC; /* [IN] profile */ + int LevelIDC; /* [IN] level */ + int FrameQp_B; /* [IN] The quantization parameter of the B frame */ + int TimeIncreamentRes; /* [IN] frame rate */ + int VopTimeIncreament; /* [IN] frame rate */ + int SliceArgument; /* [IN] MB number or byte number */ + int NumberBFrames; /* [IN] The number of consecutive B frame inserted */ + int DisableQpelME; /* [IN] disable quarter-pixel motion estimation */ +} ExynosVideoEncMpeg4Param; + +typedef struct _ExynosVideoEncH263Param { + /* H.263 specific parameters */ + int FrameRate; /* [IN] rate control parameter(frame rate) */ +} ExynosVideoEncH263Param; + +typedef struct _ExynosVideoEncVp8Param { + /* VP8 specific parameters */ + int FrameRate; /* [IN] rate control parameter(frame rate) */ + int Vp8Version; /* [IN] vp8 version */ + int Vp8NumberOfPartitions; /* [IN] number of partitions */ + int Vp8FilterLevel; /* [IN] filter level */ + int Vp8FilterSharpness; /* [IN] filter sharpness */ + int Vp8GoldenFrameSel; /* [IN] indication of golden frame */ + int Vp8GFRefreshPeriod; /* [IN] refresh period of golden frame */ + int RefNumberForPFrame; /* [IN] number of refernce picture for p frame */ + int DisableIntraMd4x4; /* [IN] prevent intra 4x4 mode */ + TemporalLayerShareBuffer TemporalSVC; /* [IN] Temporal SVC */ +} ExynosVideoEncVp8Param; + +typedef struct _ExynosVideoEncHevcParam{ + /* HEVC specific parameters */ + int ProfileIDC; /* [IN] profile */ + int TierIDC; /* [IN] tier flag(MAIN, HIGH) */ + int LevelIDC; /* [IN] level */ + int FrameQp_B; /* [IN] The quantization parameter of the B frame */ + int FrameRate; /* [IN] rate control parameter(frame rate) */ + int MaxPartitionDepth; /* [IN] Max partition depth */ + int NumberBFrames; /* [IN] The number of consecutive B frame inserted */ + int NumberReferenceFrames; /* [IN] The number of reference pictures used */ + int NumberRefForPframes; /* [IN] The number of reference pictures used for encoding P pictures */ + int LoopFilterDisable; /* [IN] disable the loop filter */ + int LoopFilterSliceFlag; /* [IN] in loop filter, select across or not slice boundary */ + int LoopFilterTcOffset; /* [IN] TC offset for HEVC loop filter */ + int LoopFilterBetaOffset; /* [IN] Beta offset for HEVC loop filter */ + int LongtermRefEnable; /* [IN] long term reference enable */ + int LongtermUserRef; /* [IN] use long term reference index (0 or 1) */ + int LongtermStoreRef; /* [IN] use long term frame index (0 or 1) */ + int DarkDisable; /* [IN] Disable adaptive rate control on dark region */ + int SmoothDisable; /* [IN] Disable adaptive rate control on smooth region */ + int StaticDisable; /* [IN] Disable adaptive rate control on static region */ + int ActivityDisable; /* [IN] Disable adaptive rate control on high activity region */ + TemporalLayerShareBuffer TemporalSVC; /* [IN] Temporal SVC */ + int MaxTemporalLayerCount; /* [IN] Max Temporal Layer count */ + int ROIEnable; /* [IN] ROIEnable */ + ExynosVideoBoolType GPBEnable; /* [IN] GPBEnable */ + int HierarType; /* [IN] Hierarchal P & B */ + ChromaQPOffset chromaQPOffset; /* [IN] Chroma QP Offset */ +} ExynosVideoEncHevcParam; + +typedef struct _ExynosVideoEncVp9Param { + /* VP9 specific parameters */ + int FrameRate; /* [IN] rate control parameter(frame rate) */ + int Vp9Profile; /* [IN] vp9 profile */ + int Vp9Level; /* [IN] vp9 level */ + int Vp9GoldenFrameSel; /* [IN] indication of golden frame */ + int Vp9GFRefreshPeriod; /* [IN] refresh period of golden frame */ + int RefNumberForPFrame; /* [IN] number of refernce picture for p frame */ + int MaxPartitionDepth; /* [IN] Max partition depth */ + TemporalLayerShareBuffer TemporalSVC; /* [IN] Temporal SVC */ +} ExynosVideoEncVp9Param; + +typedef union _ExynosVideoEncCodecParam { + ExynosVideoEncH264Param h264; + ExynosVideoEncMpeg4Param mpeg4; + ExynosVideoEncH263Param h263; + ExynosVideoEncVp8Param vp8; + ExynosVideoEncHevcParam hevc; + ExynosVideoEncVp9Param vp9; +} ExynosVideoEncCodecParam; + +typedef struct _ExynosVideoEncParam { + ExynosVideoCodingType eCompressionFormat; + ExynosVideoEncInitParam initParam; + ExynosVideoEncCommonParam commonParam; + ExynosVideoEncCodecParam codecParam; +} ExynosVideoEncParam; + +typedef struct _ExynosVideoDecSupportInfo { + ExynosVideoBoolType bSkypeSupport; /* H.264 only */ + ExynosVideoBoolType bHDRDynamicInfoSupport; /* HEVC */ + ExynosVideoBoolType bDrvDPBManageSupport; + ExynosVideoBoolType bFrameErrorTypeSupport; + ExynosVideoBoolType bOperatingRateSupport; + ExynosVideoBoolType bPrioritySupport; +} ExynosVideoDecSupportInfo; + +typedef struct _ExynosVideoEncSupportInfo { + int nSpareSize; + ExynosVideoBoolType bTemporalSvcSupport; /* H.264, HEVC, VP8, VP9 */ + ExynosVideoBoolType bSkypeSupport; /* H.264 only */ + ExynosVideoBoolType bRoiInfoSupport; /* H.264, HEVC */ + ExynosVideoBoolType bQpRangePBSupport; + ExynosVideoBoolType bFixedSliceSupport; /* H.264 only */ + ExynosVideoBoolType bPVCSupport; /* H.264, HEVC, VP8, VP9 */ + ExynosVideoBoolType bIFrameRatioSupport; /* H.264, HEVC */ + ExynosVideoBoolType bColorAspectsSupport; /* H.264, HEVC, VP9 */ + ExynosVideoBoolType bAdaptiveLayerBitrateSupport; /* H.264, HEVC, VP8, VP9 */ + ExynosVideoBoolType bHDRStaticInfoSupport; /* HEVC */ + ExynosVideoBoolType bHDRDynamicInfoSupport; /* HEVC */ + ExynosVideoBoolType bDropControlSupport; + ExynosVideoBoolType bChromaQpSupport; /* H.264, HEVC */ + ExynosVideoBoolType bOperatingRateSupport; + ExynosVideoBoolType bPrioritySupport; +} ExynosVideoEncSupportInfo; + +typedef struct _ExynosVideoInstInfo { + unsigned int nSize; + + unsigned int nWidth; + unsigned int nHeight; + unsigned int nBitrate; + unsigned int xFramerate; + ExynosVideoMemoryType nMemoryType; + ExynosVideoCodingType eCodecType; + int HwVersion; + unsigned int SwVersion; + ExynosVideoSecurityType eSecurityType; + ExynosVideoColorFormatType supportFormat[VIDEO_COLORFORMAT_MAX]; + + union { + ExynosVideoDecSupportInfo dec; + ExynosVideoEncSupportInfo enc; + } supportInfo; + + ExynosVideoBoolType bOTFMode; + ExynosVideoBoolType bDisableDFR; + ExynosVideoBoolType bVideoBufFlagCtrl; +} ExynosVideoInstInfo; + +typedef struct _ExynosVideoDecInfo { + signed long nPrivateDataShareFD; + void *pPrivateDataShareAddress; + + signed long nHDRInfoShareBufferFD; + void *pHDRInfoShareBufferAddr; +} ExynosVideoDecInfo; + +typedef struct _ExynosVideoEncInfo { + signed long nTemporalLayerShareBufferFD; + void *pTemporalLayerShareBufferAddr; + + signed long nRoiShareBufferFD; + void *pRoiShareBufferAddr; + + signed long nHDRInfoShareBufferFD; + void *pHDRInfoShareBufferAddr; + + int oldFrameRate; + signed long long oldTimeStamp; + signed long long oldDuration; + + /* format changed encoding */ + ExynosVideoColorFormatType actualFormat; +} ExynosVideoEncInfo; + +typedef struct _ExynosVideoContext { + int hDevice; + ExynosVideoBoolType bShareInbuf; + ExynosVideoBoolType bShareOutbuf; + ExynosVideoBuffer *pInbuf; + ExynosVideoBuffer *pOutbuf; + ExynosVideoGeometry inbufGeometry; + ExynosVideoGeometry outbufGeometry; + int nInbufs; + int nInbufPlanes; + int nOutbufs; + int nOutbufPlanes; + ExynosVideoBoolType bStreamonInbuf; + ExynosVideoBoolType bStreamonOutbuf; + void *pPrivate; + void *pInMutex; + void *pOutMutex; + int hIONHandle; + ExynosVideoInstInfo instInfo; + union ExynosVideoSpecificInfo { + ExynosVideoDecInfo dec; + ExynosVideoEncInfo enc; + } specificInfo; + ExynosVideoBoolType bVideoBufFlagCtrl; +} ExynosVideoContext; + +typedef struct _ExynosVideoDecOps { + unsigned int nSize; + + void * (*Init)(ExynosVideoInstInfo *pVideoInfo); + ExynosVideoErrorType (*Finalize)(void *pHandle); + + /* Add new ops at the end of structure, no order change */ + ExynosVideoErrorType (*Set_FrameTag)(void *pHandle, int nFrameTag); + int (*Get_FrameTag)(void *pHandle); + int (*Get_ActualBufferCount)(void *pHandle); + ExynosVideoErrorType (*Set_DisplayDelay)(void *pHandle, int nDelay); + ExynosVideoErrorType (*Set_IFrameDecoding)(void *pHandle); + ExynosVideoErrorType (*Enable_PackedPB)(void *pHandle); + ExynosVideoErrorType (*Enable_LoopFilter)(void *pHandle); + ExynosVideoErrorType (*Enable_SliceMode)(void *pHandle); + ExynosVideoErrorType (*Enable_SEIParsing)(void *pHandle); + ExynosVideoErrorType (*Get_FramePackingInfo)(void *pHandle, ExynosVideoFramePacking *pFramepacking); + ExynosVideoErrorType (*Set_ImmediateDisplay)(void *pHandle); + ExynosVideoErrorType (*Enable_DTSMode)(void *pHandle); + ExynosVideoErrorType (*Set_QosRatio)(void *pHandle, int nRatio); + ExynosVideoErrorType (*Enable_DualDPBMode)(void *pHandle); + ExynosVideoErrorType (*Enable_DynamicDPB)(void *pHandle); + ExynosVideoErrorType (*Enable_DiscardRcvHeader)(void *pHandle); + ExynosVideoErrorType (*Get_HDRInfo)(void *pHandle, ExynosVideoHdrInfo *pHdrInfo); + ExynosVideoErrorType (*Set_SearchBlackBar)(void *pHandle, ExynosVideoBoolType bUse); + int (*Get_ActualFormat)(void *pHandle); + int (*Get_ActualFramerate)(void *pHandle); + ExynosVideoErrorType (*Set_OperatingRate)(void *pHandle, unsigned int framerate); + ExynosVideoErrorType (*Set_Priority)(void *pHandle, unsigned int priority); +} ExynosVideoDecOps; + +typedef struct _ExynosVideoEncOps { + unsigned int nSize; + void * (*Init)(ExynosVideoInstInfo *pVideoInfo); + ExynosVideoErrorType (*Finalize)(void *pHandle); + + /* Add new ops at the end of structure, no order change */ + ExynosVideoErrorType (*Set_EncParam)(void *pHandle, ExynosVideoEncParam*encParam); + ExynosVideoErrorType (*Set_FrameTag)(void *pHandle, int nFrameTag); + int (*Get_FrameTag)(void *pHandle); + ExynosVideoErrorType (*Set_FrameType)(void *pHandle, ExynosVideoFrameType eFrameType); + ExynosVideoErrorType (*Set_FrameRate)(void *pHandle, int nFramerate); + ExynosVideoErrorType (*Set_BitRate)(void *pHandle, int nBitrate); + ExynosVideoErrorType (*Set_QpRange)(void *pHandle, ExynosVideoQPRange qpRange); + ExynosVideoErrorType (*Set_FrameSkip)(void *pHandle, int nFrameSkip); + ExynosVideoErrorType (*Set_IDRPeriod)(void *pHandle, int nPeriod); + ExynosVideoErrorType (*Set_SliceMode)(void *pHandle, int nSliceMode, int nSliceArgument); + ExynosVideoErrorType (*Enable_PrependSpsPpsToIdr)(void *pHandle); + ExynosVideoErrorType (*Set_QosRatio)(void *pHandle, int nRatio); + ExynosVideoErrorType (*Set_LayerChange)(void *pHandle, TemporalLayerShareBuffer TemporalSVC); + ExynosVideoErrorType (*Set_DynamicQpControl)(void *pHandle, int nQp); + ExynosVideoErrorType (*Set_MarkLTRFrame)(void *pHandle, int nLongTermFrmIdx); + ExynosVideoErrorType (*Set_UsedLTRFrame)(void *pHandle, int nUsedLTRFrameNum); + ExynosVideoErrorType (*Set_BasePID)(void *pHandle, int nPID); + ExynosVideoErrorType (*Set_RoiInfo)(void *pHandle, RoiInfoShareBuffer *pRoiInfo); + ExynosVideoErrorType (*Enable_WeightedPrediction)(void *pHandle); + ExynosVideoErrorType (*Set_YSumData)(void *pHandle, unsigned int nHighData, unsigned int nLowData); + ExynosVideoErrorType (*Set_IFrameRatio)(void *pHandle, int nRatio); + ExynosVideoErrorType (*Set_ColorAspects)(void *pHandle, ExynosVideoColorAspects *pColorAspects); + ExynosVideoErrorType (*Enable_AdaptiveLayerBitrate)(void *pHandle, int bEnable); + ExynosVideoErrorType (*Set_HDRStaticInfo)(void *pHandle, ExynosVideoHdrStatic *pHDRStaticInfo); + ExynosVideoErrorType (*Set_HDRDynamicInfo)(void *pHandle, ExynosVideoHdrDynamic *pHDRDynamicInfo); + ExynosVideoErrorType (*Set_HeaderMode)(void *pHandle, ExynosVideoBoolType bSeparated); + ExynosVideoErrorType (*Set_DropControl)(void *pHandle, ExynosVideoBoolType bEnable); + ExynosVideoErrorType (*Disable_DynamicFrameRate)(void *pHandle, ExynosVideoBoolType bEnable); + ExynosVideoErrorType (*Set_ActualFormat)(void *pHandle, int nFormat); + ExynosVideoErrorType (*Set_OperatingRate)(void *pHandle, unsigned int framerate); + ExynosVideoErrorType (*Set_Priority)(void *pHandle, unsigned int priority); +} ExynosVideoEncOps; + +typedef struct _ExynosVideoDecBufferOps { + unsigned int nSize; + + /* Add new ops at the end of structure, no order change */ + ExynosVideoErrorType (*Enable_Cacheable)(void *pHandle); + ExynosVideoErrorType (*Set_Shareable)(void *pHandle); + ExynosVideoErrorType (*Get_Buffer)(void *pHandle, int nIndex, ExynosVideoBuffer **pBuffer); + ExynosVideoErrorType (*Set_Geometry)(void *pHandle, ExynosVideoGeometry *pBufferConf); + ExynosVideoErrorType (*Get_Geometry)(void *pHandle, ExynosVideoGeometry *pBufferConf); + ExynosVideoErrorType (*Get_BlackBarCrop)(void *pHandle, ExynosVideoRect *pBufferCrop); + ExynosVideoErrorType (*Setup)(void *pHandle, unsigned int nBufferCount); + ExynosVideoErrorType (*Run)(void *pHandle); + ExynosVideoErrorType (*Stop)(void *pHandle); + ExynosVideoErrorType (*Enqueue)(void *pHandle, void *pBuffer[], unsigned int nDataSize[], int nPlanes, void *pPrivate); + ExynosVideoErrorType (*Enqueue_All)(void *pHandle); + ExynosVideoBuffer * (*Dequeue)(void *pHandle); + ExynosVideoErrorType (*Register)(void *pHandle, ExynosVideoPlane *pPlanes, int nPlanes); + ExynosVideoErrorType (*Clear_RegisteredBuffer)(void *pHandle); + ExynosVideoErrorType (*Clear_Queue)(void *pHandle); + ExynosVideoErrorType (*Cleanup_Buffer)(void *pHandle); + ExynosVideoErrorType (*Apply_RegisteredBuffer)(void *pHandle); + ExynosVideoErrorType (*ExtensionEnqueue)(void *pHandle, void *pBuffer[], unsigned long pFd[], unsigned int nAllocLen[], unsigned int nDataSize[], int nPlanes, void *pPrivate); + ExynosVideoErrorType (*ExtensionDequeue)(void *pHandle, ExynosVideoBuffer *pVideoBuffer); +} ExynosVideoDecBufferOps; + +typedef struct _ExynosVideoEncBufferOps { + unsigned int nSize; + + /* Add new ops at the end of structure, no order change */ + ExynosVideoErrorType (*Enable_Cacheable)(void *pHandle); + ExynosVideoErrorType (*Set_Shareable)(void *pHandle); + ExynosVideoErrorType (*Get_Buffer)(void *pHandle, int nIndex, ExynosVideoBuffer **pBuffer); + ExynosVideoErrorType (*Set_Geometry)(void *pHandle, ExynosVideoGeometry *pBufferConf); + ExynosVideoErrorType (*Get_Geometry)(void *pHandle, ExynosVideoGeometry *pBufferConf); + ExynosVideoErrorType (*Setup)(void *pHandle, unsigned int nBufferCount); + ExynosVideoErrorType (*Run)(void *pHandle); + ExynosVideoErrorType (*Stop)(void *pHandle); + ExynosVideoErrorType (*Enqueue)(void *pHandle, void *pBuffer[], unsigned int nDataSize[], int nPlanes, void *pPrivate); + ExynosVideoErrorType (*Enqueue_All)(void *pHandle); + ExynosVideoBuffer * (*Dequeue)(void *pHandle); + ExynosVideoErrorType (*Register)(void *pHandle, ExynosVideoPlane *pPlanes, int nPlanes); + ExynosVideoErrorType (*Clear_RegisteredBuffer)(void *pHandle); + ExynosVideoErrorType (*Clear_Queue)(void *pHandle); + ExynosVideoErrorType (*Cleanup_Buffer)(void *pHandle); + ExynosVideoErrorType (*ExtensionEnqueue)(void *pHandle, void *pBuffer[], unsigned long pFd[], unsigned int nAllocLen[], unsigned int nDataSize[], int nPlanes, void *pPrivate); + ExynosVideoErrorType (*ExtensionDequeue)(void *pHandle, ExynosVideoBuffer *pVideoBuffer); +} ExynosVideoEncBufferOps; + +ExynosVideoErrorType Exynos_Video_GetInstInfo( + ExynosVideoInstInfo *pVideoInstInfo, ExynosVideoBoolType bIsDec); + +ExynosVideoErrorType Exynos_Video_Register_Decoder( + ExynosVideoDecOps *pDecOps, + ExynosVideoDecBufferOps *pInbufOps, + ExynosVideoDecBufferOps *pOutbufOps); + +ExynosVideoErrorType Exynos_Video_Register_Encoder( + ExynosVideoEncOps *pEncOps, + ExynosVideoEncBufferOps *pInbufOps, + ExynosVideoEncBufferOps *pOutbufOps); + +void Exynos_Video_Unregister_Decoder( + ExynosVideoDecOps *pDecOps, + ExynosVideoDecBufferOps *pInbufOps, + ExynosVideoDecBufferOps *pOutbufOps); + +void Exynos_Video_Unregister_Encoder( + ExynosVideoEncOps *pEncOps, + ExynosVideoEncBufferOps *pInbufOps, + ExynosVideoEncBufferOps *pOutbufOps); +#endif /* _EXYNOS_VIDEO_API_H_ */ diff --git a/videocodec/include/ExynosVideoDec.h b/videocodec/include/ExynosVideoDec.h new file mode 100644 index 0000000..a3c85d8 --- /dev/null +++ b/videocodec/include/ExynosVideoDec.h @@ -0,0 +1,36 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _EXYNOS_VIDEO_DEC_H_ +#define _EXYNOS_VIDEO_DEC_H_ + +#include "ExynosVideoApi.h" + +#define VIDEO_DECODER_INBUF_SIZE (1920 * 1080 * 3 / 2) +#define VIDEO_DECODER_DEFAULT_INBUF_PLANES 1 +#define VIDEO_DECODER_DEFAULT_OUTBUF_PLANES 2 +#define VIDEO_DECODER_POLL_TIMEOUT 25 + +ExynosVideoErrorType MFC_Exynos_Video_GetInstInfo_Decoder( + ExynosVideoInstInfo *pVideoInstInfo); + +int MFC_Exynos_Video_Register_Decoder( + ExynosVideoDecOps *pDecOps, + ExynosVideoDecBufferOps *pInbufOps, + ExynosVideoDecBufferOps *pOutbufOps); + +#endif /* _EXYNOS_VIDEO_DEC_H_ */ diff --git a/videocodec/include/ExynosVideoEnc.h b/videocodec/include/ExynosVideoEnc.h new file mode 100644 index 0000000..c8db24e --- /dev/null +++ b/videocodec/include/ExynosVideoEnc.h @@ -0,0 +1,83 @@ +/* + * + * Copyright 2012 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _EXYNOS_VIDEO_ENC_H_ +#define _EXYNOS_VIDEO_ENC_H_ + +#include "ExynosVideoApi.h" +#include "ExynosVideo_OSAL.h" + +#define VIDEO_ENCODER_DEFAULT_INBUF_PLANES 2 +#define VIDEO_ENCODER_DEFAULT_OUTBUF_PLANES 1 +#define VIDEO_ENCODER_POLL_TIMEOUT 25 + +#ifndef FRAME_RATE_CHANGE_THRESH_HOLD +#define FRAME_RATE_CHANGE_THRESH_HOLD 1 +#endif +#define FRAME_RATE_CHANGE_LIMIT 480 +#define ROUND_UP(x) ((((int)((x) * 10) % 10) > 4)? (x + 1):(x)) +#define CHECK_FRAMERATE_VALIDITY(x, y) \ + (((x) > 0) && \ + ((((x) - (y)) >= FRAME_RATE_CHANGE_THRESH_HOLD) || \ + (((y) - (x)) >= FRAME_RATE_CHANGE_THRESH_HOLD)) && \ + ((x) <= FRAME_RATE_CHANGE_LIMIT)) + +static const int vp8_qp_trans[] = +{ + 0, 1, 2, 3, 4, 5, 7, 8, + 9, 10, 12, 13, 15, 17, 18, 19, + 20, 21, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 33, 35, 37, 39, 41, + 43, 45, 47, 49, 51, 53, 55, 57, + 59, 61, 64, 67, 70, 73, 76, 79, + 82, 85, 88, 91, 94, 97, 100, 103, + 106, 109, 112, 115, 118, 121, 124, 127, +}; + +static const int vp9_qp_trans[] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 36, 40, 44, 48, 52, 56, 60, + 64, 68, 72, 76, 80, 84, 88, 92, + 96, 100, 104, 108, 112, 116, 120, 124, + 128, 132, 136, 140, 144, 148, 152, 156, + 160, 164, 168, 172, 176, 180, 184, 188, + 192, 196, 200, 204, 208, 212, 216, 220, + 224, 228, 232, 236, 240, 244, 249, 255, +}; + +#define GET_VALUE(value, min, max) ((value < min)? min:(value > max)? max:value) +#define GET_H264_QP_VALUE(value) GET_VALUE(value, 0, 51) +#define GET_MPEG4_QP_VALUE(value) GET_VALUE(value, 1, 31) +#define GET_H263_QP_VALUE(value) GET_VALUE(value, 1, 31) +#define GET_VP8_QP_VALUE(value) (vp8_qp_trans[GET_VALUE(value, 0, ((int)(sizeof(vp8_qp_trans)/sizeof(int)) - 1))]) +inline int GET_HEVC_QP_VALUE(int value, int version) { + if (version == MFC_120) + return GET_VALUE(value, -12, 51); + else + return GET_VALUE(value, 0, 51); +} +#define GET_VP9_QP_VALUE(value) (vp9_qp_trans[GET_VALUE(value, 1, ((int)(sizeof(vp9_qp_trans)/sizeof(int)) - 1))]) + +ExynosVideoErrorType MFC_Exynos_Video_GetInstInfo_Encoder( + ExynosVideoInstInfo *pVideoInstInfo); + +int MFC_Exynos_Video_Register_Encoder( + ExynosVideoEncOps *pEncOps, + ExynosVideoEncBufferOps *pInbufOps, + ExynosVideoEncBufferOps *pOutbufOps); + +#endif /* _EXYNOS_VIDEO_ENC_H_ */ diff --git a/videocodec/mfc_headers/exynos_mfc_media.h b/videocodec/mfc_headers/exynos_mfc_media.h new file mode 100644 index 0000000..e606841 --- /dev/null +++ b/videocodec/mfc_headers/exynos_mfc_media.h @@ -0,0 +1,275 @@ +/**************************************************************************** + **************************************************************************** + *** + *** This header was automatically generated from a Linux kernel header + *** of the same name, to make information necessary for userspace to + *** call into the kernel available to libc. It contains only constants, + *** structures, and macros generated from the original header, and thus, + *** contains no copyrightable information. + *** + *** To edit the content of this header, modify the corresponding + *** source file (e.g. under external/kernel-headers/original/) then + *** run bionic/libc/kernel/tools/update_all.py + *** + *** Any manual change here will be lost the next time this script will + *** be run. You've been warned! + *** + **************************************************************************** + ****************************************************************************/ +#ifndef __EXYNOS_MFC_MEDIA_H +#define __EXYNOS_MFC_MEDIA_H __FILE__ +#define V4L2_PIX_FMT_RGB32X v4l2_fourcc('R', 'G', 'B', 'X') +#define V4L2_PIX_FMT_YUV444_2P v4l2_fourcc('Y', 'U', '2', 'P') +#define V4L2_PIX_FMT_YVU444_2P v4l2_fourcc('Y', 'V', '2', 'P') +#define V4L2_PIX_FMT_YUV444_3P v4l2_fourcc('Y', 'U', '3', 'P') +#define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') +#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') +#define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') +#define V4L2_PIX_FMT_FIMV v4l2_fourcc('F', 'I', 'M', 'V') +#define V4L2_PIX_FMT_FIMV1 v4l2_fourcc('F', 'I', 'M', '1') +#define V4L2_PIX_FMT_FIMV2 v4l2_fourcc('F', 'I', 'M', '2') +#define V4L2_PIX_FMT_FIMV3 v4l2_fourcc('F', 'I', 'M', '3') +#define V4L2_PIX_FMT_FIMV4 v4l2_fourcc('F', 'I', 'M', '4') +#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') +#define V4L2_PIX_FMT_VP9 v4l2_fourcc('V', 'P', '9', '0') +#define V4L2_PIX_FMT_HEVC v4l2_fourcc('H', 'E', 'V', 'C') +#define V4L2_CID_MPEG_MFC_BASE (V4L2_CTRL_CLASS_MPEG | 0x2000) +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL (V4L2_CID_MPEG_MFC_BASE + 1) +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID (V4L2_CID_MPEG_MFC_BASE + 2) +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO (V4L2_CID_MPEG_MFC_BASE + 3) +#define V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS (V4L2_CID_MPEG_MFC_BASE + 4) +#define V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB (V4L2_CID_MPEG_MFC_BASE + 5) +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG (V4L2_CID_MPEG_MFC_BASE + 6) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_ENABLE (V4L2_CID_MPEG_MFC_BASE + 7) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA (V4L2_CID_MPEG_MFC_BASE + 8) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA (V4L2_CID_MPEG_MFC_BASE + 9) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_LUMA_BOT (V4L2_CID_MPEG_MFC_BASE + 10) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_DATA_CHROMA_BOT (V4L2_CID_MPEG_MFC_BASE + 11) +#define V4L2_CID_MPEG_MFC51_VIDEO_CRC_GENERATED (V4L2_CID_MPEG_MFC_BASE + 12) +#define V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE (V4L2_CID_MPEG_MFC_BASE + 13) +#define V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS (V4L2_CID_MPEG_MFC_BASE + 14) +#define V4L2_CID_MPEG_MFC51_VIDEO_LUMA_ADDR (V4L2_CID_MPEG_MFC_BASE + 15) +#define V4L2_CID_MPEG_MFC51_VIDEO_CHROMA_ADDR (V4L2_CID_MPEG_MFC_BASE + 16) +#define V4L2_CID_MPEG_MFC51_VIDEO_STREAM_SIZE (V4L2_CID_MPEG_MFC_BASE + 17) +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_COUNT (V4L2_CID_MPEG_MFC_BASE + 18) +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TYPE (V4L2_CID_MPEG_MFC_BASE + 19) +enum v4l2_mpeg_mfc51_video_frame_type { + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_NOT_CODED = 0, + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_I_FRAME = 1, + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_P_FRAME = 2, + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_B_FRAME = 3, + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_SKIPPED = 4, + V4L2_MPEG_MFC51_VIDEO_FRAME_TYPE_OTHERS = 5, +}; +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE (V4L2_CID_MPEG_MFC_BASE + 20) +#define V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE (V4L2_CID_MPEG_MFC_BASE + 21) +#define V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_TIME_RES (V4L2_CID_MPEG_MFC_BASE + 22) +#define V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA (V4L2_CID_MPEG_MFC_BASE + 23) +#define V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE (V4L2_CID_MPEG_MFC_BASE + 24) +#define V4L2_CID_MPEG_MFC6X_VIDEO_FRAME_DELTA (V4L2_CID_MPEG_MFC_BASE + 25) +#define V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH V4L2_CID_MPEG_VIDEO_GOP_SIZE +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE +#define V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH V4L2_CID_MPEG_VIDEO_BITRATE +#define V4L2_MPEG_VIDEO_MPEG4_LEVEL_6 8 +#define V4L2_MPEG_VIDEO_HEADER_MODE_AT_THE_READY 2 +#define V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB_ROW 3 +#define V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_HIGH 17 +#define V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_S_B V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY +#define V4L2_CID_MPEG_VIDEO_SRC_BUF_FLAG (V4L2_CID_MPEG_MFC_BASE + 30) +#define V4L2_CID_MPEG_VIDEO_DST_BUF_FLAG (V4L2_CID_MPEG_MFC_BASE + 31) +#define V4L2_CID_MPEG_VIDEO_FRAME_ERROR_TYPE (V4L2_CID_MPEG_MFC_BASE + 33) +#define V4L2_CID_MPEG_VIDEO_PRIORITY (V4L2_CID_MPEG_MFC_BASE + 36) +#define V4L2_CID_MPEG_VIDEO_CHROMA_QP_OFFSET_CB (V4L2_CID_MPEG_MFC_BASE + 38) +#define V4L2_CID_MPEG_VIDEO_CHROMA_QP_OFFSET_CR (V4L2_CID_MPEG_MFC_BASE + 39) +#define V4L2_CID_MPEG_VIDEO_DROP_CONTROL (V4L2_CID_MPEG_MFC_BASE + 41) +#define V4L2_CID_MPEG_VIDEO_H264_MVC_VIEW_ID (V4L2_CID_MPEG_MFC_BASE + 42) +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_STATUS (V4L2_CID_MPEG_MFC_BASE + 43) +#define V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING (V4L2_CID_MPEG_MFC_BASE + 44) +#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE (V4L2_CID_MPEG_MFC_BASE + 45) +#define V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR (V4L2_CID_MPEG_MFC_BASE + 46) +#define V4L2_CID_MPEG_VIDEO_DECODER_IMMEDIATE_DISPLAY (V4L2_CID_MPEG_MFC_BASE + 47) +#define V4L2_CID_MPEG_VIDEO_DECODER_DECODING_TIMESTAMP_MODE (V4L2_CID_MPEG_MFC_BASE + 48) +#define V4L2_CID_MPEG_VIDEO_DECODER_WAIT_DECODING_START (V4L2_CID_MPEG_MFC_BASE + 49) +#define V4L2_CID_MPEG_VIDEO_QOS_RATIO (V4L2_CID_MPEG_MFC_BASE + 50) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT (V4L2_CID_MPEG_MFC_BASE + 51) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH (V4L2_CID_MPEG_MFC_BASE + 52) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT0 (V4L2_CID_MPEG_MFC_BASE + 53) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT1 (V4L2_CID_MPEG_MFC_BASE + 54) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT2 (V4L2_CID_MPEG_MFC_BASE + 55) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT3 (V4L2_CID_MPEG_MFC_BASE + 56) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT4 (V4L2_CID_MPEG_MFC_BASE + 57) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT5 (V4L2_CID_MPEG_MFC_BASE + 58) +#define V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT6 (V4L2_CID_MPEG_MFC_BASE + 59) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_VERSION (V4L2_CID_MPEG_MFC_BASE + 60) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_RC_FRAME_RATE (V4L2_CID_MPEG_MFC_BASE + 61) +#define V4L2_CID_MPEG_VIDEO_VP8_MIN_QP (V4L2_CID_MPEG_MFC_BASE + 62) +#define V4L2_CID_MPEG_VIDEO_VP8_MAX_QP (V4L2_CID_MPEG_MFC_BASE + 63) +#define V4L2_CID_MPEG_VIDEO_VP8_I_FRAME_QP (V4L2_CID_MPEG_MFC_BASE + 64) +#define V4L2_CID_MPEG_VIDEO_VP8_P_FRAME_QP (V4L2_CID_MPEG_MFC_BASE + 65) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_OF_PARTITIONS (V4L2_CID_MPEG_MFC_BASE + 66) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_LEVEL (V4L2_CID_MPEG_MFC_BASE + 67) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_SHARPNESS (V4L2_CID_MPEG_MFC_BASE + 68) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_GOLDEN_FRAMESEL (V4L2_CID_MPEG_MFC_BASE + 69) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_GF_REFRESH_PERIOD (V4L2_CID_MPEG_MFC_BASE + 70) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_ENABLE (V4L2_CID_MPEG_MFC_BASE + 71) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER0 (V4L2_CID_MPEG_MFC_BASE + 72) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER1 (V4L2_CID_MPEG_MFC_BASE + 73) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER2 (V4L2_CID_MPEG_MFC_BASE + 74) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_REF_NUMBER_FOR_PFRAMES (V4L2_CID_MPEG_MFC_BASE + 75) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_DISABLE_INTRA_MD4X4 (V4L2_CID_MPEG_MFC_BASE + 76) +#define V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_TEMPORAL_LAYER (V4L2_CID_MPEG_MFC_BASE + 77) +#define V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT (V4L2_CID_MPEG_MFC_BASE + 78) +#define V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH (V4L2_CID_MPEG_MFC_BASE + 79) +#define V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT0 (V4L2_CID_MPEG_MFC_BASE + 80) +#define V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT1 (V4L2_CID_MPEG_MFC_BASE + 81) +#define V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT2 (V4L2_CID_MPEG_MFC_BASE + 82) +#define V4L2_CID_MPEG_MFC_GET_VERSION_INFO (V4L2_CID_MPEG_MFC_BASE + 91) +#define V4L2_CID_MPEG_MFC_GET_EXTRA_BUFFER_SIZE (V4L2_CID_MPEG_MFC_BASE + 92) +#define V4L2_CID_MPEG_MFC_SET_DUAL_DPB_MODE (V4L2_CID_MPEG_MFC_BASE + 93) +#define V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE (V4L2_CID_MPEG_MFC_BASE + 95) +#define V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE (V4L2_CID_MPEG_MFC_BASE + 96) +#define V4L2_CID_MPEG_MFC_GET_EXT_INFO (V4L2_CID_MPEG_MFC_BASE + 97) +#define V4L2_CID_MPEG_MFC_SET_BUF_PROCESS_TYPE (V4L2_CID_MPEG_MFC_BASE + 98) +#define V4L2_CID_MPEG_MFC_GET_10BIT_INFO (V4L2_CID_MPEG_MFC_BASE + 99) +#define V4L2_CID_MPEG_MFC_H264_ENABLE_LTR (V4L2_CID_MPEG_MFC_BASE + 100) +#define V4L2_CID_MPEG_MFC_H264_MARK_LTR (V4L2_CID_MPEG_MFC_BASE + 101) +#define V4L2_CID_MPEG_MFC_H264_USE_LTR (V4L2_CID_MPEG_MFC_BASE + 102) +#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB_ROW (V4L2_CID_MPEG_MFC_BASE + 103) +#define V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY (V4L2_CID_MPEG_MFC_BASE + 104) +#define V4L2_CID_MPEG_MFC_CONFIG_QP (V4L2_CID_MPEG_MFC_BASE + 105) +#define V4L2_CID_MPEG_MFC_H264_VUI_RESTRICTION_ENABLE (V4L2_CID_MPEG_MFC_BASE + 106) +#define V4L2_CID_MPEG_MFC_GET_DRIVER_INFO (V4L2_CID_MPEG_MFC_BASE + 107) +#define V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE (V4L2_CID_MPEG_MFC_BASE + 108) +#define V4L2_CID_MPEG_MFC_HDR_USER_SHARED_HANDLE (V4L2_CID_MPEG_MFC_BASE + 109) +#ifndef MAINLINE_FEATURE_IN_SINCE_4_19 +#define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP (V4L2_CID_MPEG_MFC_BASE + 110) +#define V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP (V4L2_CID_MPEG_MFC_BASE + 111) +#define V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP (V4L2_CID_MPEG_MFC_BASE + 112) +#define V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP (V4L2_CID_MPEG_MFC_BASE + 113) +#define V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP (V4L2_CID_MPEG_MFC_BASE + 114) +#endif +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE (V4L2_CID_MPEG_MFC_BASE + 115) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE (V4L2_CID_MPEG_MFC_BASE + 116) +#ifndef MAINLINE_FEATURE_IN_SINCE_4_19 +enum v4l2_mpeg_video_hevc_hier_coding_type { + V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_B = 0, + V4L2_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_P = 1, +}; +#endif +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER (V4L2_CID_MPEG_MFC_BASE + 117) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP (V4L2_CID_MPEG_MFC_BASE + 118) +#ifndef MAINLINE_FEATURE_IN_SINCE_4_19 +enum v4l2_mpeg_video_hevc_profile { + V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN = 0, + V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE = 1, + V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10 = 2, +}; +#define V4L2_CID_MPEG_VIDEO_HEVC_PROFILE (V4L2_CID_MPEG_MFC_BASE + 120) +#define V4L2_CID_MPEG_VIDEO_HEVC_LEVEL (V4L2_CID_MPEG_MFC_BASE + 121) +#endif +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_RC_FRAME_RATE (V4L2_CID_MPEG_MFC_BASE + 122) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TIER_FLAG (V4L2_CID_MPEG_MFC_BASE + 123) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_PARTITION_DEPTH (V4L2_CID_MPEG_MFC_BASE + 124) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES (V4L2_CID_MPEG_MFC_BASE + 125) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_DISABLE (V4L2_CID_MPEG_MFC_BASE + 126) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_SLICE_BOUNDARY (V4L2_CID_MPEG_MFC_BASE + 127) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_BETA_OFFSET_DIV2 (V4L2_CID_MPEG_MFC_BASE + 128) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_TC_OFFSET_DIV2 (V4L2_CID_MPEG_MFC_BASE + 129) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_TYPE (V4L2_CID_MPEG_MFC_BASE + 130) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_PERIOD (V4L2_CID_MPEG_MFC_BASE + 131) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LOSSLESS_CU_ENABLE (V4L2_CID_MPEG_MFC_BASE + 132) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE (V4L2_CID_MPEG_MFC_BASE + 133) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WAVEFRONT_ENABLE (V4L2_CID_MPEG_MFC_BASE + 134) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LTR_ENABLE (V4L2_CID_MPEG_MFC_BASE + 135) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_USER_REF (V4L2_CID_MPEG_MFC_BASE + 136) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STORE_REF (V4L2_CID_MPEG_MFC_BASE + 137) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIGN_DATA_HIDING (V4L2_CID_MPEG_MFC_BASE + 138) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_GENERAL_PB_ENABLE (V4L2_CID_MPEG_MFC_BASE + 139) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TEMPORAL_ID_ENABLE (V4L2_CID_MPEG_MFC_BASE + 140) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STRONG_SMOTHING_FLAG (V4L2_CID_MPEG_MFC_BASE + 141) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1 (V4L2_CID_MPEG_MFC_BASE + 142) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_DARK (V4L2_CID_MPEG_MFC_BASE + 143) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH (V4L2_CID_MPEG_MFC_BASE + 144) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_STATIC (V4L2_CID_MPEG_MFC_BASE + 145) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY (V4L2_CID_MPEG_MFC_BASE + 146) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT (V4L2_CID_MPEG_MFC_BASE + 147) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_TMV_PREDICTION (V4L2_CID_MPEG_MFC_BASE + 148) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WITHOUT_STARTCODE_ENABLE (V4L2_CID_MPEG_MFC_BASE + 149) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_QP_INDEX_CR (V4L2_CID_MPEG_MFC_BASE + 150) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_QP_INDEX_CB (V4L2_CID_MPEG_MFC_BASE + 151) +#define V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIZE_OF_LENGTH_FIELD (V4L2_CID_MPEG_MFC_BASE + 152) +#define V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR (V4L2_CID_MPEG_MFC_BASE + 153) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH (V4L2_CID_MPEG_MFC_BASE + 154) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0 (V4L2_CID_MPEG_MFC_BASE + 155) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1 (V4L2_CID_MPEG_MFC_BASE + 156) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2 (V4L2_CID_MPEG_MFC_BASE + 157) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3 (V4L2_CID_MPEG_MFC_BASE + 158) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4 (V4L2_CID_MPEG_MFC_BASE + 159) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5 (V4L2_CID_MPEG_MFC_BASE + 160) +#define V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6 (V4L2_CID_MPEG_MFC_BASE + 161) +#define V4L2_CID_MPEG_VIDEO_VP9_VERSION (V4L2_CID_MPEG_MFC_BASE + 163) +#define V4L2_CID_MPEG_VIDEO_VP9_RC_FRAME_RATE (V4L2_CID_MPEG_MFC_BASE + 164) +#define V4L2_CID_MPEG_VIDEO_VP9_MIN_QP (V4L2_CID_MPEG_MFC_BASE + 165) +#define V4L2_CID_MPEG_VIDEO_VP9_MAX_QP (V4L2_CID_MPEG_MFC_BASE + 166) +#define V4L2_CID_MPEG_VIDEO_VP9_I_FRAME_QP (V4L2_CID_MPEG_MFC_BASE + 167) +#define V4L2_CID_MPEG_VIDEO_VP9_P_FRAME_QP (V4L2_CID_MPEG_MFC_BASE + 168) +#define V4L2_CID_MPEG_VIDEO_VP9_GOLDEN_FRAMESEL (V4L2_CID_MPEG_MFC_BASE + 169) +#define V4L2_CID_MPEG_VIDEO_VP9_GF_REFRESH_PERIOD (V4L2_CID_MPEG_MFC_BASE + 170) +#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHY_QP_ENABLE (V4L2_CID_MPEG_MFC_BASE + 171) +#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_QP (V4L2_CID_MPEG_MFC_BASE + 172) +#define V4L2_CID_MPEG_VIDEO_VP9_REF_NUMBER_FOR_PFRAMES (V4L2_CID_MPEG_MFC_BASE + 173) +#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER (V4L2_CID_MPEG_MFC_BASE + 174) +#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH (V4L2_CID_MPEG_MFC_BASE + 175) +#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT0 (V4L2_CID_MPEG_MFC_BASE + 176) +#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT1 (V4L2_CID_MPEG_MFC_BASE + 177) +#define V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT2 (V4L2_CID_MPEG_MFC_BASE + 178) +#define V4L2_CID_MPEG_VIDEO_VP9_MAX_PARTITION_DEPTH (V4L2_CID_MPEG_MFC_BASE + 179) +#define V4L2_CID_MPEG_VIDEO_VP9_DISABLE_INTRA_PU_SPLIT (V4L2_CID_MPEG_MFC_BASE + 180) +#define V4L2_CID_MPEG_VIDEO_DISABLE_IVF_HEADER (V4L2_CID_MPEG_MFC_BASE + 181) +#ifndef MAINLINE_FEATURE_IN_SINCE_4_19 +#define V4L2_CID_MPEG_VIDEO_VP9_PROFILE (V4L2_CID_MPEG_MFC_BASE + 182) +#endif +#define V4L2_CID_MPEG_VIDEO_UNCOMP_FMT (V4L2_CID_MPEG_MFC_BASE + 184) +#define V4L2_CID_MPEG_VIDEO_ROI_CONTROL (V4L2_CID_MPEG_MFC_BASE + 190) +#define V4L2_CID_MPEG_VIDEO_ROI_ENABLE (V4L2_CID_MPEG_MFC_BASE + 191) +#define V4L2_CID_MPEG_VIDEO_RC_PVC_ENABLE (V4L2_CID_MPEG_MFC_BASE + 192) +#define V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER (V4L2_CID_MPEG_MFC_BASE + 193) +#define V4L2_CID_MPEG_VIDEO_BLACK_BAR_DETECT (V4L2_CID_MPEG_MFC_BASE + 194) +#define V4L2_CID_MPEG_MFC_H264_NUM_OF_LTR (V4L2_CID_MPEG_MFC_BASE + 195) +#define V4L2_CID_MPEG_VIDEO_WEIGHTED_ENABLE (V4L2_CID_MPEG_MFC_BASE + 196) +#define V4L2_CID_MPEG_VIDEO_YSUM (V4L2_CID_MPEG_MFC_BASE + 197) +#define V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA (V4L2_CID_MPEG_MFC_BASE + 198) +#define V4L2_CID_MPEG_VIDEO_HIERARCHICAL_BITRATE_CTRL (V4L2_CID_MPEG_MFC_BASE + 199) +#define V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P (V4L2_CID_MPEG_MFC_BASE + 201) +#define V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P (V4L2_CID_MPEG_MFC_BASE + 202) +#define V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P (V4L2_CID_MPEG_MFC_BASE + 203) +#define V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P (V4L2_CID_MPEG_MFC_BASE + 204) +#define V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P (V4L2_CID_MPEG_MFC_BASE + 205) +#define V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P (V4L2_CID_MPEG_MFC_BASE + 206) +#define V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P (V4L2_CID_MPEG_MFC_BASE + 207) +#define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P (V4L2_CID_MPEG_MFC_BASE + 208) +#define V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P (V4L2_CID_MPEG_MFC_BASE + 209) +#define V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P (V4L2_CID_MPEG_MFC_BASE + 210) +#define V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P (V4L2_CID_MPEG_MFC_BASE + 211) +#define V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P (V4L2_CID_MPEG_MFC_BASE + 212) +#define V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B (V4L2_CID_MPEG_MFC_BASE + 213) +#define V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B (V4L2_CID_MPEG_MFC_BASE + 214) +#define V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B (V4L2_CID_MPEG_MFC_BASE + 215) +#define V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B (V4L2_CID_MPEG_MFC_BASE + 216) +#define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B (V4L2_CID_MPEG_MFC_BASE + 217) +#define V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B (V4L2_CID_MPEG_MFC_BASE + 218) +#define V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT (V4L2_CID_MPEG_MFC_BASE + 219) +#define V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT (V4L2_CID_MPEG_MFC_BASE + 220) +#define V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE (V4L2_CID_MPEG_MFC_BASE + 221) +#define V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE (V4L2_CID_MPEG_MFC_BASE + 222) +#define V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS (V4L2_CID_MPEG_MFC_BASE + 223) +#define V4L2_CID_MPEG_VIDEO_FORMAT (V4L2_CID_MPEG_MFC_BASE + 224) +#define V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT (V4L2_CID_MPEG_MFC_BASE + 225) +#define V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0 (V4L2_CID_MPEG_MFC_BASE + 226) +#define V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1 (V4L2_CID_MPEG_MFC_BASE + 227) +#define V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2 (V4L2_CID_MPEG_MFC_BASE + 228) +#define V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG (V4L2_CID_MPEG_MFC_BASE + 229) +#define V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES (V4L2_CID_MPEG_MFC_BASE + 230) +#define V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS (V4L2_CID_MPEG_MFC_BASE + 231) +#define V4L2_CID_MPEG_VIDEO_STATIC_INFO_ENABLE (V4L2_CID_MPEG_MFC_BASE + 232) +#endif diff --git a/videocodec/osal/ExynosVideo_OSAL.c b/videocodec/osal/ExynosVideo_OSAL.c new file mode 100644 index 0000000..a2b3034 --- /dev/null +++ b/videocodec/osal/ExynosVideo_OSAL.c @@ -0,0 +1,2163 @@ +/* + * + * Copyright 2016 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file ExynosVideo_OSAL.c + * @brief ExynosVideo OSAL + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 1.0.0 + * @history + * 2016.01.07 : Create + */ + +#include +#include + +#include "ExynosVideo_OSAL.h" +#include "ExynosVideo_OSAL_Dec.h" +#include "ExynosVideo_OSAL_Enc.h" + +#include "ExynosVideoDec.h" +#include "ExynosVideoEnc.h" + +/* #define LOG_NDEBUG 0 */ +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "ExynosVideoOSAL" + +#define GET_16BIT_HIGH(x) ((x >> 16) & 0xFFFF) +#define GET_16BIT_LOW(x) (x & 0xFFFF) +#define SET_16BIT_TO_HIGH(x) ((0xFFFF & x) << 16) + +static struct { + int primaries; + int transfer; + int coeff; +} ColorSpaceToColorAspects[] = +{ + {PRIMARIES_UNSPECIFIED, TRANSFER_UNSPECIFIED, MATRIX_COEFF_UNSPECIFIED}, /* Unknown */ + {PRIMARIES_BT601_6_525, TRANSFER_SMPTE_170M, MATRIX_COEFF_SMPTE170M}, /* Rec. ITU-R BT.601-7 */ + {PRIMARIES_BT709_5, TRANSFER_SMPTE_170M, MATRIX_COEFF_REC709}, /* Rec. ITU-R BT.709-6 */ + {PRIMARIES_BT601_6_525, TRANSFER_SMPTE_170M, MATRIX_COEFF_SMPTE170M}, /* SMPTE-170 */ + {PRIMARIES_BT601_6_525, TRANSFER_SMPTE_240M, MATRIX_COEFF_SMPTE240M}, /* SMPTE-240 */ + {PRIMARIES_BT2020, TRANSFER_SMPTE_170M, MATRIX_COEFF_BT2020}, /* Rec. ITU-R BT.2020-2 */ + {PRIMARIES_RESERVED, TRANSFER_RESERVED, MATRIX_COEFF_IDENTITY}, /* Reserved */ + {PRIMARIES_RESERVED, TRANSFER_SMPTE_170M, MATRIX_COEFF_REC709}, /* sRGB (IEC 61966-2-1) */ +}; + +int Codec_OSAL_VideoMemoryToSystemMemory( + ExynosVideoMemoryType eMemoryType) +{ + if (eMemoryType == VIDEO_MEMORY_DMABUF) + return V4L2_MEMORY_DMABUF; + + if (eMemoryType == VIDEO_MEMORY_USERPTR) + return V4L2_MEMORY_USERPTR; + + return V4L2_MEMORY_MMAP; +} + +unsigned int Codec_OSAL_CodingTypeToCompressdFormat( + ExynosVideoCodingType eCodingType) +{ + unsigned int nCompressdFormat = V4L2_PIX_FMT_H264; + + switch (eCodingType) { + case VIDEO_CODING_AVC: + nCompressdFormat = V4L2_PIX_FMT_H264; + break; + case VIDEO_CODING_MPEG4: + nCompressdFormat = V4L2_PIX_FMT_MPEG4; + break; + case VIDEO_CODING_VP8: + nCompressdFormat = V4L2_PIX_FMT_VP8; + break; + case VIDEO_CODING_H263: + nCompressdFormat = V4L2_PIX_FMT_H263; + break; + case VIDEO_CODING_VC1: + nCompressdFormat = V4L2_PIX_FMT_VC1_ANNEX_G; + break; + case VIDEO_CODING_VC1_RCV: + nCompressdFormat = V4L2_PIX_FMT_VC1_ANNEX_L; + break; + case VIDEO_CODING_MPEG2: + nCompressdFormat = V4L2_PIX_FMT_MPEG2; + break; + case VIDEO_CODING_HEVC: + nCompressdFormat = V4L2_PIX_FMT_HEVC; + break; + case VIDEO_CODING_VP9: + nCompressdFormat = V4L2_PIX_FMT_VP9; + break; + default: + nCompressdFormat = V4L2_PIX_FMT_H264; + break; + } + + return nCompressdFormat; +} + +ExynosVideoColorFormatType Codec_OSAL_PixelFormatToColorFormat( + unsigned int nPixelFormat) +{ + ExynosVideoColorFormatType eColorFormat = VIDEO_COLORFORMAT_NV12_TILED; + + switch (nPixelFormat) { + case V4L2_PIX_FMT_NV12M: + eColorFormat = VIDEO_COLORFORMAT_NV12M; + break; + case V4L2_PIX_FMT_NV12M_S10B: + eColorFormat = VIDEO_COLORFORMAT_NV12M_S10B; + break; + case V4L2_PIX_FMT_NV12M_P010: + eColorFormat = VIDEO_COLORFORMAT_NV12M_P010; + break; + case V4L2_PIX_FMT_NV21M: + eColorFormat = VIDEO_COLORFORMAT_NV21M; + break; + case V4L2_PIX_FMT_NV21M_S10B: + eColorFormat = VIDEO_COLORFORMAT_NV21M_S10B; + break; + case V4L2_PIX_FMT_NV21M_P010: + eColorFormat = VIDEO_COLORFORMAT_NV21M_P010; + break; + case V4L2_PIX_FMT_YUV420M: + eColorFormat = VIDEO_COLORFORMAT_I420M; + break; + case V4L2_PIX_FMT_YVU420M: + eColorFormat = VIDEO_COLORFORMAT_YV12M; + break; + case V4L2_PIX_FMT_NV12M_SBWC_8B: + eColorFormat = VIDEO_COLORFORMAT_NV12M_SBWC; + break; + case V4L2_PIX_FMT_NV12M_SBWC_10B: + eColorFormat = VIDEO_COLORFORMAT_NV12M_10B_SBWC; + break; + case V4L2_PIX_FMT_NV21M_SBWC_8B: + eColorFormat = VIDEO_COLORFORMAT_NV21M_SBWC; + break; + case V4L2_PIX_FMT_NV21M_SBWC_10B: + eColorFormat = VIDEO_COLORFORMAT_NV21M_10B_SBWC; + break; +#ifdef USE_SINGLE_PALNE_SUPPORT + case V4L2_PIX_FMT_NV12N: + eColorFormat = VIDEO_COLORFORMAT_NV12; + break; + case V4L2_PIX_FMT_NV12N_10B: + eColorFormat = VIDEO_COLORFORMAT_NV12_S10B; + break; + case V4L2_PIX_FMT_YUV420N: + eColorFormat = VIDEO_COLORFORMAT_I420; + break; + case V4L2_PIX_FMT_NV12NT: + eColorFormat = VIDEO_COLORFORMAT_NV12_TILED; + break; + case V4L2_PIX_FMT_NV12N_SBWC_8B: + eColorFormat = VIDEO_COLORFORMAT_NV12_SBWC; + break; + case V4L2_PIX_FMT_NV12N_SBWC_10B: + eColorFormat = VIDEO_COLORFORMAT_NV12_10B_SBWC; + break; +#endif + case V4L2_PIX_FMT_ARGB32: + eColorFormat = VIDEO_COLORFORMAT_ARGB8888; + break; + case V4L2_PIX_FMT_BGR32: + eColorFormat = VIDEO_COLORFORMAT_BGRA8888; + break; + case V4L2_PIX_FMT_RGB32X: + eColorFormat = VIDEO_COLORFORMAT_RGBA8888; + break; + case V4L2_PIX_FMT_NV12MT: + case V4L2_PIX_FMT_NV12MT_16X16: + default: + eColorFormat = VIDEO_COLORFORMAT_NV12M_TILED; + break; + } + + return eColorFormat; +} + +unsigned int Codec_OSAL_ColorFormatToPixelFormat( + ExynosVideoColorFormatType eColorFormat, + int nHwVersion) +{ + unsigned int nPixelFormat = V4L2_PIX_FMT_NV12M; + + switch (eColorFormat) { + case VIDEO_COLORFORMAT_NV12M: + nPixelFormat = V4L2_PIX_FMT_NV12M; + break; + case VIDEO_COLORFORMAT_NV12M_S10B: + nPixelFormat = V4L2_PIX_FMT_NV12M_S10B; + break; + case VIDEO_COLORFORMAT_NV12M_P010: + nPixelFormat = V4L2_PIX_FMT_NV12M_P010; + break; + case VIDEO_COLORFORMAT_NV21M: + nPixelFormat = V4L2_PIX_FMT_NV21M; + break; + case VIDEO_COLORFORMAT_NV21M_S10B: + nPixelFormat = V4L2_PIX_FMT_NV21M_S10B; + break; + case VIDEO_COLORFORMAT_NV21M_P010: + nPixelFormat = V4L2_PIX_FMT_NV21M_P010; + break; + case VIDEO_COLORFORMAT_I420M: + nPixelFormat = V4L2_PIX_FMT_YUV420M; + break; + case VIDEO_COLORFORMAT_YV12M: + nPixelFormat = V4L2_PIX_FMT_YVU420M; + break; + case VIDEO_COLORFORMAT_NV12M_SBWC: + nPixelFormat = V4L2_PIX_FMT_NV12M_SBWC_8B; + break; + case VIDEO_COLORFORMAT_NV12M_10B_SBWC: + nPixelFormat = V4L2_PIX_FMT_NV12M_SBWC_10B; + break; + case VIDEO_COLORFORMAT_NV21M_SBWC: + nPixelFormat = V4L2_PIX_FMT_NV21M_SBWC_8B; + break; + case VIDEO_COLORFORMAT_NV21M_10B_SBWC: + nPixelFormat = V4L2_PIX_FMT_NV21M_SBWC_10B; + break; + case VIDEO_COLORFORMAT_NV12M_SBWC_L50: + case VIDEO_COLORFORMAT_NV12M_SBWC_L75: + nPixelFormat = V4L2_PIX_FMT_NV12M_SBWCL_8B; + break; + case VIDEO_COLORFORMAT_NV12M_10B_SBWC_L40: + case VIDEO_COLORFORMAT_NV12M_10B_SBWC_L60: + case VIDEO_COLORFORMAT_NV12M_10B_SBWC_L80: + nPixelFormat = V4L2_PIX_FMT_NV12M_SBWCL_10B; + break; +#ifdef USE_SINGLE_PALNE_SUPPORT + case VIDEO_COLORFORMAT_NV12: + nPixelFormat = V4L2_PIX_FMT_NV12N; + break; + case VIDEO_COLORFORMAT_NV12_S10B: + nPixelFormat = V4L2_PIX_FMT_NV12N_10B; + break; + case VIDEO_COLORFORMAT_I420: + nPixelFormat = V4L2_PIX_FMT_YUV420N; + break; + case VIDEO_COLORFORMAT_NV12_TILED: + nPixelFormat = V4L2_PIX_FMT_NV12NT; + break; + case VIDEO_COLORFORMAT_NV12_SBWC: + nPixelFormat = V4L2_PIX_FMT_NV12N_SBWC_8B; + break; + case VIDEO_COLORFORMAT_NV12_10B_SBWC: + nPixelFormat = V4L2_PIX_FMT_NV12N_SBWC_10B; + break; + case VIDEO_COLORFORMAT_NV12_SBWC_L50: + case VIDEO_COLORFORMAT_NV12_SBWC_L75: + nPixelFormat = V4L2_PIX_FMT_NV12N_SBWCL_8B; + break; + case VIDEO_COLORFORMAT_NV12_10B_SBWC_L40: + case VIDEO_COLORFORMAT_NV12_10B_SBWC_L60: + case VIDEO_COLORFORMAT_NV12_10B_SBWC_L80: + nPixelFormat = V4L2_PIX_FMT_NV12N_SBWCL_10B; + break; +#endif + case VIDEO_COLORFORMAT_ARGB8888: + nPixelFormat = V4L2_PIX_FMT_ARGB32; + break; + case VIDEO_COLORFORMAT_BGRA8888: + nPixelFormat = V4L2_PIX_FMT_BGR32; + break; + case VIDEO_COLORFORMAT_RGBA8888: + nPixelFormat = V4L2_PIX_FMT_RGB32X; + break; + case VIDEO_COLORFORMAT_NV12M_TILED: + if (nHwVersion == (int)MFC_51) + nPixelFormat = V4L2_PIX_FMT_NV12MT; + else + nPixelFormat = V4L2_PIX_FMT_NV12MT_16X16; + break; + default: + nPixelFormat = V4L2_PIX_FMT_NV12M; + break; + } + + return nPixelFormat; +} + +int Codec_OSAL_DevOpen( + const char *sDevName, + int nFlag, + CodecOSALVideoContext *pCtx) +{ + if ((sDevName != NULL) && + (pCtx != NULL)) { + pCtx->videoCtx.hDevice = exynos_v4l2_open_devname(sDevName, nFlag, 0); + return pCtx->videoCtx.hDevice; + } + + return -1; +} + +void Codec_OSAL_DevClose(CodecOSALVideoContext *pCtx) +{ + if ((pCtx != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + exynos_v4l2_close(pCtx->videoCtx.hDevice); + } + + return; +} + +int Codec_OSAL_QueryCap(CodecOSALVideoContext *pCtx) +{ + int needCaps = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING); + + if ((pCtx != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + if (exynos_v4l2_querycap(pCtx->videoCtx.hDevice, needCaps)) + return 0; + } + + return -1; +} + +int Codec_OSAL_EnqueueBuf( + CodecOSALVideoContext *pCtx, + CodecOSAL_Buffer *pBuf) +{ + if ((pCtx != NULL) && + (pBuf != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + struct v4l2_buffer buf; + struct v4l2_plane planes[VIDEO_BUFFER_MAX_PLANES]; + int i; + unsigned int nCID; + + memset(&buf, 0, sizeof(buf)); + memset(&planes, 0, sizeof(planes)); + + buf.type = pBuf->type; + buf.m.planes = planes; + buf.length = pBuf->nPlane; + buf.memory = pBuf->memory; + buf.index = pBuf->index; + + if (pCtx->videoCtx.bShareInbuf == VIDEO_TRUE) { + for (i = 0; i < pBuf->nPlane; i++) { + if ((unsigned int)buf.memory == (unsigned int)CODEC_OSAL_MEM_TYPE_USERPTR) + buf.m.planes[i].m.userptr = (unsigned long)pBuf->planes[i].addr; + else + buf.m.planes[i].m.fd = (int)(unsigned long)pBuf->planes[i].addr; + + buf.m.planes[i].length = pBuf->planes[i].bufferSize; + buf.m.planes[i].bytesused = pBuf->planes[i].dataLen; + buf.m.planes[i].data_offset = 0; + } + } else { + for (i = 0; i < pBuf->nPlane; i++) { + buf.m.planes[i].bytesused = pBuf->planes[i].dataLen; + buf.m.planes[i].data_offset = 0; + } + } +#ifdef USE_ORIGINAL_HEADER + if (pCtx->videoCtx.bVideoBufFlagCtrl == VIDEO_TRUE) { + nCID = (buf.type == CODEC_OSAL_BUF_TYPE_SRC)? CODEC_OSAL_CID_VIDEO_SRC_BUF_FLAG:CODEC_OSAL_CID_VIDEO_DST_BUF_FLAG; + Codec_OSAL_SetControl(pCtx, nCID, pBuf->flags); + } else { + buf.reserved2 = pBuf->flags; + } +#else + buf.input = pBuf->flags; +#endif + memcpy(&(buf.timestamp), &(pBuf->timestamp), sizeof(struct timeval)); + + return exynos_v4l2_qbuf(pCtx->videoCtx.hDevice, &buf); + } + + return -1; +} + +int Codec_OSAL_DequeueBuf( + CodecOSALVideoContext *pCtx, + CodecOSAL_Buffer *pBuf) +{ + if ((pCtx != NULL) && + (pBuf != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + struct v4l2_buffer buf; + struct v4l2_plane planes[VIDEO_BUFFER_MAX_PLANES]; + int i; + unsigned int nCID; + + memset(&buf, 0, sizeof(buf)); + memset(&planes, 0, sizeof(planes)); + + buf.type = pBuf->type; + buf.m.planes = planes; + buf.length = pBuf->nPlane; + buf.memory = pBuf->memory; + + if (exynos_v4l2_dqbuf(pCtx->videoCtx.hDevice, &buf) == 0) { + pBuf->index = buf.index; +#ifdef USE_ORIGINAL_HEADER + if (pCtx->videoCtx.bVideoBufFlagCtrl == VIDEO_TRUE) { + nCID = (buf.type == CODEC_OSAL_BUF_TYPE_SRC)? CODEC_OSAL_CID_VIDEO_SRC_BUF_FLAG:CODEC_OSAL_CID_VIDEO_DST_BUF_FLAG; + Codec_OSAL_GetControl(pCtx, nCID, (int*)&pBuf->flags); + } else { + pBuf->flags = buf.reserved2; + } +#else + pBuf->flags = buf.input; +#endif + pBuf->field = buf.field; + pBuf->timestamp = buf.timestamp; + + for (i = 0; i < pBuf->nPlane; i++) + pBuf->planes[i].dataLen = buf.m.planes[i].bytesused; + + switch (buf.flags & (0x7 << 3)) { + case V4L2_BUF_FLAG_KEYFRAME: + pBuf->frameType = VIDEO_FRAME_I; + break; + case V4L2_BUF_FLAG_PFRAME: + pBuf->frameType = VIDEO_FRAME_P; + break; + case V4L2_BUF_FLAG_BFRAME: + pBuf->frameType = VIDEO_FRAME_B; + break; + default: + pBuf->frameType = VIDEO_FRAME_OTHERS; + break; + }; + + if (buf.flags & V4L2_BUF_FLAG_ERROR) + pBuf->frameType |= VIDEO_FRAME_CORRUPT; + + return 0; + } + } + + return -1; +} + +int Codec_OSAL_GetControls( + CodecOSALVideoContext *pCtx, + unsigned int nCID, + void *pInfo) +{ + int ret = -1; + + if ((pCtx != NULL) && + (pInfo != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + ret = 0; + + switch (nCID) { + case CODEC_OSAL_CID_DEC_SEI_INFO: + { + ExynosVideoFramePacking *pFramePacking = (ExynosVideoFramePacking *)pInfo; + + struct v4l2_ext_control ext_ctrl[FRAME_PACK_SEI_INFO_NUM]; + struct v4l2_ext_controls ext_ctrls; + + int seiAvailable, seiInfo, seiGridPos, i; + unsigned int seiArgmtId; + + memset(pFramePacking, 0, sizeof(*pFramePacking)); + memset(ext_ctrl, 0, sizeof(ext_ctrl)); + + ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + ext_ctrls.count = FRAME_PACK_SEI_INFO_NUM; + ext_ctrls.controls = ext_ctrl; + ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_AVAIL; + ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRGMENT_ID; + ext_ctrl[2].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_INFO; + ext_ctrl[3].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_GRID_POS; + + if (exynos_v4l2_g_ext_ctrl(pCtx->videoCtx.hDevice, &ext_ctrls) != 0) { + ret = -1; + goto EXIT; + } + + seiAvailable = ext_ctrl[0].value; + seiArgmtId = ext_ctrl[1].value; + seiInfo = ext_ctrl[2].value; + seiGridPos = ext_ctrl[3].value; + + pFramePacking->available = seiAvailable; + pFramePacking->arrangement_id = seiArgmtId; + + pFramePacking->arrangement_cancel_flag = OPERATE_BIT(seiInfo, 0x1, 0); + pFramePacking->arrangement_type = OPERATE_BIT(seiInfo, 0x3f, 1); + pFramePacking->quincunx_sampling_flag = OPERATE_BIT(seiInfo, 0x1, 8); + pFramePacking->content_interpretation_type = OPERATE_BIT(seiInfo, 0x3f, 9); + pFramePacking->spatial_flipping_flag = OPERATE_BIT(seiInfo, 0x1, 15); + pFramePacking->frame0_flipped_flag = OPERATE_BIT(seiInfo, 0x1, 16); + pFramePacking->field_views_flag = OPERATE_BIT(seiInfo, 0x1, 17); + pFramePacking->current_frame_is_frame0_flag = OPERATE_BIT(seiInfo, 0x1, 18); + + pFramePacking->frame0_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 0); + pFramePacking->frame0_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 4); + pFramePacking->frame1_grid_pos_x = OPERATE_BIT(seiGridPos, 0xf, 8); + pFramePacking->frame1_grid_pos_y = OPERATE_BIT(seiGridPos, 0xf, 12); + } + break; + case CODEC_OSAL_CID_DEC_HDR_INFO: + { + ExynosVideoHdrInfo *pHdrInfo = (ExynosVideoHdrInfo *)pInfo; + + struct v4l2_ext_control ext_ctrl[HDR_INFO_NUM]; + struct v4l2_ext_controls ext_ctrls; + + int infoType = pHdrInfo->eValidType; + int i = 0; + + memset(ext_ctrl, 0, (sizeof(struct v4l2_ext_control) * HDR_INFO_NUM)); + ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + ext_ctrls.controls = ext_ctrl; + + if (infoType & HDR_INFO_LIGHT) { + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT; + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT; + i += 2; + } + + if (infoType & HDR_INFO_LUMINANCE) { + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE; + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE; + ext_ctrl[i + 2].id = V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT; + ext_ctrl[i + 3].id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0; + ext_ctrl[i + 4].id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1; + ext_ctrl[i + 5].id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2; + i += 6; + } + + if (infoType & HDR_INFO_COLOR_ASPECTS) { + if (pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_VP9) { + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES; + i++; + } else { + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS; + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES; + ext_ctrl[i + 2].id = V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS; + i += 3; + } + } else if (infoType & HDR_INFO_MATRIX_COEFF_ONLY) { + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS; + i++; + } + + if (infoType & HDR_INFO_RANGE) { + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG; + i++; + } + + ext_ctrls.count = i; + + if (exynos_v4l2_g_ext_ctrl(pCtx->videoCtx.hDevice, &ext_ctrls) != 0) { + ret = VIDEO_ERROR_APIFAIL; + goto EXIT; + } + + i = 0; + pHdrInfo->eChangedType = HDR_INFO_NO_CHANGES | (pHdrInfo->eChangedType & HDR_INFO_DYNAMIC_META); + /* eType will be set when value is changed */ + if (infoType & HDR_INFO_LIGHT) { + if ((pHdrInfo->sHdrStatic.max_pic_average_light != ext_ctrl[i].value) || + (pHdrInfo->sHdrStatic.max_content_light != ext_ctrl[i + 1].value)) { + pHdrInfo->eChangedType |= HDR_INFO_LIGHT; + } + + pHdrInfo->sHdrStatic.max_pic_average_light = ext_ctrl[i].value; + pHdrInfo->sHdrStatic.max_content_light = ext_ctrl[i + 1].value; + i += 2; + } + + if (infoType & HDR_INFO_LUMINANCE) { + if ((pHdrInfo->sHdrStatic.max_display_luminance != ext_ctrl[i].value) || + (pHdrInfo->sHdrStatic.min_display_luminance != ext_ctrl[i + 1].value) || + (pHdrInfo->sHdrStatic.white.x != GET_16BIT_HIGH(ext_ctrl[i + 2].value)) || + (pHdrInfo->sHdrStatic.white.y != GET_16BIT_LOW(ext_ctrl[i + 2].value)) || + (pHdrInfo->sHdrStatic.green.x != GET_16BIT_HIGH(ext_ctrl[i + 3].value)) || + (pHdrInfo->sHdrStatic.green.y != GET_16BIT_LOW(ext_ctrl[i + 3].value)) || + (pHdrInfo->sHdrStatic.blue.x != GET_16BIT_HIGH(ext_ctrl[i + 4].value)) || + (pHdrInfo->sHdrStatic.blue.y != GET_16BIT_LOW(ext_ctrl[i + 4].value)) || + (pHdrInfo->sHdrStatic.red.x != GET_16BIT_HIGH(ext_ctrl[i + 5].value)) || + (pHdrInfo->sHdrStatic.red.y != GET_16BIT_LOW(ext_ctrl[i + 5].value))) { + pHdrInfo->eChangedType |= HDR_INFO_LUMINANCE; + } + + pHdrInfo->sHdrStatic.max_display_luminance = ext_ctrl[i].value; + pHdrInfo->sHdrStatic.min_display_luminance = ext_ctrl[i + 1].value; + pHdrInfo->sHdrStatic.white.x = GET_16BIT_HIGH(ext_ctrl[i + 2].value); /* [31:16] */ + pHdrInfo->sHdrStatic.white.y = GET_16BIT_LOW(ext_ctrl[i + 2].value); /* [15:0] */ + pHdrInfo->sHdrStatic.green.x = GET_16BIT_HIGH(ext_ctrl[i + 3].value); + pHdrInfo->sHdrStatic.green.y = GET_16BIT_LOW(ext_ctrl[i + 3].value); + pHdrInfo->sHdrStatic.blue.x = GET_16BIT_HIGH(ext_ctrl[i + 4].value); + pHdrInfo->sHdrStatic.blue.y = GET_16BIT_LOW(ext_ctrl[i + 4].value); + pHdrInfo->sHdrStatic.red.x = GET_16BIT_HIGH(ext_ctrl[i + 5].value); + pHdrInfo->sHdrStatic.red.y = GET_16BIT_LOW(ext_ctrl[i + 5].value); + i += 6; + } + + if (infoType & HDR_INFO_COLOR_ASPECTS) { + if (pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_VP9) { + if (((int)pHdrInfo->sColorAspects.eCoeffType != ColorSpaceToColorAspects[ext_ctrl[i].value].coeff) || + ((int)pHdrInfo->sColorAspects.ePrimariesType != ColorSpaceToColorAspects[ext_ctrl[i].value].primaries) || + ((int)pHdrInfo->sColorAspects.eTransferType != ColorSpaceToColorAspects[ext_ctrl[i].value].transfer)) { + pHdrInfo->eChangedType |= HDR_INFO_COLOR_ASPECTS; + } + + pHdrInfo->sColorAspects.eCoeffType = (ExynosMatrixCoeffType)ColorSpaceToColorAspects[ext_ctrl[i].value].coeff; + pHdrInfo->sColorAspects.ePrimariesType = (ExynosPrimariesType)ColorSpaceToColorAspects[ext_ctrl[i].value].primaries; + pHdrInfo->sColorAspects.eTransferType = (ExynosTransferType)ColorSpaceToColorAspects[ext_ctrl[i].value].transfer; + i++; + } else { + if (((int)pHdrInfo->sColorAspects.eCoeffType != ext_ctrl[i].value) || + ((int)pHdrInfo->sColorAspects.ePrimariesType != ext_ctrl[i + 1].value) || + ((int)pHdrInfo->sColorAspects.eTransferType != ext_ctrl[i + 2].value)) { + pHdrInfo->eChangedType |= HDR_INFO_COLOR_ASPECTS; + } + + pHdrInfo->sColorAspects.eCoeffType = (ExynosMatrixCoeffType)ext_ctrl[i].value; + pHdrInfo->sColorAspects.ePrimariesType = (ExynosPrimariesType)ext_ctrl[i + 1].value; + pHdrInfo->sColorAspects.eTransferType = (ExynosTransferType)ext_ctrl[i + 2].value; + i += 3; + } + } else if (infoType & HDR_INFO_MATRIX_COEFF_ONLY) { + if ((int)pHdrInfo->sColorAspects.eCoeffType != ext_ctrl[i].value) { + pHdrInfo->eChangedType |= HDR_INFO_MATRIX_COEFF_ONLY; + } + + pHdrInfo->sColorAspects.eCoeffType = (ExynosMatrixCoeffType)ext_ctrl[i].value; + i++; + } + + if (infoType & HDR_INFO_RANGE) { + ExynosRangeType eRangeType = RANGE_UNSPECIFIED; + + eRangeType = (ExynosRangeType)((ext_ctrl[i].value == 0)? RANGE_LIMITED:RANGE_FULL); + + if (pHdrInfo->sColorAspects.eRangeType != eRangeType) { + pHdrInfo->eChangedType |= HDR_INFO_RANGE; + } + + pHdrInfo->sColorAspects.eRangeType = eRangeType; + i++; + } + } + break; + default: + { + ALOGE("%s: unsupported type(%x)", __FUNCTION__, nCID); + ret = -1; + } + break; + } + } + +EXIT: + return ret; +} + +int Codec_OSAL_SetControls( + CodecOSALVideoContext *pCtx, + unsigned int nCID, + void *pInfo) +{ + int ret = -1; + + if ((pCtx != NULL) && + (pInfo != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + ret = 0; + + switch (nCID) { + case CODEC_OSAL_CID_ENC_SET_PARAMS: + { + ExynosVideoEncParam *pEncParam = (ExynosVideoEncParam *)pInfo; + ExynosVideoEncInitParam *pInitParam = &pEncParam->initParam; + ExynosVideoEncCommonParam *pCommonParam = &pEncParam->commonParam; + + int i; + struct v4l2_ext_control ext_ctrl[MAX_CTRL_NUM]; + struct v4l2_ext_controls ext_ctrls; + + /* common parameters */ + ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE; + ext_ctrl[0].value = (pCommonParam->IDRPeriod < 0)? 0:pCommonParam->IDRPeriod; + ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE; + + if ((pCtx->videoCtx.instInfo.supportInfo.enc.bFixedSliceSupport == VIDEO_TRUE) && + (pCommonParam->bFixedSlice == VIDEO_TRUE) && + (pCommonParam->SliceMode != 0)) { + ext_ctrl[1].value = 4; /* fixed bytes */ + } else { + ext_ctrl[1].value = pCommonParam->SliceMode; /* 0: one, 1: fixed #mb, 2: fixed #bytes */ + } + ext_ctrl[2].id = V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB; + ext_ctrl[2].value = pCommonParam->RandomIntraMBRefresh; + ext_ctrl[3].id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING; + ext_ctrl[3].value = pCommonParam->PadControlOn; + ext_ctrl[4].id = V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV; + ext_ctrl[4].value = pCommonParam->CrPadVal; + ext_ctrl[4].value |= (pCommonParam->CbPadVal << 8); + ext_ctrl[4].value |= (pCommonParam->LumaPadVal << 16); + ext_ctrl[5].id = V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE; + ext_ctrl[5].value = pCommonParam->EnableFRMRateControl; + ext_ctrl[6].id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE; + ext_ctrl[6].value = pCommonParam->EnableMBRateControl; + ext_ctrl[7].id = V4L2_CID_MPEG_VIDEO_BITRATE; + + /* FIXME temporary fix */ + if (pCommonParam->Bitrate) + ext_ctrl[7].value = pCommonParam->Bitrate; + else + ext_ctrl[7].value = 1; /* just for testing Movie studio */ + + /* codec specific parameters */ + switch (pEncParam->eCompressionFormat) { + case VIDEO_CODING_AVC: + { + ExynosVideoEncH264Param *pH264Param = &pEncParam->codecParam.h264; + + /* common parameters but id is depends on codec */ + ext_ctrl[8].id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP; + ext_ctrl[8].value = pCommonParam->FrameQp; + ext_ctrl[9].id = V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP; + ext_ctrl[9].value = pCommonParam->FrameQp_P; + ext_ctrl[10].id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP; /* QP range : I frame */ + ext_ctrl[10].value = GET_H264_QP_VALUE(pCommonParam->QpRange.QpMax_I); + ext_ctrl[11].id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP; + ext_ctrl[11].value = GET_H264_QP_VALUE(pCommonParam->QpRange.QpMin_I); + ext_ctrl[12].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF; + ext_ctrl[12].value = pCommonParam->CBRPeriodRf; + + /* H.264 specific parameters */ + switch (pCommonParam->SliceMode) { + case 0: + ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB; + ext_ctrl[13].value = 1; /* default */ + ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES; + ext_ctrl[14].value = 2800; /* based on MFC6.x */ + break; + case 1: + ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB; + ext_ctrl[13].value = pH264Param->SliceArgument; + ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES; + ext_ctrl[14].value = 2800; /* based on MFC6.x */ + break; + case 2: + ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB; + ext_ctrl[13].value = 1; /* default */ + ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES; + ext_ctrl[14].value = pH264Param->SliceArgument; + break; + default: + break; + } + + ext_ctrl[15].id = V4L2_CID_MPEG_VIDEO_H264_PROFILE; + ext_ctrl[15].value = pH264Param->ProfileIDC; + ext_ctrl[16].id = V4L2_CID_MPEG_VIDEO_H264_LEVEL; + ext_ctrl[16].value = pH264Param->LevelIDC; + ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P; + ext_ctrl[17].value = pH264Param->NumberRefForPframes; + /* + * It should be set using h264Param->NumberBFrames after being handled by appl. + */ + ext_ctrl[18].id = V4L2_CID_MPEG_VIDEO_B_FRAMES; + ext_ctrl[18].value = pH264Param->NumberBFrames; + ext_ctrl[19].id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE; + ext_ctrl[19].value = pH264Param->LoopFilterDisable; + ext_ctrl[20].id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA; + ext_ctrl[20].value = pH264Param->LoopFilterAlphaC0Offset; + ext_ctrl[21].id = V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA; + ext_ctrl[21].value = pH264Param->LoopFilterBetaOffset; + ext_ctrl[22].id = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE; + ext_ctrl[22].value = pH264Param->SymbolMode; + ext_ctrl[23].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_INTERLACE; + ext_ctrl[23].value = pH264Param->PictureInterlace; + ext_ctrl[24].id = V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM; + ext_ctrl[24].value = pH264Param->Transform8x8Mode; + ext_ctrl[25].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_RC_FRAME_RATE; + ext_ctrl[25].value = pH264Param->FrameRate; + ext_ctrl[26].id = V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP; + ext_ctrl[26].value = pH264Param->FrameQp_B; + ext_ctrl[27].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK; + ext_ctrl[27].value = pH264Param->DarkDisable; + ext_ctrl[28].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH; + ext_ctrl[28].value = pH264Param->SmoothDisable; + ext_ctrl[29].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC; + ext_ctrl[29].value = pH264Param->StaticDisable; + ext_ctrl[30].id = V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY; + ext_ctrl[30].value = pH264Param->ActivityDisable; + + /* doesn't have to be set */ + ext_ctrl[31].id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE; + ext_ctrl[31].value = 1; + ext_ctrl[32].id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD; + ext_ctrl[32].value = 0; + ext_ctrl[33].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE; + ext_ctrl[33].value = 0; + ext_ctrl[34].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE; + + if (pH264Param->HeaderWithIFrame == 0) { + /* default */ + ext_ctrl[34].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE; /* 0: seperated header */ + } else { + ext_ctrl[34].value = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME; /* 1: header + first frame */ + } + ext_ctrl[35].id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE; + ext_ctrl[35].value = pH264Param->SarEnable; + ext_ctrl[36].id = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC; + ext_ctrl[36].value = pH264Param->SarIndex; + ext_ctrl[37].id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH; + ext_ctrl[37].value = pH264Param->SarWidth; + ext_ctrl[38].id = V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT; + ext_ctrl[38].value = pH264Param->SarHeight; + + /* Initial parameters : Frame Skip */ + switch (pInitParam->FrameSkip) { + case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT: + ext_ctrl[39].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[39].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT; + break; + case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT: + ext_ctrl[39].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[39].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT; + break; + default: + /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */ + ext_ctrl[39].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[39].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED; + break; + } + + /* SVC is not supported yet */ + ext_ctrl[40].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING; + ext_ctrl[40].value = 0; + switch (pH264Param->HierarType) { + case 1: + ext_ctrl[41].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE; + ext_ctrl[41].value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B; + break; + case 0: + default: + ext_ctrl[41].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_TYPE; + ext_ctrl[41].value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P; + break; + } + ext_ctrl[42].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER; + ext_ctrl[42].value = pH264Param->TemporalSVC.nTemporalLayerCount; + ext_ctrl[43].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP; + ext_ctrl[43].value = ((unsigned int)0 << 16 | 29); + ext_ctrl[44].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP; + ext_ctrl[44].value = ((unsigned int)1 << 16 | 29); + ext_ctrl[45].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_QP; + ext_ctrl[45].value = ((unsigned int)2 << 16 | 29); + + ext_ctrl[46].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING; + ext_ctrl[46].value = 0; + ext_ctrl[47].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_CURRENT_FRAME_0; + ext_ctrl[47].value = 0; + ext_ctrl[48].id = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE; + ext_ctrl[48].value = V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_SIDE_BY_SIDE; + + /* FMO is not supported yet */ + ext_ctrl[49].id = V4L2_CID_MPEG_VIDEO_H264_FMO; + ext_ctrl[49].value = 0; + ext_ctrl[50].id = V4L2_CID_MPEG_VIDEO_H264_FMO_MAP_TYPE; + ext_ctrl[50].value = V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES; + ext_ctrl[51].id = V4L2_CID_MPEG_VIDEO_H264_FMO_SLICE_GROUP; + ext_ctrl[51].value = 4; + ext_ctrl[52].id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH; + ext_ctrl[52].value = ((unsigned int)0 << 30 | 0); + ext_ctrl[53].id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH; + ext_ctrl[53].value = ((unsigned int)1 << 30 | 0); + ext_ctrl[54].id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH; + ext_ctrl[54].value = ((unsigned int)2 << 30 | 0); + ext_ctrl[55].id = V4L2_CID_MPEG_VIDEO_H264_FMO_RUN_LENGTH; + ext_ctrl[55].value = ((unsigned int)3 << 30 | 0); + ext_ctrl[56].id = V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_DIRECTION; + ext_ctrl[56].value = V4L2_MPEG_VIDEO_H264_FMO_CHANGE_DIR_RIGHT; + ext_ctrl[57].id = V4L2_CID_MPEG_VIDEO_H264_FMO_CHANGE_RATE; + ext_ctrl[57].value = 0; + + /* ASO is not supported yet */ + ext_ctrl[58].id = V4L2_CID_MPEG_VIDEO_H264_ASO; + ext_ctrl[58].value = 0; + for (i = 0; i < 32; i++) { + ext_ctrl[59 + i].id = V4L2_CID_MPEG_VIDEO_H264_ASO_SLICE_ORDER; + ext_ctrl[59 + i].value = ((unsigned int)i << 16 | 0); + } + + /* VUI RESRICTION ENABLE */ + ext_ctrl[91].id = V4L2_CID_MPEG_MFC_H264_VUI_RESTRICTION_ENABLE; + ext_ctrl[91].value = pH264Param->VuiRestrictionEnable; + + ext_ctrls.count = H264_CTRL_NUM; + if (pCtx->videoCtx.instInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT0; + ext_ctrl[i].value = pH264Param->TemporalSVC.nTemporalLayerBitrateRatio[0]; + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT1; + ext_ctrl[i + 1].value = pH264Param->TemporalSVC.nTemporalLayerBitrateRatio[1]; + ext_ctrl[i + 2].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT2; + ext_ctrl[i + 2].value = pH264Param->TemporalSVC.nTemporalLayerBitrateRatio[2]; + ext_ctrl[i + 3].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT3; + ext_ctrl[i + 3].value = pH264Param->TemporalSVC.nTemporalLayerBitrateRatio[3]; + ext_ctrl[i + 4].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT4; + ext_ctrl[i + 4].value = pH264Param->TemporalSVC.nTemporalLayerBitrateRatio[4]; + ext_ctrl[i + 5].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT5; + ext_ctrl[i + 5].value = pH264Param->TemporalSVC.nTemporalLayerBitrateRatio[5]; + ext_ctrl[i + 6].id = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_BIT6; + ext_ctrl[i + 6].value = pH264Param->TemporalSVC.nTemporalLayerBitrateRatio[6]; + ext_ctrls.count += 7; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bSkypeSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + /* H264 LTR FRAMES (0: disable, LTRFrames > 0: enable) */ + ext_ctrl[i].id = V4L2_CID_MPEG_MFC_H264_NUM_OF_LTR; + ext_ctrl[i].value = pH264Param->LTRFrames; + + /* FRAME LEVEL QP ENABLE */ + ext_ctrl[i + 1].id = V4L2_CID_MPEG_MFC_CONFIG_QP_ENABLE; + ext_ctrl[i + 1].value = pCommonParam->EnableFRMQpControl; + + /* CONFIG QP VALUE */ + ext_ctrl[i + 2].id = V4L2_CID_MPEG_MFC_CONFIG_QP; + ext_ctrl[i + 2].value = pCommonParam->FrameQp; + + /* MAX LAYER COUNT for SHORT TERM */ + ext_ctrl[i + 3].id = V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER; + ext_ctrl[i + 3].value = pH264Param->MaxTemporalLayerCount; + + ext_ctrls.count += 4; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bRoiInfoSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_ROI_ENABLE; + ext_ctrl[i].value = pH264Param->ROIEnable; + + ext_ctrls.count += 1; + } + + /* optional : if these are not set, set value are same as I frame */ + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P; /* P frame */ + ext_ctrl[i].value = GET_H264_QP_VALUE(pCommonParam->QpRange.QpMin_P); + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P; + ext_ctrl[i + 1].value = GET_H264_QP_VALUE(pCommonParam->QpRange.QpMax_P); + ext_ctrl[i + 2].id = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B; /* B frame */ + ext_ctrl[i + 2].value = GET_H264_QP_VALUE(pCommonParam->QpRange.QpMin_B); + ext_ctrl[i + 3].id = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B; + ext_ctrl[i + 3].value = GET_H264_QP_VALUE(pCommonParam->QpRange.QpMax_B); + + ext_ctrls.count += 4; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bPVCSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_RC_PVC_ENABLE; + ext_ctrl[i].value = pCommonParam->PerceptualMode; + + ext_ctrls.count += 1; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bChromaQpSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_CHROMA_QP_OFFSET_CB; + ext_ctrl[i].value = pH264Param->chromaQPOffset.Cb; + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_CHROMA_QP_OFFSET_CR; + ext_ctrl[i + 1].value = pH264Param->chromaQPOffset.Cr; + + ext_ctrls.count +=2; + } + } + break; + case VIDEO_CODING_MPEG4: + { + ExynosVideoEncMpeg4Param *pMpeg4Param = &pEncParam->codecParam.mpeg4; + + /* common parameters but id is depends on codec */ + ext_ctrl[8].id = V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP; + ext_ctrl[8].value = pCommonParam->FrameQp; + ext_ctrl[9].id = V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP; + ext_ctrl[9].value = pCommonParam->FrameQp_P; + ext_ctrl[10].id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP; /* I frame */ + ext_ctrl[10].value = GET_MPEG4_QP_VALUE(pCommonParam->QpRange.QpMax_I); + ext_ctrl[11].id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP; + ext_ctrl[11].value = GET_MPEG4_QP_VALUE(pCommonParam->QpRange.QpMin_I); + ext_ctrl[12].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF; + ext_ctrl[12].value = pCommonParam->CBRPeriodRf; + + /* MPEG4 specific parameters */ + switch (pCommonParam->SliceMode) { + case 0: + ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB; + ext_ctrl[13].value = 1; /* default */ + ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES; + ext_ctrl[14].value = 2800; /* based on MFC6.x */ + break; + case 1: + ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB; + ext_ctrl[13].value = pMpeg4Param->SliceArgument; + ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES; + ext_ctrl[14].value = 2800; /* based on MFC6.x */ + break; + case 2: + ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB; + ext_ctrl[13].value = 1; /* default */ + ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES; + ext_ctrl[14].value = pMpeg4Param->SliceArgument; + break; + default: + break; + } + + ext_ctrl[15].id = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE; + ext_ctrl[15].value = pMpeg4Param->ProfileIDC; + ext_ctrl[16].id = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL; + ext_ctrl[16].value = pMpeg4Param->LevelIDC; + ext_ctrl[17].id = V4L2_CID_MPEG_VIDEO_MPEG4_QPEL; + ext_ctrl[17].value = pMpeg4Param->DisableQpelME; + + /* + * It should be set using mpeg4Param->NumberBFrames after being handled by appl. + */ + ext_ctrl[18].id = V4L2_CID_MPEG_VIDEO_B_FRAMES; + ext_ctrl[18].value = pMpeg4Param->NumberBFrames; + + ext_ctrl[19].id = V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_TIME_RES; + ext_ctrl[19].value = pMpeg4Param->TimeIncreamentRes; + ext_ctrl[20].id = V4L2_CID_MPEG_MFC51_VIDEO_MPEG4_VOP_FRM_DELTA; + ext_ctrl[20].value = pMpeg4Param->VopTimeIncreament; + ext_ctrl[21].id = V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP; + ext_ctrl[21].value = pMpeg4Param->FrameQp_B; + ext_ctrl[22].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE; + ext_ctrl[22].value = 0; + ext_ctrl[23].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE; + ext_ctrl[23].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE; + ext_ctrl[24].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT; + ext_ctrl[24].value = 1; + + /* Initial parameters : Frame Skip */ + switch (pInitParam->FrameSkip) { + case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT: + ext_ctrl[25].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[25].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT; + break; + case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT: + ext_ctrl[25].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[25].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT; + break; + default: + /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */ + ext_ctrl[25].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[25].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED; + break; + } + ext_ctrls.count = MPEG4_CTRL_NUM; + + /* optional : if these are not set, set value are same as I frame */ + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P; /* P frame */ + ext_ctrl[i].value = GET_MPEG4_QP_VALUE(pCommonParam->QpRange.QpMin_P); + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P; + ext_ctrl[i + 1].value = GET_MPEG4_QP_VALUE(pCommonParam->QpRange.QpMax_P); + ext_ctrl[i + 2].id = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B; /* B frame */ + ext_ctrl[i + 2].value = GET_MPEG4_QP_VALUE(pCommonParam->QpRange.QpMin_B); + ext_ctrl[i + 3].id = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B; + ext_ctrl[i + 3].value = GET_MPEG4_QP_VALUE(pCommonParam->QpRange.QpMax_B); + + ext_ctrls.count += 4; + } + } + break; + case VIDEO_CODING_H263: + { + ExynosVideoEncH263Param *pH263Param = &pEncParam->codecParam.h263; + + /* common parameters but id is depends on codec */ + ext_ctrl[8].id = V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP; + ext_ctrl[8].value = pCommonParam->FrameQp; + ext_ctrl[9].id = V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP; + ext_ctrl[9].value = pCommonParam->FrameQp_P; + ext_ctrl[10].id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP; /* I frame */ + ext_ctrl[10].value = GET_H263_QP_VALUE(pCommonParam->QpRange.QpMax_I); + ext_ctrl[11].id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP; + ext_ctrl[11].value = GET_H263_QP_VALUE(pCommonParam->QpRange.QpMin_I); + ext_ctrl[12].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF; + ext_ctrl[12].value = pCommonParam->CBRPeriodRf; + + /* H263 specific parameters */ + ext_ctrl[13].id = V4L2_CID_MPEG_MFC51_VIDEO_H263_RC_FRAME_RATE; + ext_ctrl[13].value = pH263Param->FrameRate; + ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE; + ext_ctrl[14].value = 0; + ext_ctrl[15].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE; + ext_ctrl[15].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE; + ext_ctrl[16].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT; + ext_ctrl[16].value = 1; + + /* Initial parameters : Frame Skip */ + switch (pInitParam->FrameSkip) { + case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT: + ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT; + break; + case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT: + ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT; + break; + default: + /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */ + ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED; + break; + } + ext_ctrls.count = H263_CTRL_NUM; + + /* optional : if these are not set, set value are same as I frame */ + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P; /* P frame */ + ext_ctrl[i].value = GET_H263_QP_VALUE(pCommonParam->QpRange.QpMin_P); + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P; + ext_ctrl[i + 1].value = GET_H263_QP_VALUE(pCommonParam->QpRange.QpMax_P); + + ext_ctrls.count += 2; + } + } + break; + case VIDEO_CODING_VP8: + { + ExynosVideoEncVp8Param *pVp8Param = &pEncParam->codecParam.vp8; + + /* common parameters but id is depends on codec */ + ext_ctrl[8].id = V4L2_CID_MPEG_VIDEO_VP8_I_FRAME_QP; + ext_ctrl[8].value = pCommonParam->FrameQp; + ext_ctrl[9].id = V4L2_CID_MPEG_VIDEO_VP8_P_FRAME_QP; + ext_ctrl[9].value = pCommonParam->FrameQp_P; + ext_ctrl[10].id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP; /* I frame */ + ext_ctrl[10].value = GET_VP8_QP_VALUE(pCommonParam->QpRange.QpMax_I); + ext_ctrl[11].id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP; + ext_ctrl[11].value = GET_VP8_QP_VALUE(pCommonParam->QpRange.QpMin_I); + ext_ctrl[12].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF; + ext_ctrl[12].value = pCommonParam->CBRPeriodRf; + + /* VP8 specific parameters */ + ext_ctrl[13].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_RC_FRAME_RATE; + ext_ctrl[13].value = pVp8Param->FrameRate; + ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE; + ext_ctrl[14].value = 0; + ext_ctrl[15].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE; + ext_ctrl[15].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE; + ext_ctrl[16].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT; + ext_ctrl[16].value = 1; + + /* Initial parameters : Frame Skip */ + switch (pInitParam->FrameSkip) { + case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT: + ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT; + break; + case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT: + ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT; + break; + default: + /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */ + ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED; + break; + } + + ext_ctrl[18].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_VERSION; + ext_ctrl[18].value = pVp8Param->Vp8Version; + + ext_ctrl[19].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_OF_PARTITIONS; + ext_ctrl[19].value = pVp8Param->Vp8NumberOfPartitions; + + ext_ctrl[20].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_LEVEL; + ext_ctrl[20].value = pVp8Param->Vp8FilterLevel; + + ext_ctrl[21].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_FILTER_SHARPNESS; + ext_ctrl[21].value = pVp8Param->Vp8FilterSharpness; + + ext_ctrl[22].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_GOLDEN_FRAMESEL; + ext_ctrl[22].value = pVp8Param->Vp8GoldenFrameSel; + + ext_ctrl[23].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_ENABLE; + ext_ctrl[23].value = 0; + + ext_ctrl[24].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER0; + ext_ctrl[24].value = ((unsigned int)0 << 16 | 37); + + ext_ctrl[25].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER1; + ext_ctrl[25].value = ((unsigned int)1 << 16 | 37); + + ext_ctrl[26].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_HIERARCHY_QP_LAYER2; + ext_ctrl[26].value = ((unsigned int)2 << 16 | 37); + + ext_ctrl[27].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_REF_NUMBER_FOR_PFRAMES; + ext_ctrl[27].value = pVp8Param->RefNumberForPFrame; + + ext_ctrl[28].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_DISABLE_INTRA_MD4X4; + ext_ctrl[28].value = pVp8Param->DisableIntraMd4x4; + + ext_ctrl[29].id = V4L2_CID_MPEG_MFC70_VIDEO_VP8_NUM_TEMPORAL_LAYER; + ext_ctrl[29].value = pVp8Param->TemporalSVC.nTemporalLayerCount; + ext_ctrls.count = VP8_CTRL_NUM; + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT0; + ext_ctrl[i].value = pVp8Param->TemporalSVC.nTemporalLayerBitrateRatio[0]; + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT1; + ext_ctrl[i + 1].value = pVp8Param->TemporalSVC.nTemporalLayerBitrateRatio[1]; + ext_ctrl[i + 2].id = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_BIT2; + ext_ctrl[i + 2].value = pVp8Param->TemporalSVC.nTemporalLayerBitrateRatio[2]; + + ext_ctrls.count += 3; + } + + /* optional : if these are not set, set value are same as I frame */ + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P; /* P frame */ + ext_ctrl[i].value = GET_VP8_QP_VALUE(pCommonParam->QpRange.QpMin_P); + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P; + ext_ctrl[i + 1].value = GET_VP8_QP_VALUE(pCommonParam->QpRange.QpMax_P); + + ext_ctrls.count += 2; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bPVCSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_RC_PVC_ENABLE; + ext_ctrl[i].value = pCommonParam->PerceptualMode; + + ext_ctrls.count += 1; + } + } + break; + case VIDEO_CODING_HEVC: + { + ExynosVideoEncHevcParam *pHevcParam = &pEncParam->codecParam.hevc; + + /* common parameters but id is depends on codec */ + ext_ctrl[8].id = V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP; + ext_ctrl[8].value = pCommonParam->FrameQp; + ext_ctrl[9].id = V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP; + ext_ctrl[9].value = pCommonParam->FrameQp_P; + ext_ctrl[10].id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP; /* I frame */ + ext_ctrl[10].value = GET_HEVC_QP_VALUE(pCommonParam->QpRange.QpMax_I, + pCtx->videoCtx.instInfo.HwVersion); + ext_ctrl[11].id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP; + ext_ctrl[11].value = GET_HEVC_QP_VALUE(pCommonParam->QpRange.QpMin_I, + pCtx->videoCtx.instInfo.HwVersion); + ext_ctrl[12].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF; + ext_ctrl[12].value = pCommonParam->CBRPeriodRf; + + /* HEVC specific parameters */ + ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_QP; + ext_ctrl[13].value = pHevcParam->FrameQp_B; + ext_ctrl[14].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_RC_FRAME_RATE; + ext_ctrl[14].value = pHevcParam->FrameRate; + + /* Initial parameters : Frame Skip */ + switch (pInitParam->FrameSkip) { + case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT: + ext_ctrl[15].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[15].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT; + break; + case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT: + ext_ctrl[15].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[15].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT; + break; + default: + /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */ + ext_ctrl[15].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[15].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED; + break; + } + + ext_ctrl[16].id = V4L2_CID_MPEG_VIDEO_HEVC_PROFILE; + ext_ctrl[16].value = pHevcParam->ProfileIDC; + + ext_ctrl[17].id = V4L2_CID_MPEG_VIDEO_HEVC_LEVEL; + ext_ctrl[17].value = pHevcParam->LevelIDC; + + ext_ctrl[18].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TIER_FLAG; + ext_ctrl[18].value = pHevcParam->TierIDC; + + ext_ctrl[19].id = V4L2_CID_MPEG_VIDEO_B_FRAMES; + ext_ctrl[19].value = pHevcParam->NumberBFrames; + + ext_ctrl[20].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_PARTITION_DEPTH; + ext_ctrl[20].value = pHevcParam->MaxPartitionDepth; + + ext_ctrl[21].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REF_NUMBER_FOR_PFRAMES; + ext_ctrl[21].value = pHevcParam->NumberRefForPframes; + + ext_ctrl[22].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_DISABLE; + ext_ctrl[22].value = pHevcParam->LoopFilterDisable; + + ext_ctrl[23].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_SLICE_BOUNDARY; + ext_ctrl[23].value = pHevcParam->LoopFilterSliceFlag; + + ext_ctrl[24].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_TC_OFFSET_DIV2; + ext_ctrl[24].value = pHevcParam->LoopFilterTcOffset; + + ext_ctrl[25].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LF_BETA_OFFSET_DIV2; + ext_ctrl[25].value = pHevcParam->LoopFilterBetaOffset; + + ext_ctrl[26].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LTR_ENABLE; + ext_ctrl[26].value = pHevcParam->LongtermRefEnable; + + ext_ctrl[27].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_USER_REF; + ext_ctrl[27].value = pHevcParam->LongtermUserRef; + + ext_ctrl[28].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STORE_REF; + ext_ctrl[28].value = pHevcParam->LongtermStoreRef; + + /* should be set V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE first */ + ext_ctrl[29].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_DARK; + ext_ctrl[29].value = pHevcParam->DarkDisable; + + ext_ctrl[30].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_SMOOTH; + ext_ctrl[30].value = pHevcParam->SmoothDisable; + + ext_ctrl[31].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_STATIC; + ext_ctrl[31].value = pHevcParam->StaticDisable; + + ext_ctrl[32].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_ADAPTIVE_RC_ACTIVITY; + ext_ctrl[32].value = pHevcParam->ActivityDisable; + + /* doesn't have to be set */ + ext_ctrl[33].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_TYPE; + ext_ctrl[33].value = 2; + ext_ctrl[34].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_REFRESH_PERIOD; + ext_ctrl[34].value = 0; + ext_ctrl[35].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_LOSSLESS_CU_ENABLE; + ext_ctrl[35].value = 0; + ext_ctrl[36].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_CONST_INTRA_PRED_ENABLE; + ext_ctrl[36].value = 0; + ext_ctrl[37].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_WAVEFRONT_ENABLE; + ext_ctrl[37].value = 0; + ext_ctrl[38].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_SIGN_DATA_HIDING; + ext_ctrl[38].value = 1; + ext_ctrl[39].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_GENERAL_PB_ENABLE; + ext_ctrl[39].value = pHevcParam->GPBEnable; + ext_ctrl[40].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_TEMPORAL_ID_ENABLE; + ext_ctrl[40].value = 1; + ext_ctrl[41].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_STRONG_SMOTHING_FLAG; + ext_ctrl[41].value = 1; + ext_ctrl[42].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1; + ext_ctrl[42].value = 4; + ext_ctrl[43].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_INTRA_PU_SPLIT; + ext_ctrl[43].value = 0; + ext_ctrl[44].id = V4L2_CID_MPEG_MFC90_VIDEO_HEVC_DISABLE_TMV_PREDICTION; + ext_ctrl[44].value = 0; + ext_ctrl[45].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE; + ext_ctrl[45].value = 0; + ext_ctrl[46].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE; + ext_ctrl[46].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE; + + /* SVC is not supported yet */ + ext_ctrl[47].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_QP_ENABLE; + ext_ctrl[47].value = 0; + switch (pHevcParam->HierarType) { + case 1: + ext_ctrl[48].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE; + ext_ctrl[48].value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_B; + break; + case 0: + default: + ext_ctrl[48].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_TYPE; + ext_ctrl[48].value = V4L2_MPEG_VIDEO_H264_HIERARCHICAL_CODING_P; + break; + } + ext_ctrl[49].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER; + ext_ctrl[49].value = pHevcParam->TemporalSVC.nTemporalLayerCount; + ext_ctrl[50].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP; + ext_ctrl[50].value = ((unsigned int)0 << 16 | 29); + ext_ctrl[51].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP; + ext_ctrl[51].value = ((unsigned int)1 << 16 | 29); + ext_ctrl[52].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_QP; + ext_ctrl[52].value = ((unsigned int)2 << 16 | 29); + ext_ctrls.count = HEVC_CTRL_NUM; + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT0; + ext_ctrl[i].value = pHevcParam->TemporalSVC.nTemporalLayerBitrateRatio[0]; + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT1; + ext_ctrl[i + 1].value = pHevcParam->TemporalSVC.nTemporalLayerBitrateRatio[1]; + ext_ctrl[i + 2].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT2; + ext_ctrl[i + 2].value = pHevcParam->TemporalSVC.nTemporalLayerBitrateRatio[2]; + ext_ctrl[i + 3].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT3; + ext_ctrl[i + 3].value = pHevcParam->TemporalSVC.nTemporalLayerBitrateRatio[3]; + ext_ctrl[i + 4].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT4; + ext_ctrl[i + 4].value = pHevcParam->TemporalSVC.nTemporalLayerBitrateRatio[4]; + ext_ctrl[i + 5].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT5; + ext_ctrl[i + 5].value = pHevcParam->TemporalSVC.nTemporalLayerBitrateRatio[5]; + ext_ctrl[i + 6].id = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_BIT6; + ext_ctrl[i + 6].value = pHevcParam->TemporalSVC.nTemporalLayerBitrateRatio[6]; + ext_ctrls.count += 7; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bSkypeSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + /* MAX LAYER COUNT */ + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_TEMPORAL_SHORTTERM_MAX_LAYER; + ext_ctrl[i].value = pHevcParam->MaxTemporalLayerCount; + + ext_ctrls.count += 1; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bRoiInfoSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_ROI_ENABLE; + ext_ctrl[i].value = pHevcParam->ROIEnable; + + ext_ctrls.count += 1; + } + + /* optional : if these are not set, set value are same as I frame */ + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P; /* P frame */ + ext_ctrl[i].value = GET_HEVC_QP_VALUE(pCommonParam->QpRange.QpMin_P, + pCtx->videoCtx.instInfo.HwVersion); + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P; + ext_ctrl[i + 1].value = GET_HEVC_QP_VALUE(pCommonParam->QpRange.QpMax_P, + pCtx->videoCtx.instInfo.HwVersion); + ext_ctrl[i + 2].id = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B; /* B frame */ + ext_ctrl[i + 2].value = GET_HEVC_QP_VALUE(pCommonParam->QpRange.QpMin_B, + pCtx->videoCtx.instInfo.HwVersion); + ext_ctrl[i + 3].id = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B; + ext_ctrl[i + 3].value = GET_HEVC_QP_VALUE(pCommonParam->QpRange.QpMax_B, + pCtx->videoCtx.instInfo.HwVersion); + + ext_ctrls.count += 4; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bPVCSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_RC_PVC_ENABLE; + ext_ctrl[i].value = pCommonParam->PerceptualMode; + + ext_ctrls.count += 1; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bChromaQpSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_CHROMA_QP_OFFSET_CB; + ext_ctrl[i].value = pHevcParam->chromaQPOffset.Cb; + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_CHROMA_QP_OFFSET_CR; + ext_ctrl[i + 1].value = pHevcParam->chromaQPOffset.Cr; + + ext_ctrls.count +=2; + } + } + break; + case VIDEO_CODING_VP9: + { + ExynosVideoEncVp9Param *pVp9Param = &pEncParam->codecParam.vp9; + + /* VP9 specific parameters */ + ext_ctrl[8].id = V4L2_CID_MPEG_VIDEO_VP9_I_FRAME_QP; + ext_ctrl[8].value = pCommonParam->FrameQp; + + ext_ctrl[9].id = V4L2_CID_MPEG_VIDEO_VP9_P_FRAME_QP; + ext_ctrl[9].value = pCommonParam->FrameQp_P; + + ext_ctrl[10].id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP; /* I frame */ + ext_ctrl[10].value = GET_VP9_QP_VALUE(pCommonParam->QpRange.QpMax_I); + + ext_ctrl[11].id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP; + ext_ctrl[11].value = GET_VP9_QP_VALUE(pCommonParam->QpRange.QpMin_I); + + ext_ctrl[12].id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF; + ext_ctrl[12].value = pCommonParam->CBRPeriodRf; + + ext_ctrl[13].id = V4L2_CID_MPEG_VIDEO_VP9_RC_FRAME_RATE; + ext_ctrl[13].value = pVp9Param->FrameRate; + + ext_ctrl[14].id = V4L2_CID_MPEG_VIDEO_VBV_SIZE; + ext_ctrl[14].value = 0; + + ext_ctrl[15].id = V4L2_CID_MPEG_VIDEO_HEADER_MODE; + ext_ctrl[15].value = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE; + + ext_ctrl[16].id = V4L2_CID_MPEG_VIDEO_VP9_DISABLE_INTRA_PU_SPLIT; + ext_ctrl[16].value = 0; + + /* Initial parameters : Frame Skip */ + switch (pInitParam->FrameSkip) { + case VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT: + ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT; + break; + case VIDEO_FRAME_SKIP_MODE_BUF_LIMIT: + ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT; + break; + default: + /* VIDEO_FRAME_SKIP_MODE_DISABLE (default) */ + ext_ctrl[17].id = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE; + ext_ctrl[17].value = V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED; + break; + } + + ext_ctrl[18].id = V4L2_CID_MPEG_VIDEO_VP9_VERSION; + ext_ctrl[18].value = pVp9Param->Vp9Profile; + + /* TODO */ + //ext_ctrl[18].id = V4L2_CID_MPEG_VIDEO_VP9_LEVEL; + //ext_ctrl[18].value = pVp9Param->Vp9Level; + + ext_ctrl[19].id = V4L2_CID_MPEG_VIDEO_VP9_MAX_PARTITION_DEPTH; + ext_ctrl[19].value = pVp9Param->MaxPartitionDepth; + + ext_ctrl[20].id = V4L2_CID_MPEG_VIDEO_VP9_GOLDEN_FRAMESEL; + ext_ctrl[20].value = pVp9Param->Vp9GoldenFrameSel; + + ext_ctrl[21].id = V4L2_CID_MPEG_VIDEO_VP9_GF_REFRESH_PERIOD; + ext_ctrl[21].value = pVp9Param->Vp9GFRefreshPeriod; + + ext_ctrl[22].id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHY_QP_ENABLE; + ext_ctrl[22].value = 0; + + ext_ctrl[23].id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_QP; + ext_ctrl[23].value = ((unsigned int)0 << 16 | 90); + + ext_ctrl[24].id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_QP; + ext_ctrl[24].value = ((unsigned int)1 << 16 | 90); + + ext_ctrl[25].id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_QP; + ext_ctrl[25].value = ((unsigned int)2 << 16 | 90); + + ext_ctrl[26].id = V4L2_CID_MPEG_VIDEO_VP9_REF_NUMBER_FOR_PFRAMES; + ext_ctrl[26].value = pVp9Param->RefNumberForPFrame; + + ext_ctrl[27].id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER; + ext_ctrl[27].value = pVp9Param->TemporalSVC.nTemporalLayerCount; + + ext_ctrl[28].id = V4L2_CID_MPEG_VIDEO_DISABLE_IVF_HEADER; + ext_ctrl[28].value = 1; + ext_ctrls.count = VP9_CTRL_NUM; + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bTemporalSvcSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT0; + ext_ctrl[i].value = pVp9Param->TemporalSVC.nTemporalLayerBitrateRatio[0]; + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT1; + ext_ctrl[i + 1].value = pVp9Param->TemporalSVC.nTemporalLayerBitrateRatio[1]; + ext_ctrl[i + 2].id = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_BIT2; + ext_ctrl[i + 2].value = pVp9Param->TemporalSVC.nTemporalLayerBitrateRatio[2]; + + ext_ctrls.count += 3; + } + + /* optional : if these are not set, set value are same as I frame */ + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P; /* P frame */ + ext_ctrl[i].value = GET_VP9_QP_VALUE(pCommonParam->QpRange.QpMin_P); + ext_ctrl[i + 1].id = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P; + ext_ctrl[i + 1].value = GET_VP9_QP_VALUE(pCommonParam->QpRange.QpMax_P); + + ext_ctrls.count += 2; + } + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bPVCSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_RC_PVC_ENABLE; + ext_ctrl[i].value = pCommonParam->PerceptualMode; + + ext_ctrls.count += 1; + } + } + break; + default: + { + ALOGE("[%s] Undefined codec type",__FUNCTION__); + ret = -1; + goto EXIT; + } + break; + } + + /* extra common parameters */ + if (pCtx->videoCtx.instInfo.supportInfo.enc.bDropControlSupport == VIDEO_TRUE) { + i = ext_ctrls.count; + ext_ctrl[i].id = V4L2_CID_MPEG_VIDEO_DROP_CONTROL; + ext_ctrl[i].value = pCommonParam->bDropControl; + + ext_ctrls.count += 1; + } + + ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + ext_ctrls.controls = ext_ctrl; + + if (exynos_v4l2_s_ext_ctrl(pCtx->videoCtx.hDevice, &ext_ctrls) != 0) { + ret = -1; + goto EXIT; + } + } + break; // CODEC_OSAL_CID_ENC_SET_PARAMS + case CODEC_OSAL_CID_ENC_QP_RANGE: + { + ExynosVideoQPRange *pQpRange = (ExynosVideoQPRange *)pInfo; + + int cids[3][2], values[3][2]; /* I, P, B : min & max */ + int i; + + memset(cids, 0, sizeof(cids)); + memset(values, 0, sizeof(values)); + + /* codec specific parameters */ + /* common parameters but id is depends on codec */ + switch (pCtx->videoCtx.instInfo.eCodecType) { + case VIDEO_CODING_AVC: + { + cids[0][0] = V4L2_CID_MPEG_VIDEO_H264_MIN_QP; + cids[0][1] = V4L2_CID_MPEG_VIDEO_H264_MAX_QP; + + values[0][0] = GET_H264_QP_VALUE(pQpRange->QpMin_I); + values[0][1] = GET_H264_QP_VALUE(pQpRange->QpMax_I); + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + if (pQpRange->QpMin_P > pQpRange->QpMax_P) { + ALOGE("%s: QP(P) range(%d, %d) is wrong", __FUNCTION__, pQpRange->QpMin_P, pQpRange->QpMax_P); + ret = -1; + goto EXIT; + } + + if (pQpRange->QpMin_B > pQpRange->QpMax_B) { + ALOGE("%s: QP(B) range(%d, %d) is wrong", __FUNCTION__, pQpRange->QpMin_B, pQpRange->QpMax_B); + ret = -1; + goto EXIT; + } + + cids[1][0] = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_P; + cids[1][1] = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_P; + cids[2][0] = V4L2_CID_MPEG_VIDEO_H264_MIN_QP_B; + cids[2][1] = V4L2_CID_MPEG_VIDEO_H264_MAX_QP_B; + + values[1][0] = GET_H264_QP_VALUE(pQpRange->QpMin_P); + values[1][1] = GET_H264_QP_VALUE(pQpRange->QpMax_P); + values[2][0] = GET_H264_QP_VALUE(pQpRange->QpMin_B); + values[2][1] = GET_H264_QP_VALUE(pQpRange->QpMax_B); + } + } + break; + case VIDEO_CODING_MPEG4: + { + cids[0][0] = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP; + cids[0][1] = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP; + + values[0][0] = GET_MPEG4_QP_VALUE(pQpRange->QpMin_I); + values[0][1] = GET_MPEG4_QP_VALUE(pQpRange->QpMax_I); + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + if (pQpRange->QpMin_P > pQpRange->QpMax_P) { + ALOGE("%s: QP(P) range(%d, %d) is wrong", __FUNCTION__, pQpRange->QpMin_P, pQpRange->QpMax_P); + ret = -1; + goto EXIT; + } + + if (pQpRange->QpMin_B > pQpRange->QpMax_B) { + ALOGE("%s: QP(B) range(%d, %d) is wrong", __FUNCTION__, pQpRange->QpMin_B, pQpRange->QpMax_B); + ret = -1; + goto EXIT; + } + + cids[1][0] = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_P; + cids[1][1] = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_P; + cids[2][0] = V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP_B; + cids[2][1] = V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP_B; + + values[1][0] = GET_MPEG4_QP_VALUE(pQpRange->QpMin_P); + values[1][1] = GET_MPEG4_QP_VALUE(pQpRange->QpMax_P); + values[2][0] = GET_MPEG4_QP_VALUE(pQpRange->QpMin_B); + values[2][1] = GET_MPEG4_QP_VALUE(pQpRange->QpMax_B); + } + } + break; + case VIDEO_CODING_H263: + { + cids[0][0] = V4L2_CID_MPEG_VIDEO_H263_MIN_QP; + cids[0][1] = V4L2_CID_MPEG_VIDEO_H263_MAX_QP; + + values[0][0] = GET_H263_QP_VALUE(pQpRange->QpMin_I); + values[0][1] = GET_H263_QP_VALUE(pQpRange->QpMax_I); + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + if (pQpRange->QpMin_P > pQpRange->QpMax_P) { + ALOGE("%s: QP(P) range(%d, %d) is wrong", __FUNCTION__, pQpRange->QpMin_P, pQpRange->QpMax_P); + ret = -1; + goto EXIT; + } + + cids[1][0] = V4L2_CID_MPEG_VIDEO_H263_MIN_QP_P; + cids[1][1] = V4L2_CID_MPEG_VIDEO_H263_MAX_QP_P; + + values[1][0] = GET_H263_QP_VALUE(pQpRange->QpMin_P); + values[1][1] = GET_H263_QP_VALUE(pQpRange->QpMax_P); + } + } + break; + case VIDEO_CODING_VP8: + { + cids[0][0] = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP; + cids[0][1] = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP; + + values[0][0] = GET_VP8_QP_VALUE(pQpRange->QpMin_I); + values[0][1] = GET_VP8_QP_VALUE(pQpRange->QpMax_I); + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + if (pQpRange->QpMin_P > pQpRange->QpMax_P) { + ALOGE("%s: QP(P) range(%d, %d) is wrong", __FUNCTION__, pQpRange->QpMin_P, pQpRange->QpMax_P); + ret = -1; + goto EXIT; + } + + cids[1][0] = V4L2_CID_MPEG_VIDEO_VP8_MIN_QP_P; + cids[1][1] = V4L2_CID_MPEG_VIDEO_VP8_MAX_QP_P; + + values[1][0] = GET_VP8_QP_VALUE(pQpRange->QpMin_P); + values[1][1] = GET_VP8_QP_VALUE(pQpRange->QpMax_P); + } + } + break; + case VIDEO_CODING_HEVC: + { + cids[0][0] = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP; + cids[0][1] = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP; + + values[0][0] = GET_HEVC_QP_VALUE(pQpRange->QpMin_I, + pCtx->videoCtx.instInfo.HwVersion); + values[0][1] = GET_HEVC_QP_VALUE(pQpRange->QpMax_I, + pCtx->videoCtx.instInfo.HwVersion); + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + if (pQpRange->QpMin_P > pQpRange->QpMax_P) { + ALOGE("%s: QP(P) range(%d, %d) is wrong", __FUNCTION__, pQpRange->QpMin_P, pQpRange->QpMax_P); + ret = -1; + goto EXIT; + } + + if (pQpRange->QpMin_B > pQpRange->QpMax_B) { + ALOGE("%s: QP(B) range(%d, %d) is wrong", __FUNCTION__, pQpRange->QpMin_B, pQpRange->QpMax_B); + ret = -1; + goto EXIT; + } + + cids[1][0] = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_P; + cids[1][1] = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_P; + cids[2][0] = V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP_B; + cids[2][1] = V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP_B; + + values[1][0] = GET_HEVC_QP_VALUE(pQpRange->QpMin_P, + pCtx->videoCtx.instInfo.HwVersion); + values[1][1] = GET_HEVC_QP_VALUE(pQpRange->QpMax_P, + pCtx->videoCtx.instInfo.HwVersion); + values[2][0] = GET_HEVC_QP_VALUE(pQpRange->QpMin_B, + pCtx->videoCtx.instInfo.HwVersion); + values[2][1] = GET_HEVC_QP_VALUE(pQpRange->QpMax_B, + pCtx->videoCtx.instInfo.HwVersion); + } + } + break; + case VIDEO_CODING_VP9: + { + cids[0][0] = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP; + cids[0][1] = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP; + + values[0][0] = GET_VP9_QP_VALUE(pQpRange->QpMin_I); + values[0][1] = GET_VP9_QP_VALUE(pQpRange->QpMax_I); + + if (pCtx->videoCtx.instInfo.supportInfo.enc.bQpRangePBSupport == VIDEO_TRUE) { + cids[1][0] = V4L2_CID_MPEG_VIDEO_VP9_MIN_QP_P; + cids[1][1] = V4L2_CID_MPEG_VIDEO_VP9_MAX_QP_P; + + values[1][0] = GET_VP9_QP_VALUE(pQpRange->QpMin_P); + values[1][1] = GET_VP9_QP_VALUE(pQpRange->QpMax_P); + } + } + break; + default: + { + ALOGE("[%s] Undefined codec type", __FUNCTION__); + ret = -1; + goto EXIT; + } + break; + } + + for (i = 0; i < (int)(sizeof(cids)/sizeof(cids[0])); i++) { + if (cids[i][0] == 0) + break; + + ALOGV("%s: QP[%d] range (%d / %d)", __FUNCTION__, i, values[i][0], values[i][1]); + + /* keep a calling sequence as Max->Min because dirver has a restriction */ + if (exynos_v4l2_s_ctrl(pCtx->videoCtx.hDevice, cids[i][1], values[i][1]) != 0) { + ALOGE("%s: Failed to s_ctrl for max value", __FUNCTION__); + ret = -1; + goto EXIT; + } + + if (exynos_v4l2_s_ctrl(pCtx->videoCtx.hDevice, cids[i][0], values[i][0]) != 0) { + ALOGE("%s: Failed to s_ctrl for min value", __FUNCTION__); + ret = -1; + goto EXIT; + } + } + } + break; + case CODEC_OSAL_CID_ENC_COLOR_ASPECTS: + { + ExynosVideoColorAspects *pColorAspects = (ExynosVideoColorAspects *)pInfo; + struct v4l2_ext_control ext_ctrl[4]; /* range, primaries, transfer, matrix coeff */ + struct v4l2_ext_controls ext_ctrls; + + ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_FULL_RANGE_FLAG; + ext_ctrl[0].value = (pColorAspects->eRangeType == RANGE_FULL)? 1:0; + + if (pCtx->videoCtx.instInfo.eCodecType == VIDEO_CODING_VP9) { + int i; + + ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES; + ext_ctrl[1].value = 0; + + /* PRIMARIES_BT601_6_625 is supposed to be used as same as PRIMARIES_BT601_6_525 based on MFC. + * And ColorSpace matrix doesn't have PRIMARIES_BT601_6_625 case + */ + if (pColorAspects->ePrimariesType == PRIMARIES_BT601_6_625) + pColorAspects->ePrimariesType = PRIMARIES_BT601_6_525; + + /* TRANSFER_SMPTE_170M is supposed to be used as same as TRANSFER_BT709 based on spec. + * And ColorSpace doesn't support TRANSFER_BT709 + */ + if (pColorAspects->eTransferType == TRANSFER_BT709) + pColorAspects->eTransferType = TRANSFER_SMPTE_170M; + + for (i = 0; i < (int)(sizeof(ColorSpaceToColorAspects)/sizeof(ColorSpaceToColorAspects[0])); i++) { + if ((ColorSpaceToColorAspects[i].primaries == pColorAspects->ePrimariesType) && + (ColorSpaceToColorAspects[i].transfer == pColorAspects->eTransferType) && + (ColorSpaceToColorAspects[i].coeff == pColorAspects->eCoeffType)) { + ext_ctrl[1].value = i; + break; + } + } + + ext_ctrls.count = 2; + } else { + ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_COLOUR_PRIMARIES; + ext_ctrl[1].value = pColorAspects->ePrimariesType; + + ext_ctrl[2].id = V4L2_CID_MPEG_VIDEO_TRANSFER_CHARACTERISTICS; + ext_ctrl[2].value = pColorAspects->eTransferType; + + ext_ctrl[3].id = V4L2_CID_MPEG_VIDEO_MATRIX_COEFFICIENTS; + ext_ctrl[3].value = pColorAspects->eCoeffType; + + ext_ctrls.count = 4; + } + + ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + ext_ctrls.controls = ext_ctrl; + + if (exynos_v4l2_s_ext_ctrl(pCtx->videoCtx.hDevice, &ext_ctrls) != 0) { + ret = -1; + goto EXIT; + } + } + break; + case CODEC_OSAL_CID_ENC_HDR_STATIC_INFO: + { + ExynosVideoHdrStatic *pHDRStaticInfo = (ExynosVideoHdrStatic *)pInfo; + struct v4l2_ext_control ext_ctrl[9]; + struct v4l2_ext_controls ext_ctrls; + + ExynosVideoHdrStatic invalidHDR; + + /* check a validation */ + memset(&invalidHDR, 0, sizeof(ExynosVideoHdrStatic)); + if (memcmp(&invalidHDR, pHDRStaticInfo, sizeof(ExynosVideoHdrStatic)) == 0) { + /* all values are invalid */ + ALOGD("%s: HDRStaticInfo is unspecified. HDRStaticInfo won't be set", __FUNCTION__); + goto EXIT; + } + + ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_STATIC_INFO_ENABLE; + ext_ctrl[0].value = 1; + + ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_SEI_MAX_PIC_AVERAGE_LIGHT; + ext_ctrl[1].value = pHDRStaticInfo->max_pic_average_light; + ALOGE("%s: value = %u", __FUNCTION__, ext_ctrl[1].value); + + + ext_ctrl[2].id = V4L2_CID_MPEG_VIDEO_SEI_MAX_CONTENT_LIGHT; + ext_ctrl[2].value = pHDRStaticInfo->max_content_light; + ALOGE("%s: value = %u", __FUNCTION__, ext_ctrl[2].value); + + ext_ctrl[3].id = V4L2_CID_MPEG_VIDEO_SEI_MAX_DISPLAY_LUMINANCE; + ext_ctrl[3].value = pHDRStaticInfo->max_display_luminance; + ALOGE("%s: value = %u", __FUNCTION__, ext_ctrl[3].value); + + ext_ctrl[4].id = V4L2_CID_MPEG_VIDEO_SEI_MIN_DISPLAY_LUMINANCE; + ext_ctrl[4].value = pHDRStaticInfo->min_display_luminance; + ALOGE("%s: value = %u", __FUNCTION__, ext_ctrl[4].value); + + ext_ctrl[5].id = V4L2_CID_MPEG_VIDEO_SEI_WHITE_POINT; + ext_ctrl[5].value = SET_16BIT_TO_HIGH(pHDRStaticInfo->white.x) | GET_16BIT_LOW(pHDRStaticInfo->white.y); + ALOGE("%s: value = %u", __FUNCTION__, ext_ctrl[5].value); + ext_ctrl[6].id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_0; + ext_ctrl[6].value = SET_16BIT_TO_HIGH(pHDRStaticInfo->green.x) | GET_16BIT_LOW(pHDRStaticInfo->green.y); + ALOGE("%s: value = %u", __FUNCTION__, ext_ctrl[6].value); + ext_ctrl[7].id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_1; + ext_ctrl[7].value = SET_16BIT_TO_HIGH(pHDRStaticInfo->blue.x) | GET_16BIT_LOW(pHDRStaticInfo->blue.y); + ALOGE("%s: value = %u", __FUNCTION__, ext_ctrl[7].value); + ext_ctrl[8].id = V4L2_CID_MPEG_VIDEO_SEI_DISPLAY_PRIMARIES_2; + ext_ctrl[8].value = SET_16BIT_TO_HIGH(pHDRStaticInfo->red.x) | GET_16BIT_LOW(pHDRStaticInfo->red.y); + ALOGE("%s: value = %u", __FUNCTION__, ext_ctrl[8].value); + + ext_ctrls.count = 9; + + ext_ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + ext_ctrls.controls = ext_ctrl; + + if (exynos_v4l2_s_ext_ctrl(pCtx->videoCtx.hDevice, &ext_ctrls) != 0) { + ret = -1; + goto EXIT; + } + } + break; + default: + { + ALOGE("%s: unsupported CID(%x)", __FUNCTION__, nCID); + ret = -1; + } + break; + } + } + +EXIT: + return ret; +} + +int Codec_OSAL_GetControl( + CodecOSALVideoContext *pCtx, + unsigned int uCID, + int *pValue) +{ + if ((pCtx != NULL) && + (pValue != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + return exynos_v4l2_g_ctrl(pCtx->videoCtx.hDevice, uCID, pValue); + } + + return -1; +} + +int Codec_OSAL_SetControl( + CodecOSALVideoContext *pCtx, + unsigned int uCID, + unsigned long nValue) +{ + if ((pCtx != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + return exynos_v4l2_s_ctrl(pCtx->videoCtx.hDevice, uCID, nValue); + } + + return -1; +} + +int Codec_OSAL_GetCrop( + CodecOSALVideoContext *pCtx, + CodecOSAL_Crop *pCrop) +{ + if ((pCtx != NULL) && + (pCrop != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + struct v4l2_crop crop; + + memset(&crop, 0, sizeof(crop)); + crop.type = pCrop->type; + + if (exynos_v4l2_g_crop(pCtx->videoCtx.hDevice, &crop) == 0) { + pCrop->top = crop.c.top; + pCrop->left = crop.c.left; + pCrop->width = crop.c.width; + pCrop->height = crop.c.height; + + return 0; + } + } + + return -1; +} + +int Codec_OSAL_GetFormat( + CodecOSALVideoContext *pCtx, + CodecOSAL_Format *pFmt) +{ + if ((pCtx != NULL) && + (pFmt != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + struct v4l2_format fmt; + int i; + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = pFmt->type; + + if (exynos_v4l2_g_fmt(pCtx->videoCtx.hDevice, &fmt) == 0) { + pFmt->format = fmt.fmt.pix_mp.pixelformat; + pFmt->width = fmt.fmt.pix_mp.width; + pFmt->height = fmt.fmt.pix_mp.height; + pFmt->stride = fmt.fmt.pix_mp.plane_fmt[0].bytesperline; + pFmt->nPlane = fmt.fmt.pix_mp.num_planes; + pFmt->field = fmt.fmt.pix_mp.field; + + for (i = 0; i < fmt.fmt.pix_mp.num_planes; i++) + pFmt->planeSize[i] = fmt.fmt.pix_mp.plane_fmt[i].sizeimage; + + return 0; + } + } + + return -1; +} + +int Codec_OSAL_SetFormat( + CodecOSALVideoContext *pCtx, + CodecOSAL_Format *pFmt) +{ + if ((pCtx != NULL) && + (pFmt != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + struct v4l2_format fmt; + int i; + + memset(&fmt, 0, sizeof(fmt)); + fmt.type = pFmt->type; + fmt.fmt.pix_mp.pixelformat = pFmt->format; + fmt.fmt.pix_mp.width = pFmt->width; + fmt.fmt.pix_mp.height = pFmt->height; + fmt.fmt.pix_mp.plane_fmt[0].bytesperline = pFmt->stride; + fmt.fmt.pix_mp.num_planes = pFmt->nPlane; + fmt.fmt.pix_mp.flags = pFmt->field; + + for (i = 0; i < pFmt->nPlane; i++) + fmt.fmt.pix_mp.plane_fmt[i].sizeimage = pFmt->planeSize[i]; + + return exynos_v4l2_s_fmt(pCtx->videoCtx.hDevice, &fmt); + } + + return -1; +} + +int Codec_OSAL_RequestBuf( + CodecOSALVideoContext *pCtx, + CodecOSAL_ReqBuf *pReqBuf) +{ + if ((pCtx != NULL) && + (pReqBuf != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + return exynos_v4l2_reqbufs(pCtx->videoCtx.hDevice, pReqBuf); + } + + return -1; +} + +int Codec_OSAL_QueryBuf( + CodecOSALVideoContext *pCtx, + CodecOSAL_Buffer *pBuf) +{ + if ((pCtx != NULL) && + (pBuf != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + struct v4l2_buffer buf; + struct v4l2_plane planes[VIDEO_BUFFER_MAX_PLANES]; + int i; + + memset(&buf, 0, sizeof(buf)); + memset(&planes, 0, sizeof(planes)); + + buf.type = pBuf->type; + buf.m.planes = planes; + buf.length = pBuf->nPlane; + buf.memory = pBuf->memory; + + if (exynos_v4l2_querybuf(pCtx->videoCtx.hDevice, &buf) == 0) { + for (i = 0; i < (int)buf.length; i++) { + pBuf->planes[i].bufferSize = buf.m.planes[i].length; + pBuf->planes[i].offset = buf.m.planes[i].m.mem_offset; + } + + return 0; + } + } + + return -1; +} + +int Codec_OSAL_SetStreamOn( + CodecOSALVideoContext *pCtx, + int nPort) +{ + if ((pCtx != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + return exynos_v4l2_streamon(pCtx->videoCtx.hDevice, nPort); + } + + return -1; +} + +int Codec_OSAL_SetStreamOff( + CodecOSALVideoContext *pCtx, + int nPort) +{ + if ((pCtx != NULL) && + (pCtx->videoCtx.hDevice >= 0)) { + return exynos_v4l2_streamoff(pCtx->videoCtx.hDevice, nPort); + } + + return -1; +} + +void *Codec_OSAL_MemoryMap(void *addr, size_t len, int prot, int flags, unsigned long fd, off_t offset) +{ + return mmap(addr, len, prot, flags, fd, offset); +} + +int Codec_OSAL_MemoryUnmap(void *addr, size_t len) +{ + return munmap(addr, len); +} diff --git a/videocodec/osal/include/ExynosVideo_OSAL.h b/videocodec/osal/include/ExynosVideo_OSAL.h new file mode 100644 index 0000000..5c032ec --- /dev/null +++ b/videocodec/osal/include/ExynosVideo_OSAL.h @@ -0,0 +1,233 @@ +/* + * + * Copyright 2016 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file ExynosVideo_OSAL.h + * @brief ExynosVideo OSAL define + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 1.0.0 + * @history + * 2016.01.07 : Create + */ + +#ifndef _EXYNOS_VIDEO_OSAL_H_ +#define _EXYNOS_VIDEO_OSAL_H_ + +#include "exynos_v4l2.h" + +#include "videodev2_exynos_media.h" +#ifdef USE_EXYNOS_MEDIA_EXT +#include "videodev2_exynos_media_ext.h" +#endif +#ifdef USE_MFC_HEADER +#include "exynos_mfc_media.h" +#endif + +#include + +#include + +#include "ExynosVideoApi.h" + +typedef enum _CodecOSAL_MemType { + CODEC_OSAL_MEM_TYPE_MMAP = V4L2_MEMORY_MMAP, + CODEC_OSAL_MEM_TYPE_USERPTR = V4L2_MEMORY_USERPTR, + CODEC_OSAL_MEM_TYPE_DMABUF = V4L2_MEMORY_DMABUF, +} CodecOSAL_MemType; + +typedef enum _CodecOSAL_BufType { + CODEC_OSAL_BUF_TYPE_SRC = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + CODEC_OSAL_BUF_TYPE_DST = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, +} CodecOSAL_BufType; + +typedef enum _CodecOSAL_CID { + CODEC_OSAL_CID_DEC_NUM_MIN_BUFFERS = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, + CODEC_OSAL_CID_DEC_DISPLAY_DELAY = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY, + CODEC_OSAL_CID_DEC_IMMEDIATE_DISPLAY = V4L2_CID_MPEG_VIDEO_DECODER_IMMEDIATE_DISPLAY, + CODEC_OSAL_CID_DEC_I_FRAME_DECODING = V4L2_CID_MPEG_MFC51_VIDEO_I_FRAME_DECODING, + CODEC_OSAL_CID_DEC_PACKED_PB = V4L2_CID_MPEG_MFC51_VIDEO_PACKED_PB, + CODEC_OSAL_CID_DEC_DEBLOCK_FILTER = V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER, + CODEC_OSAL_CID_DEC_SLICE_MODE = V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE, + CODEC_OSAL_CID_DEC_SEI_PARSING = V4L2_CID_MPEG_VIDEO_H264_SEI_FRAME_PACKING, + CODEC_OSAL_CID_DEC_DTS_MODE = V4L2_CID_MPEG_VIDEO_DECODER_DECODING_TIMESTAMP_MODE, + CODEC_OSAL_CID_DEC_DUAL_DPB_MODE = V4L2_CID_MPEG_MFC_SET_DUAL_DPB_MODE, + CODEC_OSAL_CID_DEC_DYNAMIC_DPB_MODE = V4L2_CID_MPEG_MFC_SET_DYNAMIC_DPB_MODE, + CODEC_OSAL_CID_DEC_SET_USER_SHARED_HANDLE = V4L2_CID_MPEG_MFC_SET_USER_SHARED_HANDLE, + CODEC_OSAL_CID_DEC_GET_10BIT_INFO = V4L2_CID_MPEG_MFC_GET_10BIT_INFO, + CODEC_OSAL_CID_DEC_CHECK_STATE = V4L2_CID_MPEG_MFC51_VIDEO_CHECK_STATE, + CODEC_OSAL_CID_DEC_DISPLAY_STATUS = V4L2_CID_MPEG_MFC51_VIDEO_DISPLAY_STATUS, + CODEC_OSAL_CID_DEC_WAIT_DECODING_START = V4L2_CID_MPEG_VIDEO_DECODER_WAIT_DECODING_START, + CODEC_OSAL_CID_DEC_SEARCH_BLACK_BAR = V4L2_CID_MPEG_VIDEO_BLACK_BAR_DETECT, + CODEC_OSAL_CID_DEC_ACTUAL_FORMAT = V4L2_CID_MPEG_VIDEO_UNCOMP_FMT, + + CODEC_OSAL_CID_ENC_FRAME_TYPE = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE, + CODEC_OSAL_CID_ENC_FRAME_RATE = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE_CH, + CODEC_OSAL_CID_ENC_BIT_RATE = V4L2_CID_MPEG_MFC51_VIDEO_BIT_RATE_CH, + CODEC_OSAL_CID_ENC_FRAME_SKIP_MODE = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE, + CODEC_OSAL_CID_ENC_IDR_PERIOD = V4L2_CID_MPEG_MFC51_VIDEO_I_PERIOD_CH, + CODEC_OSAL_CID_ENC_H264_PREPEND_SPSPPS_TO_IDR = V4L2_CID_MPEG_VIDEO_H264_PREPEND_SPSPPS_TO_IDR, + CODEC_OSAL_CID_ENC_HEVC_PREPEND_SPSPPS_TO_IDR = V4L2_CID_MPEG_VIDEO_HEVC_PREPEND_SPSPPS_TO_IDR, + CODEC_OSAL_CID_ENC_H264_TEMPORAL_SVC_LAYER_CH = V4L2_CID_MPEG_VIDEO_H264_HIERARCHICAL_CODING_LAYER_CH, + CODEC_OSAL_CID_ENC_HEVC_TEMPORAL_SVC_LAYER_CH = V4L2_CID_MPEG_VIDEO_HEVC_HIERARCHICAL_CODING_LAYER_CH, + CODEC_OSAL_CID_ENC_VP8_TEMPORAL_SVC_LAYER_CH = V4L2_CID_MPEG_VIDEO_VP8_HIERARCHICAL_CODING_LAYER_CH, + CODEC_OSAL_CID_ENC_VP9_TEMPORAL_SVC_LAYER_CH = V4L2_CID_MPEG_VIDEO_VP9_HIERARCHICAL_CODING_LAYER_CH, + CODEC_OSAL_CID_ENC_SET_CONFIG_QP = V4L2_CID_MPEG_MFC_CONFIG_QP, + CODEC_OSAL_CID_ENC_H264_LTR_MARK_INDEX = V4L2_CID_MPEG_MFC_H264_MARK_LTR, + CODEC_OSAL_CID_ENC_H264_LTR_USE_INDEX = V4L2_CID_MPEG_MFC_H264_USE_LTR, + CODEC_OSAL_CID_ENC_H264_LTR_BASE_PID = V4L2_CID_MPEG_MFC_H264_BASE_PRIORITY, + CODEC_OSAL_CID_ENC_ROI_INFO = V4L2_CID_MPEG_VIDEO_ROI_CONTROL, + CODEC_OSAL_CID_ENC_EXT_BUFFER_SIZE = V4L2_CID_MPEG_MFC_GET_EXTRA_BUFFER_SIZE, + CODEC_OSAL_CID_ENC_WP_ENABLE = V4L2_CID_MPEG_VIDEO_WEIGHTED_ENABLE, + CODEC_OSAL_CID_ENC_YSUM_DATA = V4L2_CID_MPEG_VIDEO_YSUM, + CODEC_OSAL_CID_ENC_I_FRAME_RATIO = V4L2_CID_MPEG_VIDEO_RATIO_OF_INTRA, + CODEC_OSAL_CID_ENC_ENABLE_ADAPTIVE_LAYER_BITRATE = V4L2_CID_MPEG_VIDEO_HIERARCHICAL_BITRATE_CTRL, + CODEC_OSAL_CID_ENC_HEADER_MODE = V4L2_CID_MPEG_VIDEO_HEADER_MODE, + CODEC_OSAL_CID_ENC_ENABLE_DROP_CTRL = V4L2_CID_MPEG_VIDEO_DROP_CONTROL, + + CODEC_OSAL_CID_VIDEO_FRAME_TAG = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_TAG, + CODEC_OSAL_CID_VIDEO_QOS_RATIO = V4L2_CID_MPEG_VIDEO_QOS_RATIO, + CODEC_OSAL_CID_VIDEO_CACHEABLE_BUFFER = V4L2_CID_CACHEABLE, + CODEC_OSAL_CID_VIDEO_GET_VERSION_INFO = V4L2_CID_MPEG_MFC_GET_VERSION_INFO, + CODEC_OSAL_CID_VIDEO_GET_EXT_INFO = V4L2_CID_MPEG_MFC_GET_EXT_INFO, + CODEC_OSAL_CID_VIDEO_GET_DRIVER_VERSION = V4L2_CID_MPEG_MFC_GET_DRIVER_INFO, + CODEC_OSAL_CID_VIDEO_SET_HDR_USER_SHARED_HANDLE = V4L2_CID_MPEG_MFC_HDR_USER_SHARED_HANDLE, +#ifdef USE_ORIGINAL_HEADER + CODEC_OSAL_CID_VIDEO_SRC_BUF_FLAG = V4L2_CID_MPEG_VIDEO_SRC_BUF_FLAG, + CODEC_OSAL_CID_VIDEO_DST_BUF_FLAG = V4L2_CID_MPEG_VIDEO_DST_BUF_FLAG, + CODEC_OSAL_CID_VIDEO_FRAME_ERROR_TYPE = V4L2_CID_MPEG_VIDEO_FRAME_ERROR_TYPE, + CODEC_OSAL_CID_VIDEO_PRIOTIY = V4L2_CID_MPEG_VIDEO_PRIORITY, +#endif + CODEC_OSAL_CID_ACTUAL_FRAMERATE = V4L2_CID_MPEG_MFC51_VIDEO_FRAME_RATE, + + CODEC_OSAL_CID_DEC_SEI_INFO = 0xFFFF0000, + CODEC_OSAL_CID_ENC_SET_PARAMS, + CODEC_OSAL_CID_ENC_QP_RANGE, + CODEC_OSAL_CID_DEC_DISCARD_RCVHEADER, /* not implemented */ + CODEC_OSAL_CID_ENC_SLICE_MODE, /* not implemented : V4L2_CID_MPEG_MFC_SET_SLICE_MODE */ + CODEC_OSAL_CID_DEC_HDR_INFO, + CODEC_OSAL_CID_ENC_COLOR_ASPECTS, + CODEC_OSAL_CID_ENC_HDR_STATIC_INFO, +} CodecOSAL_CID; + +typedef enum _CodecOSAL_InterlaceType { + CODEC_OSAL_INTER_TYPE_NONE = V4L2_FIELD_NONE, + CODEC_OSAL_INTER_TYPE_INTER = V4L2_FIELD_INTERLACED, + CODEC_OSAL_INTER_TYPE_TB = V4L2_FIELD_INTERLACED_TB, + CODEC_OSAL_INTER_TYPE_BT = V4L2_FIELD_INTERLACED_BT, +} CodecOSAL_InterlaceType; + +#ifdef USE_DEFINE_H264_SEI_TYPE +enum v4l2_mpeg_video_h264_sei_fp_type { + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_CHEKERBOARD = 0, + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_COLUMN = 1, + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_ROW = 2, + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_SIDE_BY_SIDE = 3, + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_TOP_BOTTOM = 4, + V4L2_MPEG_VIDEO_H264_SEI_FP_TYPE_TEMPORAL = 5, +}; +#endif + +typedef enum _CodecOSAL_HeaderMode { + CODEC_OSAL_HEADER_MODE_SEPARATE = V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE, + CODEC_OSAL_HEADER_WITH_1ST_IDR = V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME, +} CodecOSAL_HeaderMode; + +typedef struct _CodecOSAL_Format { + CodecOSAL_BufType type; + ExynosVideoCodingType format; + int field; + int planeSize[VIDEO_BUFFER_MAX_PLANES]; + unsigned int width; + unsigned int height; + unsigned int stride; + int nPlane; +} CodecOSAL_Format; + +typedef struct _CodecOSAL_Crop { + CodecOSAL_BufType type; + int left; + int top; + int width; + int height; +} CodecOSAL_Crop; + +typedef struct _CodecOSAL_Plane { + void *addr; + int bufferSize; + int dataLen; + unsigned offset; +} CodecOSAL_Plane; + +typedef struct _CodecOSAL_Buffer { + CodecOSAL_BufType type; + int memory; + int nPlane; + CodecOSAL_Plane planes[VIDEO_BUFFER_MAX_PLANES]; + int index; + unsigned int flags; + struct timeval timestamp; + + unsigned int field; + ExynosVideoFrameType frameType; +} CodecOSAL_Buffer; + +typedef struct v4l2_requestbuffers CodecOSAL_ReqBuf; + +typedef struct _CodecOSALInfo { + int reserved; +} CodecOSALInfo; + +typedef struct _CodecOSALVideoContext { + ExynosVideoContext videoCtx; + CodecOSALInfo osalCtx; +} CodecOSALVideoContext; + +int Codec_OSAL_VideoMemoryToSystemMemory(ExynosVideoMemoryType eMemoryType); + +unsigned int Codec_OSAL_CodingTypeToCompressdFormat(ExynosVideoCodingType eCodingType); +ExynosVideoColorFormatType Codec_OSAL_PixelFormatToColorFormat(unsigned int nPixelFormat); +unsigned int Codec_OSAL_ColorFormatToPixelFormat(ExynosVideoColorFormatType eColorFormat, int nHwVersion); + +int Codec_OSAL_DevOpen(const char *sDevName, int nFlag, CodecOSALVideoContext *pCtx); +void Codec_OSAL_DevClose(CodecOSALVideoContext *pCtx); + +int Codec_OSAL_QueryCap(CodecOSALVideoContext *pCtx); + +int Codec_OSAL_EnqueueBuf(CodecOSALVideoContext *pCtx, CodecOSAL_Buffer *pBuf); +int Codec_OSAL_DequeueBuf(CodecOSALVideoContext *pCtx, CodecOSAL_Buffer *pBuf); + +int Codec_OSAL_GetControls(CodecOSALVideoContext *pCtx, unsigned int nCID, void *pInfo); +int Codec_OSAL_SetControls(CodecOSALVideoContext *pCtx, unsigned int nCID, void *pInfo); + +int Codec_OSAL_GetControl(CodecOSALVideoContext *pCtx, unsigned int nCID, int *pValue); +int Codec_OSAL_SetControl(CodecOSALVideoContext *pCtx, unsigned int nCID, unsigned long nValue); + +int Codec_OSAL_GetCrop(CodecOSALVideoContext *pCtx, CodecOSAL_Crop *pCrop); + +int Codec_OSAL_GetFormat(CodecOSALVideoContext *pCtx, CodecOSAL_Format *pFmt); +int Codec_OSAL_SetFormat(CodecOSALVideoContext *pCtx, CodecOSAL_Format *pFmt); + +int Codec_OSAL_RequestBuf(CodecOSALVideoContext *pCtx, CodecOSAL_ReqBuf *pReqBuf); +int Codec_OSAL_QueryBuf(CodecOSALVideoContext *pCtx, CodecOSAL_Buffer *pBuf); + +int Codec_OSAL_SetStreamOn(CodecOSALVideoContext *pCtx, int nPort); +int Codec_OSAL_SetStreamOff(CodecOSALVideoContext *pCtx, int nPort); + +void *Codec_OSAL_MemoryMap(void *addr, size_t len, int prot, int flags, unsigned long fd, off_t offset); +int Codec_OSAL_MemoryUnmap(void *addr, size_t len); +#endif diff --git a/videocodec/osal/include/ExynosVideo_OSAL_Dec.h b/videocodec/osal/include/ExynosVideo_OSAL_Dec.h new file mode 100644 index 0000000..06051c7 --- /dev/null +++ b/videocodec/osal/include/ExynosVideo_OSAL_Dec.h @@ -0,0 +1,46 @@ +/* + * + * Copyright 2016 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file ExynosVideo_OSAL_Dec.h + * @brief ExynosVideo OSAL define related with Decoder + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 1.0.0 + * @history + * 2016.01.07 : Create + */ + +#ifndef _EXYNOS_VIDEO_OSAL_DEC_H_ +#define _EXYNOS_VIDEO_OSAL_DEC_H_ + +#include "ExynosVideoApi.h" +#include "ExynosVideo_OSAL.h" + +/* Normal Node */ +#define VIDEO_MFC_DECODER_NAME "s5p-mfc-dec" +#define VIDEO_HEVC_DECODER_NAME "exynos-hevc-dec" +/* Secure Node */ +#define VIDEO_MFC_SECURE_DECODER_NAME "s5p-mfc-dec-secure" +#define VIDEO_HEVC_SECURE_DECODER_NAME "exynos-hevc-dec-secure" + +#define FRAME_PACK_SEI_INFO_NUM 4 +#define HDR_INFO_NUM 12 + +#define OPERATE_BIT(x, mask, shift) ((x & (mask << shift)) >> shift) + +#endif diff --git a/videocodec/osal/include/ExynosVideo_OSAL_Enc.h b/videocodec/osal/include/ExynosVideo_OSAL_Enc.h new file mode 100644 index 0000000..00dd0c8 --- /dev/null +++ b/videocodec/osal/include/ExynosVideo_OSAL_Enc.h @@ -0,0 +1,52 @@ +/* + * + * Copyright 2016 Samsung Electronics S.LSI Co. LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * @file ExynosVideo_OSAL_Enc.h + * @brief ExynosVideo OSAL define related with Encoder + * @author SeungBeom Kim (sbcrux.kim@samsung.com) + * Taehwan Kim (t_h.kim@samsung.com) + * @version 1.0.0 + * @history + * 2016.01.07 : Create + */ + +#ifndef _EXYNOS_VIDEO_OSAL_ENC_H_ +#define _EXYNOS_VIDEO_OSAL_ENC_H_ + +#include "ExynosVideoApi.h" +#include "ExynosVideo_OSAL.h" + +/* Normal Node */ +#define VIDEO_MFC_ENCODER_NAME "s5p-mfc-enc" +#define VIDEO_HEVC_ENCODER_NAME "exynos-hevc-enc" +/* Secure Node */ +#define VIDEO_MFC_SECURE_ENCODER_NAME "s5p-mfc-enc-secure" +#define VIDEO_HEVC_SECURE_ENCODER_NAME "exynos-hevc-enc-secure" +/* OTF Node */ +#define VIDEO_MFC_OTF_ENCODER_NAME "s5p-mfc-enc-otf" +#define VIDEO_MFC_OTF_SECURE_ENCODER_NAME "s5p-mfc-enc-otf-secure" + +#define MAX_CTRL_NUM 112 /* +1(drop ctrl) */ +#define H264_CTRL_NUM 92 /* +7(svc), +4(skype), +1(roi), +4(qp range) +1(pvc) +1(drop ctrl) + 2(chroma_qp) */ +#define MPEG4_CTRL_NUM 26 /* +4(qp range) */ +#define H263_CTRL_NUM 18 /* +2(qp range) */ +#define VP8_CTRL_NUM 30 /* +3(svc), +2(qp range) */ +#define HEVC_CTRL_NUM 53 /* +7(svc), +1(roi), +4(qp range) + 2(chroma_qp) */ +#define VP9_CTRL_NUM 29 /* +3(svc), +4(qp range) */ + +#endif