From a9bdc01ee61858493c8aa534878c2cae73ee9626 Mon Sep 17 00:00:00 2001 From: TO21Consortium <51391510+TO21Consortium@users.noreply.github.com> Date: Tue, 11 Jun 2019 18:50:50 +0900 Subject: [PATCH] import exynos 7570 bsp * source taken from https://github.com/TO21Consortium/SGSWPlatform Change-Id: I0dab428039bedcececa7ab8559ef0bbab15b4c7a --- Android.mk | 85 + NOTICE | 190 + component/audio/dec/Android.mk | 30 + component/audio/dec/Exynos_OMX_Adec.c | 1569 ++++++++ component/audio/dec/Exynos_OMX_Adec.h | 144 + component/audio/dec/NOTICE | 190 + component/audio/dec/mp3/Android.mk | 40 + component/audio/dec/mp3/Exynos_OMX_Mp3dec.c | 940 +++++ component/audio/dec/mp3/Exynos_OMX_Mp3dec.h | 63 + component/audio/dec/mp3/NOTICE | 190 + component/audio/dec/mp3/library_register.c | 58 + component/audio/dec/mp3/library_register.h | 54 + component/audio/dec/wma/Android.mk | 33 + component/audio/dec/wma/Exynos_OMX_Wmadec.c | 752 ++++ component/audio/dec/wma/Exynos_OMX_Wmadec.h | 68 + component/audio/dec/wma/NOTICE | 190 + component/audio/dec/wma/library_register.c | 57 + component/audio/dec/wma/library_register.h | 53 + component/audio/seiren_dec/Android.mk | 28 + component/audio/seiren_dec/Exynos_OMX_Adec.c | 1562 ++++++++ component/audio/seiren_dec/Exynos_OMX_Adec.h | 143 + component/audio/seiren_dec/NOTICE | 190 + component/audio/seiren_dec/aac/Android.mk | 40 + .../audio/seiren_dec/aac/Exynos_OMX_Aacdec.c | 963 +++++ .../audio/seiren_dec/aac/Exynos_OMX_Aacdec.h | 72 + component/audio/seiren_dec/aac/NOTICE | 190 + .../audio/seiren_dec/aac/library_register.c | 58 + .../audio/seiren_dec/aac/library_register.h | 54 + component/audio/seiren_dec/flac/Android.mk | 40 + .../seiren_dec/flac/Exynos_OMX_Flacdec.c | 939 +++++ .../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 | 40 + .../audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.c | 954 +++++ .../audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.h | 74 + component/audio/seiren_dec/mp3/NOTICE | 190 + .../audio/seiren_dec/mp3/library_register.c | 67 + .../audio/seiren_dec/mp3/library_register.h | 60 + component/common/Android.mk | 76 + component/common/Exynos_OMX_Basecomponent.c | 1672 ++++++++ component/common/Exynos_OMX_Basecomponent.h | 162 + component/common/Exynos_OMX_Baseport.c | 1148 ++++++ component/common/Exynos_OMX_Baseport.h | 233 ++ component/common/Exynos_OMX_Resourcemanager.c | 584 +++ component/common/Exynos_OMX_Resourcemanager.h | 50 + component/common/NOTICE | 190 + component/video/dec/Android.mk | 58 + component/video/dec/Exynos_OMX_Vdec.c | 1887 +++++++++ component/video/dec/Exynos_OMX_Vdec.h | 199 + component/video/dec/Exynos_OMX_VdecControl.c | 2057 ++++++++++ component/video/dec/Exynos_OMX_VdecControl.h | 116 + component/video/dec/NOTICE | 190 + component/video/dec/h264/Android.mk | 83 + component/video/dec/h264/Exynos_OMX_H264dec.c | 3423 ++++++++++++++++ component/video/dec/h264/Exynos_OMX_H264dec.h | 101 + component/video/dec/h264/NOTICE | 190 + component/video/dec/h264/library_register.c | 69 + component/video/dec/h264/library_register.h | 60 + component/video/dec/hevc/Android.mk | 77 + component/video/dec/hevc/Exynos_OMX_HEVCdec.c | 3392 ++++++++++++++++ component/video/dec/hevc/Exynos_OMX_HEVCdec.h | 96 + component/video/dec/hevc/NOTICE | 190 + component/video/dec/hevc/library_register.c | 76 + component/video/dec/hevc/library_register.h | 60 + component/video/dec/mpeg2/Android.mk | 62 + .../video/dec/mpeg2/Exynos_OMX_Mpeg2dec.c | 3085 +++++++++++++++ .../video/dec/mpeg2/Exynos_OMX_Mpeg2dec.h | 91 + component/video/dec/mpeg2/NOTICE | 190 + component/video/dec/mpeg2/library_register.c | 63 + component/video/dec/mpeg2/library_register.h | 56 + component/video/dec/mpeg4/Android.mk | 66 + .../video/dec/mpeg4/Exynos_OMX_Mpeg4dec.c | 3470 ++++++++++++++++ .../video/dec/mpeg4/Exynos_OMX_Mpeg4dec.h | 118 + component/video/dec/mpeg4/NOTICE | 190 + component/video/dec/mpeg4/library_register.c | 84 + component/video/dec/mpeg4/library_register.h | 66 + component/video/dec/vc1/Android.mk | 66 + component/video/dec/vc1/Exynos_OMX_Wmvdec.c | 3443 ++++++++++++++++ component/video/dec/vc1/Exynos_OMX_Wmvdec.h | 103 + component/video/dec/vc1/NOTICE | 190 + component/video/dec/vc1/library_register.c | 63 + component/video/dec/vc1/library_register.h | 55 + component/video/dec/vp8/Android.mk | 63 + component/video/dec/vp8/Exynos_OMX_Vp8dec.c | 3073 +++++++++++++++ component/video/dec/vp8/Exynos_OMX_Vp8dec.h | 92 + component/video/dec/vp8/NOTICE | 190 + component/video/dec/vp8/library_register.c | 63 + component/video/dec/vp8/library_register.h | 56 + component/video/dec/vp9/Android.mk | 63 + component/video/dec/vp9/Exynos_OMX_Vp9dec.c | 2782 +++++++++++++ component/video/dec/vp9/Exynos_OMX_Vp9dec.h | 86 + component/video/dec/vp9/NOTICE | 190 + component/video/dec/vp9/library_register.c | 64 + component/video/dec/vp9/library_register.h | 57 + component/video/enc/Android.mk | 75 + component/video/enc/Exynos_OMX_Venc.c | 2038 ++++++++++ component/video/enc/Exynos_OMX_Venc.h | 178 + component/video/enc/Exynos_OMX_VencControl.c | 2129 ++++++++++ component/video/enc/Exynos_OMX_VencControl.h | 110 + component/video/enc/NOTICE | 190 + component/video/enc/h264/Android.mk | 78 + component/video/enc/h264/Exynos_OMX_H264enc.c | 3508 +++++++++++++++++ component/video/enc/h264/Exynos_OMX_H264enc.h | 123 + component/video/enc/h264/NOTICE | 190 + component/video/enc/h264/library_register.c | 60 + component/video/enc/h264/library_register.h | 56 + component/video/enc/hevc/Android.mk | 72 + component/video/enc/hevc/Exynos_OMX_HEVCenc.c | 3257 +++++++++++++++ component/video/enc/hevc/Exynos_OMX_HEVCenc.h | 94 + component/video/enc/hevc/NOTICE | 190 + component/video/enc/hevc/library_register.c | 61 + component/video/enc/hevc/library_register.h | 57 + component/video/enc/mpeg4/Android.mk | 66 + .../video/enc/mpeg4/Exynos_OMX_Mpeg4enc.c | 3145 +++++++++++++++ .../video/enc/mpeg4/Exynos_OMX_Mpeg4enc.h | 98 + component/video/enc/mpeg4/NOTICE | 190 + component/video/enc/mpeg4/library_register.c | 62 + component/video/enc/mpeg4/library_register.h | 59 + component/video/enc/vp8/Android.mk | 67 + component/video/enc/vp8/Exynos_OMX_Vp8enc.c | 3053 ++++++++++++++ component/video/enc/vp8/Exynos_OMX_Vp8enc.h | 91 + component/video/enc/vp8/NOTICE | 190 + component/video/enc/vp8/library_register.c | 58 + component/video/enc/vp8/library_register.h | 56 + component/video/enc/vp9/Android.mk | 66 + component/video/enc/vp9/Exynos_OMX_Vp9enc.c | 2936 ++++++++++++++ component/video/enc/vp9/Exynos_OMX_Vp9enc.h | 91 + component/video/enc/vp9/NOTICE | 190 + component/video/enc/vp9/library_register.c | 58 + component/video/enc/vp9/library_register.h | 56 + core/Android.mk | 44 + core/Exynos_OMX_Component_Register.c | 266 ++ core/Exynos_OMX_Component_Register.h | 75 + core/Exynos_OMX_Core.c | 416 ++ core/Exynos_OMX_Core.h | 78 + core/NOTICE | 190 + include/exynos/Exynos_OMX_Def.h | 850 ++++ include/exynos/Exynos_OMX_Macros.h | 97 + include/khronos/OMX_Audio.h | 1311 ++++++ include/khronos/OMX_Component.h | 579 +++ include/khronos/OMX_ComponentExt.h | 61 + include/khronos/OMX_ContentPipe.h | 195 + include/khronos/OMX_Core.h | 1431 +++++++ include/khronos/OMX_CoreExt.h | 73 + include/khronos/OMX_IVCommon.h | 920 +++++ include/khronos/OMX_Image.h | 328 ++ include/khronos/OMX_ImageExt.h | 55 + include/khronos/OMX_Index.h | 258 ++ include/khronos/OMX_IndexExt.h | 90 + include/khronos/OMX_Other.h | 337 ++ include/khronos/OMX_Types.h | 359 ++ include/khronos/OMX_Video.h | 1060 +++++ include/khronos/OMX_VideoExt.h | 123 + include/skype/OMX_Video_Extensions.h | 187 + osal/Android.mk | 187 + osal/Exynos_OSAL_Android.cpp | 1330 +++++++ osal/Exynos_OSAL_Android.h | 98 + osal/Exynos_OSAL_ETC.c | 890 +++++ osal/Exynos_OSAL_ETC.h | 122 + osal/Exynos_OSAL_Event.c | 217 + osal/Exynos_OSAL_Event.h | 61 + osal/Exynos_OSAL_Library.c | 54 + osal/Exynos_OSAL_Library.h | 46 + osal/Exynos_OSAL_Log.c | 122 + osal/Exynos_OSAL_Log.h | 80 + osal/Exynos_OSAL_Memory.c | 76 + osal/Exynos_OSAL_Memory.h | 49 + osal/Exynos_OSAL_Mutex.c | 92 + osal/Exynos_OSAL_Mutex.h | 47 + osal/Exynos_OSAL_Queue.c | 197 + osal/Exynos_OSAL_Queue.h | 68 + osal/Exynos_OSAL_Semaphore.c | 161 + osal/Exynos_OSAL_Semaphore.h | 50 + osal/Exynos_OSAL_SharedMemory.c | 539 +++ osal/Exynos_OSAL_SharedMemory.h | 63 + osal/Exynos_OSAL_SkypeHD.c | 1183 ++++++ osal/Exynos_OSAL_SkypeHD.h | 69 + osal/Exynos_OSAL_Thread.c | 165 + osal/Exynos_OSAL_Thread.h | 48 + osal/NOTICE | 190 + 182 files changed, 84013 insertions(+) create mode 100644 Android.mk create mode 100644 NOTICE create mode 100644 component/audio/dec/Android.mk create mode 100644 component/audio/dec/Exynos_OMX_Adec.c create mode 100644 component/audio/dec/Exynos_OMX_Adec.h create mode 100644 component/audio/dec/NOTICE create mode 100644 component/audio/dec/mp3/Android.mk create mode 100644 component/audio/dec/mp3/Exynos_OMX_Mp3dec.c create mode 100644 component/audio/dec/mp3/Exynos_OMX_Mp3dec.h create mode 100644 component/audio/dec/mp3/NOTICE create mode 100644 component/audio/dec/mp3/library_register.c create mode 100644 component/audio/dec/mp3/library_register.h create mode 100644 component/audio/dec/wma/Android.mk create mode 100644 component/audio/dec/wma/Exynos_OMX_Wmadec.c create mode 100644 component/audio/dec/wma/Exynos_OMX_Wmadec.h create mode 100644 component/audio/dec/wma/NOTICE create mode 100644 component/audio/dec/wma/library_register.c create mode 100644 component/audio/dec/wma/library_register.h create mode 100644 component/audio/seiren_dec/Android.mk create mode 100644 component/audio/seiren_dec/Exynos_OMX_Adec.c create mode 100644 component/audio/seiren_dec/Exynos_OMX_Adec.h create mode 100644 component/audio/seiren_dec/NOTICE create mode 100644 component/audio/seiren_dec/aac/Android.mk create mode 100644 component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.c create mode 100644 component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.h create mode 100644 component/audio/seiren_dec/aac/NOTICE create mode 100644 component/audio/seiren_dec/aac/library_register.c create mode 100644 component/audio/seiren_dec/aac/library_register.h create mode 100644 component/audio/seiren_dec/flac/Android.mk create mode 100644 component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.c create mode 100644 component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.h create mode 100644 component/audio/seiren_dec/flac/NOTICE create mode 100644 component/audio/seiren_dec/flac/library_register.c create mode 100644 component/audio/seiren_dec/flac/library_register.h create mode 100644 component/audio/seiren_dec/mp3/Android.mk create mode 100644 component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.c create mode 100644 component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.h create mode 100644 component/audio/seiren_dec/mp3/NOTICE create mode 100644 component/audio/seiren_dec/mp3/library_register.c create mode 100644 component/audio/seiren_dec/mp3/library_register.h create mode 100644 component/common/Android.mk create mode 100644 component/common/Exynos_OMX_Basecomponent.c create mode 100644 component/common/Exynos_OMX_Basecomponent.h create mode 100644 component/common/Exynos_OMX_Baseport.c create mode 100644 component/common/Exynos_OMX_Baseport.h create mode 100644 component/common/Exynos_OMX_Resourcemanager.c create mode 100644 component/common/Exynos_OMX_Resourcemanager.h create mode 100644 component/common/NOTICE create mode 100644 component/video/dec/Android.mk create mode 100644 component/video/dec/Exynos_OMX_Vdec.c create mode 100644 component/video/dec/Exynos_OMX_Vdec.h create mode 100644 component/video/dec/Exynos_OMX_VdecControl.c create mode 100644 component/video/dec/Exynos_OMX_VdecControl.h create mode 100644 component/video/dec/NOTICE create mode 100644 component/video/dec/h264/Android.mk create mode 100644 component/video/dec/h264/Exynos_OMX_H264dec.c create mode 100644 component/video/dec/h264/Exynos_OMX_H264dec.h create mode 100644 component/video/dec/h264/NOTICE create mode 100644 component/video/dec/h264/library_register.c create mode 100644 component/video/dec/h264/library_register.h create mode 100644 component/video/dec/hevc/Android.mk create mode 100644 component/video/dec/hevc/Exynos_OMX_HEVCdec.c create mode 100644 component/video/dec/hevc/Exynos_OMX_HEVCdec.h create mode 100644 component/video/dec/hevc/NOTICE create mode 100644 component/video/dec/hevc/library_register.c create mode 100644 component/video/dec/hevc/library_register.h create mode 100644 component/video/dec/mpeg2/Android.mk create mode 100644 component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.c create mode 100644 component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.h create mode 100644 component/video/dec/mpeg2/NOTICE create mode 100644 component/video/dec/mpeg2/library_register.c create mode 100644 component/video/dec/mpeg2/library_register.h create mode 100644 component/video/dec/mpeg4/Android.mk create mode 100644 component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.c create mode 100644 component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.h create mode 100644 component/video/dec/mpeg4/NOTICE create mode 100644 component/video/dec/mpeg4/library_register.c create mode 100644 component/video/dec/mpeg4/library_register.h create mode 100644 component/video/dec/vc1/Android.mk create mode 100644 component/video/dec/vc1/Exynos_OMX_Wmvdec.c create mode 100644 component/video/dec/vc1/Exynos_OMX_Wmvdec.h create mode 100644 component/video/dec/vc1/NOTICE create mode 100644 component/video/dec/vc1/library_register.c create mode 100644 component/video/dec/vc1/library_register.h create mode 100644 component/video/dec/vp8/Android.mk create mode 100644 component/video/dec/vp8/Exynos_OMX_Vp8dec.c create mode 100644 component/video/dec/vp8/Exynos_OMX_Vp8dec.h create mode 100644 component/video/dec/vp8/NOTICE create mode 100644 component/video/dec/vp8/library_register.c create mode 100644 component/video/dec/vp8/library_register.h create mode 100644 component/video/dec/vp9/Android.mk create mode 100644 component/video/dec/vp9/Exynos_OMX_Vp9dec.c create mode 100644 component/video/dec/vp9/Exynos_OMX_Vp9dec.h create mode 100644 component/video/dec/vp9/NOTICE create mode 100644 component/video/dec/vp9/library_register.c create mode 100644 component/video/dec/vp9/library_register.h create mode 100644 component/video/enc/Android.mk create mode 100644 component/video/enc/Exynos_OMX_Venc.c create mode 100644 component/video/enc/Exynos_OMX_Venc.h create mode 100644 component/video/enc/Exynos_OMX_VencControl.c create mode 100644 component/video/enc/Exynos_OMX_VencControl.h create mode 100644 component/video/enc/NOTICE create mode 100644 component/video/enc/h264/Android.mk create mode 100644 component/video/enc/h264/Exynos_OMX_H264enc.c create mode 100644 component/video/enc/h264/Exynos_OMX_H264enc.h create mode 100644 component/video/enc/h264/NOTICE create mode 100644 component/video/enc/h264/library_register.c create mode 100644 component/video/enc/h264/library_register.h create mode 100644 component/video/enc/hevc/Android.mk create mode 100644 component/video/enc/hevc/Exynos_OMX_HEVCenc.c create mode 100644 component/video/enc/hevc/Exynos_OMX_HEVCenc.h create mode 100644 component/video/enc/hevc/NOTICE create mode 100644 component/video/enc/hevc/library_register.c create mode 100644 component/video/enc/hevc/library_register.h create mode 100644 component/video/enc/mpeg4/Android.mk create mode 100644 component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.c create mode 100644 component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.h create mode 100644 component/video/enc/mpeg4/NOTICE create mode 100644 component/video/enc/mpeg4/library_register.c create mode 100644 component/video/enc/mpeg4/library_register.h create mode 100644 component/video/enc/vp8/Android.mk create mode 100644 component/video/enc/vp8/Exynos_OMX_Vp8enc.c create mode 100644 component/video/enc/vp8/Exynos_OMX_Vp8enc.h create mode 100644 component/video/enc/vp8/NOTICE create mode 100644 component/video/enc/vp8/library_register.c create mode 100644 component/video/enc/vp8/library_register.h create mode 100644 component/video/enc/vp9/Android.mk create mode 100644 component/video/enc/vp9/Exynos_OMX_Vp9enc.c create mode 100644 component/video/enc/vp9/Exynos_OMX_Vp9enc.h create mode 100644 component/video/enc/vp9/NOTICE create mode 100644 component/video/enc/vp9/library_register.c create mode 100644 component/video/enc/vp9/library_register.h create mode 100644 core/Android.mk create mode 100644 core/Exynos_OMX_Component_Register.c create mode 100644 core/Exynos_OMX_Component_Register.h create mode 100644 core/Exynos_OMX_Core.c create mode 100644 core/Exynos_OMX_Core.h create mode 100644 core/NOTICE create mode 100644 include/exynos/Exynos_OMX_Def.h create mode 100644 include/exynos/Exynos_OMX_Macros.h create mode 100644 include/khronos/OMX_Audio.h create mode 100644 include/khronos/OMX_Component.h create mode 100644 include/khronos/OMX_ComponentExt.h create mode 100644 include/khronos/OMX_ContentPipe.h create mode 100644 include/khronos/OMX_Core.h create mode 100644 include/khronos/OMX_CoreExt.h create mode 100644 include/khronos/OMX_IVCommon.h create mode 100644 include/khronos/OMX_Image.h create mode 100644 include/khronos/OMX_ImageExt.h create mode 100644 include/khronos/OMX_Index.h create mode 100644 include/khronos/OMX_IndexExt.h create mode 100644 include/khronos/OMX_Other.h create mode 100644 include/khronos/OMX_Types.h create mode 100644 include/khronos/OMX_Video.h create mode 100644 include/khronos/OMX_VideoExt.h create mode 100644 include/skype/OMX_Video_Extensions.h create mode 100644 osal/Android.mk create mode 100644 osal/Exynos_OSAL_Android.cpp create mode 100644 osal/Exynos_OSAL_Android.h create mode 100644 osal/Exynos_OSAL_ETC.c create mode 100644 osal/Exynos_OSAL_ETC.h create mode 100644 osal/Exynos_OSAL_Event.c create mode 100644 osal/Exynos_OSAL_Event.h create mode 100644 osal/Exynos_OSAL_Library.c create mode 100644 osal/Exynos_OSAL_Library.h create mode 100644 osal/Exynos_OSAL_Log.c create mode 100644 osal/Exynos_OSAL_Log.h create mode 100644 osal/Exynos_OSAL_Memory.c create mode 100644 osal/Exynos_OSAL_Memory.h create mode 100644 osal/Exynos_OSAL_Mutex.c create mode 100644 osal/Exynos_OSAL_Mutex.h create mode 100644 osal/Exynos_OSAL_Queue.c create mode 100644 osal/Exynos_OSAL_Queue.h create mode 100644 osal/Exynos_OSAL_Semaphore.c create mode 100644 osal/Exynos_OSAL_Semaphore.h create mode 100644 osal/Exynos_OSAL_SharedMemory.c create mode 100644 osal/Exynos_OSAL_SharedMemory.h create mode 100644 osal/Exynos_OSAL_SkypeHD.c create mode 100644 osal/Exynos_OSAL_SkypeHD.h create mode 100644 osal/Exynos_OSAL_Thread.c create mode 100644 osal/Exynos_OSAL_Thread.h create mode 100644 osal/NOTICE diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..6970d08 --- /dev/null +++ b/Android.mk @@ -0,0 +1,85 @@ +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), true) +BOARD_USE_ANB := true +BOARD_USE_ANDROIDOPAQUE := true +ANDROID_MEDIA_INC := $(TOP)/frameworks/native/include/media +else +BOARD_USE_METADATABUFFERTYPE := 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 := \ + hardware/samsung_slsi/exynos/libvideocodec +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/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 + +ifeq ($(BOARD_USE_VP8ENC_SUPPORT), true) +include $(EXYNOS_OMX_COMPONENT)/video/enc/vp8/Android.mk +endif +ifeq ($(BOARD_USE_HEVCDEC_SUPPORT), true) +include $(EXYNOS_OMX_COMPONENT)/video/dec/hevc/Android.mk +endif +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_ALP_AUDIO), true) + 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/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/component/audio/dec/Android.mk b/component/audio/dec/Android.mk new file mode 100644 index 0000000..7bc75d4 --- /dev/null +++ b/component/audio/dec/Android.mk @@ -0,0 +1,30 @@ +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_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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_STATIC_LIBRARY) diff --git a/component/audio/dec/Exynos_OMX_Adec.c b/component/audio/dec/Exynos_OMX_Adec.c new file mode 100644 index 0000000..e51a94e --- /dev/null +++ b/component/audio/dec/Exynos_OMX_Adec.c @@ -0,0 +1,1569 @@ +/* + * + * 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 (pExynosPort->portState != OMX_StateIdle) { + 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) { + 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 (pExynosPort->portState != OMX_StateIdle ) { + ret = OMX_ErrorIncorrectStateOperation; + 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 != OMX_StateLoaded) && (pExynosPort->portState != OMX_StateInvalid)) { + (*(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 == OMX_StateIdle) && + (pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portState == OMX_StateIdle) && + (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->way.port1WayDataBuffer.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->way.port1WayDataBuffer.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->way.port1WayDataBuffer.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->way.port1WayDataBuffer.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.multiPlaneBuffer.dataBuffer[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->way.port1WayDataBuffer.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->multiPlaneBuffer.dataBuffer[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_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->way.port1WayDataBuffer.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 { + Exynos_ResetCodecData(outputData); + ret = OMX_TRUE; + goto EXIT; + } + } else if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) { + Exynos_ResetCodecData(outputData); + 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; + + /* reset outputData */ + Exynos_ResetCodecData(outputData); + + if ((outputUseBuffer->remainDataLen > 0) || + (outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) || + (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) + Exynos_OutputBufferReturn(pOMXComponent); + } 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->way.port1WayDataBuffer.dataBuffer; + EXYNOS_OMX_DATABUFFER *outputUseBuffer = &exynosOutputPort->way.port1WayDataBuffer.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 != OMX_StateIdle) || + (exynosOutputPort->portState != OMX_StateIdle)) { + 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(); + + if (pExynosPort->portWayType == WAY2_PORT) { + *pDataBuffer = NULL; + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + *pDataBuffer = &pExynosPort->way.port1WayDataBuffer.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); + } + } + + 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); + + pExynosComponent->pExynosPort[nPortIndex].bIsPortFlushed = OMX_TRUE; + + 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); + + pExynosComponent->pExynosPort[nPortIndex].bIsPortFlushed = OMX_FALSE; + + if (bEvent == OMX_TRUE && ret == OMX_ErrorNone) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandFlush, nPortIndex, NULL); + } + + 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: + if ((ret != OMX_ErrorNone) && (pOMXComponent != NULL) && (pExynosComponent != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR,"%s : %d", __FUNCTION__, __LINE__); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + + 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; + pExynosComponent->bMultiThreadProcess = 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/component/audio/dec/Exynos_OMX_Adec.h b/component/audio/dec/Exynos_OMX_Adec.h new file mode 100644 index 0000000..d48636e --- /dev/null +++ b/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_Baseport.h" +#include "Exynos_OMX_Basecomponent.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/component/audio/dec/NOTICE b/component/audio/dec/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/audio/dec/mp3/Android.mk b/component/audio/dec/mp3/Android.mk new file mode 100644 index 0000000..6fb6ecd --- /dev/null +++ b/component/audio/dec/mp3/Android.mk @@ -0,0 +1,40 @@ +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_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Adec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + 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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/audio/dec/mp3/Exynos_OMX_Mp3dec.c b/component/audio/dec/mp3/Exynos_OMX_Mp3dec.c new file mode 100644 index 0000000..0e677e1 --- /dev/null +++ b/component/audio/dec/mp3/Exynos_OMX_Mp3dec.c @@ -0,0 +1,940 @@ +/* + * + * 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_Basecomponent.h" +#include "Exynos_OMX_Baseport.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->multiPlaneBuffer.dataBuffer[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->multiPlaneBuffer.dataBuffer[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->multiPlaneBuffer.dataBuffer[AUDIO_DATA_PLANE], dataBuffer, dataLen); + } else { + pOutputData->dataLen = 0; + } + +#ifdef SRP_DUMP_TO_FILE + if (pOutputData->dataLen > 0) + fwrite(pOutputData->multiPlaneBuffer.dataBuffer[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.multiPlaneBuffer.dataBuffer[AUDIO_DATA_PLANE] = Exynos_OSAL_Malloc(inputBufferSize); + if (pExynosPort->processData.multiPlaneBuffer.dataBuffer[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; + pExynosPort->portWayType = WAY1_PORT; + + /* 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; + pExynosPort->portWayType = WAY1_PORT; + + /* 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.multiPlaneBuffer.dataBuffer[AUDIO_DATA_PLANE]); + pExynosPort->processData.multiPlaneBuffer.dataBuffer[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.multiPlaneBuffer.dataBuffer[AUDIO_DATA_PLANE]) { + Exynos_OSAL_Free(pExynosPort->processData.multiPlaneBuffer.dataBuffer[AUDIO_DATA_PLANE]); + pExynosPort->processData.multiPlaneBuffer.dataBuffer[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/component/audio/dec/mp3/Exynos_OMX_Mp3dec.h b/component/audio/dec/mp3/Exynos_OMX_Mp3dec.h new file mode 100644 index 0000000..6e871b5 --- /dev/null +++ b/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/component/audio/dec/mp3/NOTICE b/component/audio/dec/mp3/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/audio/dec/mp3/library_register.c b/component/audio/dec/mp3/library_register.c new file mode 100644 index 0000000..f0775cc --- /dev/null +++ b/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/component/audio/dec/mp3/library_register.h b/component/audio/dec/mp3/library_register.h new file mode 100644 index 0000000..7b9c34a --- /dev/null +++ b/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/component/audio/dec/wma/Android.mk b/component/audio/dec/wma/Android.mk new file mode 100644 index 0000000..8b5e302 --- /dev/null +++ b/component/audio/dec/wma/Android.mk @@ -0,0 +1,33 @@ +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_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Adec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + 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/component/audio/dec/wma/Exynos_OMX_Wmadec.c b/component/audio/dec/wma/Exynos_OMX_Wmadec.c new file mode 100644 index 0000000..6ed3cec --- /dev/null +++ b/component/audio/dec/wma/Exynos_OMX_Wmadec.c @@ -0,0 +1,752 @@ +/* + * + * 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_Basecomponent.h" +#include "Exynos_OMX_Baseport.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->multiPlaneBuffer.dataBuffer[AUDIO_DATA_PLANE], codec_info_size); + Exynos_OSAL_Memcpy(extra_data, ((char*)pInputData->multiPlaneBuffer.dataBuffer[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->multiPlaneBuffer.dataBuffer[AUDIO_DATA_PLANE], (int*)&pInputData->dataLen, + pOutputData->multiPlaneBuffer.dataBuffer[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.multiPlaneBuffer.dataBuffer[AUDIO_DATA_PLANE] = Exynos_OSAL_Malloc(inputBufferSize); + if (pExynosPort->processData.multiPlaneBuffer.dataBuffer[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; + pExynosPort->portWayType = WAY1_PORT; + + /* 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; + pExynosPort->portWayType = WAY1_PORT; + + /* 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.multiPlaneBuffer.dataBuffer[AUDIO_DATA_PLANE]) { + Exynos_OSAL_Free(pExynosPort->processData.multiPlaneBuffer.dataBuffer[AUDIO_DATA_PLANE]); + pExynosPort->processData.multiPlaneBuffer.dataBuffer[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/component/audio/dec/wma/Exynos_OMX_Wmadec.h b/component/audio/dec/wma/Exynos_OMX_Wmadec.h new file mode 100644 index 0000000..9cef0c4 --- /dev/null +++ b/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/component/audio/dec/wma/NOTICE b/component/audio/dec/wma/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/audio/dec/wma/library_register.c b/component/audio/dec/wma/library_register.c new file mode 100644 index 0000000..a2122c0 --- /dev/null +++ b/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/component/audio/dec/wma/library_register.h b/component/audio/dec/wma/library_register.h new file mode 100644 index 0000000..0e7aaad --- /dev/null +++ b/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/component/audio/seiren_dec/Android.mk b/component/audio/seiren_dec/Android.mk new file mode 100644 index 0000000..8dc2db1 --- /dev/null +++ b/component/audio/seiren_dec/Android.mk @@ -0,0 +1,28 @@ +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_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/component/audio/seiren_dec/Exynos_OMX_Adec.c b/component/audio/seiren_dec/Exynos_OMX_Adec.c new file mode 100644 index 0000000..9ae681f --- /dev/null +++ b/component/audio/seiren_dec/Exynos_OMX_Adec.c @@ -0,0 +1,1562 @@ +/* + * + * 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 (pExynosPort->portState != OMX_StateIdle) { + 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) { + 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 (pExynosPort->portState != OMX_StateIdle ) { + ret = OMX_ErrorIncorrectStateOperation; + 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 != OMX_StateLoaded) && (pExynosPort->portState != OMX_StateInvalid)) { + (*(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 == OMX_StateIdle) && + (pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portState == OMX_StateIdle) && + (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->way.port1WayDataBuffer.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->way.port1WayDataBuffer.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->way.port1WayDataBuffer.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->way.port1WayDataBuffer.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.multiPlaneBuffer.dataBuffer[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->way.port1WayDataBuffer.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->multiPlaneBuffer.dataBuffer[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_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->way.port1WayDataBuffer.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 { + Exynos_ResetCodecData(outputData); + ret = OMX_TRUE; + goto EXIT; + } + } else if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) { + Exynos_ResetCodecData(outputData); + 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; + + /* reset outputData */ + Exynos_ResetCodecData(outputData); + + if ((outputUseBuffer->remainDataLen > 0) || + (outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) || + (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) + Exynos_OutputBufferReturn(pOMXComponent); + } 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->way.port1WayDataBuffer.dataBuffer; + EXYNOS_OMX_DATABUFFER *outputUseBuffer = &exynosOutputPort->way.port1WayDataBuffer.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 != OMX_StateIdle) || + (exynosOutputPort->portState != OMX_StateIdle)) { + 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(); + + if (pExynosPort->portWayType == WAY2_PORT) { + *pDataBuffer = NULL; + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + *pDataBuffer = &pExynosPort->way.port1WayDataBuffer.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); + } + } + + 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); + + pExynosComponent->pExynosPort[nPortIndex].bIsPortFlushed = OMX_FALSE; + + if (bEvent == OMX_TRUE && ret == OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "bEVENT!!!!!!OMX_FLUSH_SEIREN"); + pAudioDec->exynos_codec_flushSeiren(pOMXComponent, nPortIndex); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandFlush, nPortIndex, NULL); + } + + 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: + if ((ret != OMX_ErrorNone) && (pOMXComponent != NULL) && (pExynosComponent != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR,"%s : %d", __FUNCTION__, __LINE__); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + + 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; + pExynosComponent->bMultiThreadProcess = 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/component/audio/seiren_dec/Exynos_OMX_Adec.h b/component/audio/seiren_dec/Exynos_OMX_Adec.h new file mode 100644 index 0000000..f67312d --- /dev/null +++ b/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_Baseport.h" +#include "Exynos_OMX_Basecomponent.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/component/audio/seiren_dec/NOTICE b/component/audio/seiren_dec/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/audio/seiren_dec/aac/Android.mk b/component/audio/seiren_dec/aac/Android.mk new file mode 100644 index 0000000..c043e55 --- /dev/null +++ b/component/audio/seiren_dec/aac/Android.mk @@ -0,0 +1,40 @@ +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_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Adec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + 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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.c b/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.c new file mode 100644 index 0000000..aedff6f --- /dev/null +++ b/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.c @@ -0,0 +1,963 @@ +/* + * + * 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_Basecomponent.h" +#include "Exynos_OMX_Baseport.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 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 sample_rate, channels; + int consumed_size = 0; + sample_rate = channels = 0; + + FunctionIn(); + +#ifdef Seiren_DUMP_TO_FILE + if (pExynosComponent->reInputData == OMX_FALSE) { + fwrite(pInputData->multiPlaneBuffer.dataBuffer[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, aac_sample_rates[sample_rate_index]); + ADec_SetParams(fd, PCM_PARAM_NUM_OF_CH, 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_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_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->multiPlaneBuffer.dataBuffer[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->multiPlaneBuffer.dataBuffer[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_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_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_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.multiPlaneBuffer.dataBuffer[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; + pExynosPort->portWayType = WAY1_PORT; + + /* 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; + pExynosPort->portWayType = WAY1_PORT; + + /* 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.multiPlaneBuffer.dataBuffer[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; + + 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/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.h b/component/audio/seiren_dec/aac/Exynos_OMX_Aacdec.h new file mode 100644 index 0000000..5e32a2a --- /dev/null +++ b/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/component/audio/seiren_dec/aac/NOTICE b/component/audio/seiren_dec/aac/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/audio/seiren_dec/aac/library_register.c b/component/audio/seiren_dec/aac/library_register.c new file mode 100644 index 0000000..cb7f3f5 --- /dev/null +++ b/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/component/audio/seiren_dec/aac/library_register.h b/component/audio/seiren_dec/aac/library_register.h new file mode 100644 index 0000000..75b0cc2 --- /dev/null +++ b/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/component/audio/seiren_dec/flac/Android.mk b/component/audio/seiren_dec/flac/Android.mk new file mode 100644 index 0000000..e3be0c4 --- /dev/null +++ b/component/audio/seiren_dec/flac/Android.mk @@ -0,0 +1,40 @@ +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_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Adec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + 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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.c b/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.c new file mode 100644 index 0000000..ef6451e --- /dev/null +++ b/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.c @@ -0,0 +1,939 @@ +/* + * + * 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_Basecomponent.h" +#include "Exynos_OMX_Baseport.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 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 sample_rate, channels; + int consumed_size = 0; + sample_rate = channels = 0; + + FunctionIn(); + +#ifdef Seiren_DUMP_TO_FILE + if (pExynosComponent->reInputData == OMX_FALSE) { + fwrite(pInputData->multiPlaneBuffer.dataBuffer[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_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_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->multiPlaneBuffer.dataBuffer[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->multiPlaneBuffer.dataBuffer[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_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_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_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.multiPlaneBuffer.dataBuffer[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; + pExynosPort->portWayType = WAY1_PORT; + + /* 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; + pExynosPort->portWayType = WAY1_PORT; + + /* 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.multiPlaneBuffer.dataBuffer[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; + + 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/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.h b/component/audio/seiren_dec/flac/Exynos_OMX_Flacdec.h new file mode 100644 index 0000000..7f88847 --- /dev/null +++ b/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/component/audio/seiren_dec/flac/NOTICE b/component/audio/seiren_dec/flac/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/audio/seiren_dec/flac/library_register.c b/component/audio/seiren_dec/flac/library_register.c new file mode 100644 index 0000000..e242810 --- /dev/null +++ b/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/component/audio/seiren_dec/flac/library_register.h b/component/audio/seiren_dec/flac/library_register.h new file mode 100644 index 0000000..f9d4e5b --- /dev/null +++ b/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/component/audio/seiren_dec/mp3/Android.mk b/component/audio/seiren_dec/mp3/Android.mk new file mode 100644 index 0000000..73854e2 --- /dev/null +++ b/component/audio/seiren_dec/mp3/Android.mk @@ -0,0 +1,40 @@ +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_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Adec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + 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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.c b/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.c new file mode 100644 index 0000000..f2e926e --- /dev/null +++ b/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.c @@ -0,0 +1,954 @@ +/* + * + * 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_Basecomponent.h" +#include "Exynos_OMX_Baseport.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 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 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->multiPlaneBuffer.dataBuffer[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_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_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; + const int gapless_frames = 529; + const int gapless_bytes = gapless_frames * pMp3Dec->pcmParam.nChannels * sizeof(OMX_S16); + 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->multiPlaneBuffer.dataBuffer[AUDIO_DATA_PLANE], + pt, output_mem_pool.data_size); + } else { + pOutputData->dataLen = 0; + } + +#ifdef Seiren_DUMP_TO_FILE + if (pOutputData->dataLen > 0) + fwrite(pOutputData->multiPlaneBuffer.dataBuffer[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_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_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_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.multiPlaneBuffer.dataBuffer[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; + pExynosPort->portWayType = WAY1_PORT; + + /* 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; + pExynosPort->portWayType = WAY1_PORT; + + /* 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.multiPlaneBuffer.dataBuffer[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/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.h b/component/audio/seiren_dec/mp3/Exynos_OMX_Mp3dec.h new file mode 100644 index 0000000..84f7e10 --- /dev/null +++ b/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/component/audio/seiren_dec/mp3/NOTICE b/component/audio/seiren_dec/mp3/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/audio/seiren_dec/mp3/library_register.c b/component/audio/seiren_dec/mp3/library_register.c new file mode 100644 index 0000000..fe44c0b --- /dev/null +++ b/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/component/audio/seiren_dec/mp3/library_register.h b/component/audio/seiren_dec/mp3/library_register.h new file mode 100644 index 0000000..a750690 --- /dev/null +++ b/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/component/common/Android.mk b/component/common/Android.mk new file mode 100644 index 0000000..5318c83 --- /dev/null +++ b/component/common/Android.mk @@ -0,0 +1,76 @@ +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_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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +ifeq ($(EXYNOS_OMX_SUPPORT_EGL_IMAGE), true) +LOCAL_CFLAGS += -DEGL_IMAGE_SUPPORT +endif + +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_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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +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 + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/common/Exynos_OMX_Basecomponent.c b/component/common/Exynos_OMX_Basecomponent.c new file mode 100644 index 0000000..33735aa --- /dev/null +++ b/component/common/Exynos_OMX_Basecomponent.c @@ -0,0 +1,1672 @@ +/* + * + * 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) + * 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_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" + + +/* 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_TRACE, "nVersionMajor:%d, nVersionMinor:%d", 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; + OMX_S32 countValue = 0; + 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++) { + 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; + } + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].hPortMutex); + pExynosComponent->pExynosPort[i].hPortMutex = NULL; + } + + if (pExynosComponent->bMultiThreadProcess == OMX_FALSE) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pauseEvent); + pExynosComponent->pauseEvent = NULL; + } else { + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pExynosPort[i].pauseEvent); + pExynosComponent->pExynosPort[i].pauseEvent = NULL; + if (pExynosComponent->pExynosPort[i].bufferProcessType & BUFFER_SHARE) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pExynosPort[i].hAllCodecBufferReturnEvent); + pExynosComponent->pExynosPort[i].hAllCodecBufferReturnEvent = NULL; + } + } + } + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SemaphoreTerminate(pExynosComponent->pExynosPort[i].bufferSemID); + pExynosComponent->pExynosPort[i].bufferSemID = NULL; + } + if (pExynosComponent->exynos_codec_componentTerminate != NULL) + pExynosComponent->exynos_codec_componentTerminate(pOMXComponent); + + ret = OMX_ErrorInvalidState; + break; + default: + ret = OMX_ErrorInvalidState; + break; + } + break; + case OMX_StateLoaded: + switch (currentState) { + case OMX_StateIdle: + ret = pExynosComponent->exynos_BufferProcessTerminate(pOMXComponent); + + for (i = 0; i < ALL_PORT_NUM; i++) { + 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; + } + Exynos_OSAL_MutexTerminate(pExynosComponent->pExynosPort[i].hPortMutex); + pExynosComponent->pExynosPort[i].hPortMutex = NULL; + } + if (pExynosComponent->bMultiThreadProcess == OMX_FALSE) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pauseEvent); + pExynosComponent->pauseEvent = NULL; + } else { + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pExynosPort[i].pauseEvent); + pExynosComponent->pExynosPort[i].pauseEvent = NULL; + if (pExynosComponent->pExynosPort[i].bufferProcessType & BUFFER_SHARE) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pExynosPort[i].hAllCodecBufferReturnEvent); + pExynosComponent->pExynosPort[i].hAllCodecBufferReturnEvent = 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_SemaphoreWait(pExynosPort->unloadedResource); + while (Exynos_OSAL_GetElemNum(&pExynosPort->bufferQ) > 0) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message != NULL) + Exynos_OSAL_Free(message); + } + pExynosPort->portDefinition.bPopulated = OMX_FALSE; + } + } + } + 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); +#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_SemaphoreWait(pExynosComponent->pExynosPort[i].loadedResource); + if (pExynosComponent->abendState == OMX_TRUE) { + Exynos_OSAL_SignalSet(pExynosComponent->abendStateEvent); + goto EXIT; + } + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + } + } + } + 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; + } + if (pExynosComponent->bMultiThreadProcess == OMX_FALSE) { + Exynos_OSAL_SignalCreate(&pExynosComponent->pauseEvent); + } else { + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SignalCreate(&pExynosComponent->pExynosPort[i].pauseEvent); + if (pExynosComponent->pExynosPort[i].bufferProcessType & BUFFER_SHARE) + Exynos_OSAL_SignalCreate(&pExynosComponent->pExynosPort[i].hAllCodecBufferReturnEvent); + } + } + 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, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + } + for (i = 0; i < ALL_PORT_NUM; i++) { + if (pExynosComponent->pExynosPort[i].portWayType == WAY1_PORT) { + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->pExynosPort[i].way.port1WayDataBuffer.dataBuffer.bufferMutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + } else if (pExynosComponent->pExynosPort[i].portWayType == WAY2_PORT) { + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.inputDataBuffer.bufferMutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->pExynosPort[i].way.port2WayDataBuffer.outputDataBuffer.bufferMutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + } + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->pExynosPort[i].hPortMutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + ret = pExynosComponent->exynos_BufferProcessCreate(pOMXComponent); + if (ret != OMX_ErrorNone) { +#ifdef TUNNELING_SUPPORT + /* + * if (CHECK_PORT_TUNNELED == OMX_TRUE) thenTunnel Buffer Free + */ +#endif + if (pExynosComponent->bMultiThreadProcess == OMX_FALSE) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pauseEvent); + pExynosComponent->pauseEvent = NULL; + } else { + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pExynosPort[i].pauseEvent); + pExynosComponent->pExynosPort[i].pauseEvent = NULL; + if (pExynosComponent->pExynosPort[i].bufferProcessType & BUFFER_SHARE) { + Exynos_OSAL_SignalTerminate(pExynosComponent->pExynosPort[i].hAllCodecBufferReturnEvent); + pExynosComponent->pExynosPort[i].hAllCodecBufferReturnEvent = NULL; + } + } + } + for (i = 0; i < ALL_PORT_NUM; i++) { + 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; + } + 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->currentState = OMX_StateIdle; + break; + case OMX_StateExecuting: + case OMX_StatePause: + 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; + if (pExynosComponent->bMultiThreadProcess == OMX_FALSE) { + Exynos_OSAL_SignalSet(pExynosComponent->pauseEvent); + } else { + for (i = 0; i < ALL_PORT_NUM; i++) { + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[i].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; + if (pExynosComponent->bMultiThreadProcess == OMX_FALSE) { + Exynos_OSAL_SignalSet(pExynosComponent->pauseEvent); + } else { + 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]:%d OMX_EventCmdComplete", pExynosComponent, __FUNCTION__, __LINE__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, OMX_CommandStateSet, + destState, NULL); + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%p][%s]:%d ret = %d", pExynosComponent, __FUNCTION__, __LINE__, 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: + ret = Exynos_OMX_BufferFlushProcess(pOMXComponent, message->messageParam, OMX_TRUE); + break; + case OMX_CommandPortDisable: + ret = Exynos_OMX_PortDisableProcess(pOMXComponent, message->messageParam); + break; + case OMX_CommandPortEnable: + 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_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 = OMX_StateIdle; + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "to OMX_StateIdle"); + } 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 = OMX_StateLoaded; + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "to OMX_StateLoaded"); + } else if ((destState == OMX_StateIdle) && (pExynosComponent->currentState == OMX_StateExecuting)) { + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + pExynosPort = &(pExynosComponent->pExynosPort[INPUT_PORT_INDEX]); + if ((pExynosPort->portDefinition.bEnabled == OMX_FALSE) && + (pExynosPort->portState == OMX_StateIdle)) { + pExynosPort->exceptionFlag = INVALID_STATE; + Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource); + } + + pExynosPort = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]); + if ((pExynosPort->portDefinition.bEnabled == OMX_FALSE) && + (pExynosPort->portState == OMX_StateIdle)) { + pExynosPort->exceptionFlag = INVALID_STATE; + Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource); + } + + pExynosComponent->transientState = EXYNOS_OMX_TransStateExecutingToIdle; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "to OMX_StateIdle"); + } else if ((destState == OMX_StateExecuting) && (pExynosComponent->currentState == OMX_StateIdle)) { + pExynosComponent->transientState = EXYNOS_OMX_TransStateIdleToExecuting; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "to OMX_StateExecuting"); + } else if (destState == OMX_StateInvalid) { + for (i = 0; i < pExynosComponent->portParam.nPorts; i++) { + pExynosComponent->pExynosPort[i].portState = OMX_StateInvalid; + } + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE Exynos_SetPortFlush(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_S32 portIndex = nParam; + OMX_U16 i = 0, cnt = 0, index = 0; + + + if ((pExynosComponent->currentState == OMX_StateExecuting) || + (pExynosComponent->currentState == OMX_StatePause)) { + if ((portIndex != ALL_PORT_INDEX) && + ((OMX_S32)portIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + /********************* + * need flush event set ????? + **********************/ + cnt = (portIndex == ALL_PORT_INDEX ) ? ALL_PORT_NUM : 1; + for (i = 0; i < cnt; i++) { + if (portIndex == ALL_PORT_INDEX) + index = i; + else + index = portIndex; + pExynosComponent->pExynosPort[index].bIsPortFlushed = OMX_TRUE; + } + } 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 portIndex = nParam; + OMX_U16 i = 0, cnt = 0; + + FunctionIn(); + + if ((portIndex != ALL_PORT_INDEX) && + ((OMX_S32)portIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (portIndex == 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->portState = OMX_StateIdle; + } + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + if (CHECK_PORT_ENABLED(pExynosPort)) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } else { + pExynosPort->portState = OMX_StateIdle; + } + } + 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 portIndex = nParam; + OMX_U16 i = 0, cnt = 0; + + FunctionIn(); + + if ((portIndex != ALL_PORT_INDEX) && + ((OMX_S32)portIndex >= (OMX_S32)pExynosComponent->portParam.nPorts)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (portIndex == 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 = OMX_StateLoaded; + pExynosPort->bIsPortDisabled = OMX_TRUE; + } + } else { + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + pExynosPort->portState = OMX_StateLoaded; + pExynosPort->bIsPortDisabled = OMX_TRUE; + } + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +static OMX_ERRORTYPE Exynos_SetMarkBuffer(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_U32 nParam) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 portIndex = nParam; + OMX_U16 i = 0, cnt = 0; + + + 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_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; + EXYNOS_OMX_MESSAGE *message = 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_TRACE, "Command: OMX_CommandStateSet"); + Exynos_StateSet(pExynosComponent, nParam); + break; + case OMX_CommandFlush : + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Command: OMX_CommandFlush"); + ret = Exynos_SetPortFlush(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + break; + case OMX_CommandPortDisable : + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Command: OMX_CommandPortDisable"); + ret = Exynos_SetPortDisable(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + break; + case OMX_CommandPortEnable : + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Command: OMX_CommandPortEnable"); + ret = Exynos_SetPortEnable(pExynosComponent, nParam); + if (ret != OMX_ErrorNone) + goto EXIT; + break; + case OMX_CommandMarkBuffer : + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Command: OMX_CommandMarkBuffer"); + 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 + +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, "lib version is %s", IS_64BIT_OS? "64bit":"32bit"); + + if (hComponent == NULL) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + ret = Exynos_OSAL_MutexCreate(&pExynosComponent->compMutex); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + ret = Exynos_OSAL_SignalCreate(&pExynosComponent->abendStateEvent); + if (ret != OMX_ErrorNone) { + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + + Exynos_OSAL_QueueCreate(&pExynosComponent->dynamicConfigQ, MAX_QUEUE_ELEMENTS); + + pExynosComponent->bMultiThreadProcess = OMX_FALSE; + + 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); + + Exynos_OMX_CommandQueue(pExynosComponent, 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/component/common/Exynos_OMX_Basecomponent.h b/component/common/Exynos_OMX_Basecomponent.h new file mode 100644 index 0000000..a147e78 --- /dev/null +++ b/component/common/Exynos_OMX_Basecomponent.h @@ -0,0 +1,162 @@ +/* + * + * 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) + * Yunji Kim (yunji.kim@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#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 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; + EXYNOS_QUEUE dynamicConfigQ; + + /* Port */ + OMX_PORT_PARAM_TYPE portParam; + EXYNOS_OMX_BASEPORT *pExynosPort; + + OMX_HANDLETYPE pauseEvent; + + /* 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 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. */ + + /* Check for Old & New OMX Process type switch */ + OMX_BOOL bMultiThreadProcess; + + 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); + +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/component/common/Exynos_OMX_Baseport.c b/component/common/Exynos_OMX_Baseport.c new file mode 100644 index 0000000..2f66b99 --- /dev/null +++ b/component/common/Exynos_OMX_Baseport.c @@ -0,0 +1,1148 @@ +/* + * + * 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) + * 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_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 + + +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, "Trying to return the input buffer without ownership!!"); + } + } + } + +#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->EmptyBufferDone(pOMXComponent, pExynosComponent->callbackData, bufferHeader); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader: %p", pOMXComponent, __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, "Trying to return the output buffer without ownership!!"); + } + } + } + +#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->FillBufferDone(pOMXComponent, pExynosComponent->callbackData, bufferHeader); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bufferHeader: %p", pOMXComponent, __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 portIndex = 0; + EXYNOS_OMX_DATABUFFER *flushPortBuffer[2] = {NULL, NULL}; + 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) + portIndex = i; + else + portIndex = nPortIndex; + + pExynosComponent->exynos_BufferFlush(pOMXComponent, portIndex, bEvent); + } + +EXIT: + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR,"%s : %d", __FUNCTION__, __LINE__); + + 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 portIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 i = 0, cnt = 0; + + FunctionIn(); + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + + if ((pExynosComponent->currentState != OMX_StateLoaded) && (pExynosComponent->currentState != OMX_StateWaitForResources)) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: Port($d) is waiting for loadedResource", __func__, portIndex); + Exynos_OSAL_SemaphoreWait(pExynosPort->loadedResource); + + if (pExynosPort->exceptionFlag == INVALID_STATE) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: Port(%d) is in the INVALID_STATE", __func__, portIndex); + pExynosPort->exceptionFlag = NEED_PORT_DISABLE; + goto EXIT; + } + pExynosPort->portDefinition.bPopulated = OMX_TRUE; + } + pExynosPort->exceptionFlag = GENERAL_STATE; + pExynosPort->portDefinition.bEnabled = OMX_TRUE; + + if ((pExynosComponent->bMultiThreadProcess == OMX_TRUE) && + (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; + OMX_S32 portIndex = 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) + portIndex = i; + else + portIndex = nPortIndex; + + ret = Exynos_OMX_EnablePort(pOMXComponent, portIndex); + if (ret == OMX_ErrorNone) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortEnable, portIndex, NULL); + } + } + +EXIT: + if ((ret != OMX_ErrorNone) && (pOMXComponent != NULL) && (pExynosComponent != 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 portIndex) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_U32 i = 0, elemNum = 0; + EXYNOS_OMX_MESSAGE *message; + + FunctionIn(); + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + + 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); + } + } + pExynosPort->portDefinition.bPopulated = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: Port(%d) is waiting for unloadedResource", __func__, portIndex); + Exynos_OSAL_SemaphoreWait(pExynosPort->unloadedResource); + } + 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 portIndex = 0; + OMX_U32 i = 0, cnt = 0; + EXYNOS_OMX_DATABUFFER *flushPortBuffer[2] = {NULL, NULL}; + + 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) + portIndex = i; + else + portIndex = nPortIndex; + + Exynos_OMX_BufferFlushProcess(pOMXComponent, portIndex, OMX_FALSE); + } + } + + for(i = 0; i < cnt; i++) { + if (nPortIndex == ALL_PORT_INDEX) + portIndex = i; + else + portIndex = nPortIndex; + + ret = Exynos_OMX_DisablePort(pOMXComponent, portIndex); + pExynosComponent->pExynosPort[portIndex].bIsPortDisabled = OMX_FALSE; + if (ret == OMX_ErrorNone) { + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandPortDisable, portIndex, NULL); + } + } + +EXIT: + if ((ret != OMX_ErrorNone) && (pOMXComponent != NULL) && (pExynosComponent != 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)))) { + 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, "input buffer(%p) was already entered!", pBuffer); + } + } + } + + if (bFindBuffer == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "EmptyThisBuffer is failed : %p", 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->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", pOMXComponent, __FUNCTION__, pBuffer, pBuffer->nAllocLen, pBuffer->nFilledLen, pBuffer->nOffset); + + 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)))) { + 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, "output buffer(%p) was already entered!", pBuffer); + } + } + } + + if (bFindBuffer == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "FillThisBuffer is failed : %p", 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->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", pOMXComponent, __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)) || + (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)))) { + 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, "output buffer(%p) is firstly entered!", pBuffer); + } + } + } + + if (bFindBuffer == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "FillThisBufferAgain is failed : %p", 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_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, "OMX_ErrorBadParameter, Line:%d", __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, "OMX_ErrorBadParameter, Line:%d", __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, "OMX_ErrorInsufficientResources, Line:%d", __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, "OMX_ErrorInsufficientResources, Line:%d", __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, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + Exynos_OSAL_Memset(pExynosInputPort->bufferStateAllocate, 0, sizeof(OMX_U32) * MAX_BUFFER_NUM); + + pExynosInputPort->bufferSemID = NULL; + pExynosInputPort->assignedBufferNum = 0; + pExynosInputPort->portState = OMX_StateMax; + pExynosInputPort->bIsPortFlushed = OMX_FALSE; + pExynosInputPort->bIsPortDisabled = OMX_FALSE; + pExynosInputPort->tunneledComponent = NULL; + pExynosInputPort->tunneledPort = 0; + pExynosInputPort->tunnelBufferNum = 0; + pExynosInputPort->bufferSupplier = OMX_BufferSupplyUnspecified; + pExynosInputPort->tunnelFlags = 0; + pExynosInputPort->supportFormat = NULL; + pExynosInputPort->bNeedContigMem = OMX_FALSE; + pExynosInputPort->bDynamicDPBMode = OMX_FALSE; + pExynosInputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + + ret = Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->loadedResource); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + + ret = Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->unloadedResource); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + + 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, "OMX_ErrorInsufficientResources, Line:%d", __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; + +#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) */ + + pExynosOutputPort->extendBufferHeader = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_BUFFERHEADERTYPE) * MAX_BUFFER_NUM); + if (pExynosOutputPort->extendBufferHeader == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __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, "OMX_ErrorInsufficientResources, Line:%d", __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 = OMX_StateMax; + pExynosOutputPort->bIsPortFlushed = OMX_FALSE; + pExynosOutputPort->bIsPortDisabled = OMX_FALSE; + pExynosOutputPort->tunneledComponent = NULL; + pExynosOutputPort->tunneledPort = 0; + pExynosOutputPort->tunnelBufferNum = 0; + pExynosOutputPort->bufferSupplier = OMX_BufferSupplyUnspecified; + pExynosOutputPort->tunnelFlags = 0; + pExynosOutputPort->supportFormat = NULL; + pExynosOutputPort->bNeedContigMem = OMX_FALSE; + pExynosOutputPort->bDynamicDPBMode = OMX_FALSE; + pExynosOutputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + + ret = Exynos_OSAL_SemaphoreCreate(&pExynosOutputPort->loadedResource); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + + ret = Exynos_OSAL_SemaphoreCreate(&pExynosOutputPort->unloadedResource); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + goto EXIT; + } + + 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, "OMX_ErrorInsufficientResources, Line:%d", __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; + +#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_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; + + OMX_S32 countValue = 0; + 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; + + if (pExynosComponent->transientState == EXYNOS_OMX_TransStateLoadedToIdle) { + pExynosComponent->abendState = OMX_TRUE; + for (i = 0; i < ALL_PORT_NUM; i++) { + pExynosPort = &pExynosComponent->pExynosPort[i]; + Exynos_OSAL_SemaphorePost(pExynosPort->loadedResource); + } + Exynos_OSAL_SignalWait(pExynosComponent->abendStateEvent, DEF_MAX_WAIT_TIME); + Exynos_OSAL_SignalReset(pExynosComponent->abendStateEvent); + } + + 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_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_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; + } + + pData->dataLen = 0; + pData->usedDataLen = 0; + pData->remainDataLen = 0; + pData->nFlags = 0; + pData->timeStamp = 0; + pData->pPrivate = NULL; + pData->bufferHeader = NULL; + +EXIT: + return ret; +} + +OMX_ERRORTYPE Exynos_Shared_BufferToData(EXYNOS_OMX_DATABUFFER *pUseBuffer, EXYNOS_OMX_DATA *pData, EXYNOS_OMX_PLANE nPlane) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (nPlane == ONE_PLANE) { + /* Case of Shared Buffer, Only support singlePlaneBuffer */ + pData->multiPlaneBuffer.dataBuffer[0] = pUseBuffer->bufferHeader->pBuffer; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not support plane"); + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + 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: + return ret; +} + +int Exynos_GetPlaneFromPort(EXYNOS_OMX_BASEPORT *pPort) +{ + int ret = 0; + + if (pPort == NULL) + goto EXIT; + + ret = pPort->processData.multiPlaneBuffer.validPlaneNum; + +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.multiPlaneBuffer.validPlaneNum = nPlaneNum; + +EXIT: + return ret; +} + diff --git a/component/common/Exynos_OMX_Baseport.h b/component/common/Exynos_OMX_Baseport.h new file mode 100644 index 0000000..ebd36ef --- /dev/null +++ b/component/common/Exynos_OMX_Baseport.h @@ -0,0 +1,233 @@ +/* + * + * 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) + * HyeYeon Chung (hyeon.chung@samsung.com) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#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 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]; + int 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_DATA +{ + OMX_U32 validPlaneNum; + OMX_PTR dataBuffer[MAX_BUFFER_PLANE]; + int fd[MAX_BUFFER_PLANE]; +} EXYNOS_OMX_MULTIPLANE_DATA; + +typedef struct _EXYNOS_OMX_DATA +{ + EXYNOS_OMX_MULTIPLANE_DATA multiPlaneBuffer; + 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; + OMX_S32 assignedBufferNum; + OMX_STATETYPE portState; + OMX_HANDLETYPE loadedResource; + OMX_HANDLETYPE unloadedResource; + OMX_HANDLETYPE semWaitPortEnable[ALL_WAY_NUM]; + + OMX_BOOL bIsPortFlushed; + OMX_BOOL bIsPortDisabled; + OMX_MARKTYPE markType; + + OMX_CONFIG_RECTTYPE cropRectangle; + + /* Tunnel Info */ + OMX_HANDLETYPE tunneledComponent; + OMX_U32 tunneledPort; + OMX_U32 tunnelBufferNum; + OMX_BUFFERSUPPLIERTYPE bufferSupplier; + OMX_U32 tunnelFlags; + + OMX_COLOR_FORMATTYPE *supportFormat; + OMX_BOOL bIsANBEnabled; + EXYNOS_ANB_TYPE eANBType; + OMX_BOOL bStoreMetaData; + OMX_BOOL bNeedContigMem; + OMX_BOOL bDynamicDPBMode; + 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; + + /* for flush of Shared buffer scheme */ + OMX_HANDLETYPE hAllCodecBufferReturnEvent; + OMX_HANDLETYPE hPortMutex; + EXYNOS_OMX_EXCEPTION_STATE exceptionFlag; + + OMX_PARAM_PORTDEFINITIONTYPE newPortDefinition; + OMX_CONFIG_RECTTYPE newCropRectangle; + OMX_TICKS latestTimeStamp; + +#ifdef PERFORMANCE_DEBUG + /* For performance debug */ + OMX_HANDLETYPE hBufferCount; +#endif +} 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_ResetDataBuffer(EXYNOS_OMX_DATABUFFER *pDataBuffer); +OMX_ERRORTYPE Exynos_ResetCodecData(EXYNOS_OMX_DATA *pData); +OMX_ERRORTYPE Exynos_Shared_BufferToData(EXYNOS_OMX_DATABUFFER *pUseBuffer, EXYNOS_OMX_DATA *pData, EXYNOS_OMX_PLANE nPlane); +OMX_ERRORTYPE Exynos_OMX_InputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE *bufferHeader); +OMX_ERRORTYPE Exynos_OMX_OutputBufferReturn(OMX_COMPONENTTYPE *pOMXComponent, OMX_BUFFERHEADERTYPE *bufferHeader); +int Exynos_GetPlaneFromPort(EXYNOS_OMX_BASEPORT *pPort); +OMX_ERRORTYPE Exynos_SetPlaneFromPort(EXYNOS_OMX_BASEPORT *pPort, int nPlaneNum); +OMX_ERRORTYPE Exynos_SetPlaneToPort(EXYNOS_OMX_BASEPORT *pPort, int nPlaneNum); +OMX_ERRORTYPE Exynos_OMX_FillThisBuffer(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer); +OMX_ERRORTYPE Exynos_OMX_FillThisBufferAgain(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer); + +#ifdef __cplusplus +}; +#endif + + +#endif diff --git a/component/common/Exynos_OMX_Resourcemanager.c b/component/common/Exynos_OMX_Resourcemanager.c new file mode 100644 index 0000000..57883a6 --- /dev/null +++ b/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, "[%s][%s] can't use secure with non-secure", + __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, "[%s][%s] can't use secure with non-secure", + __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, "[%s][%s] has got a resource", __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/component/common/Exynos_OMX_Resourcemanager.h b/component/common/Exynos_OMX_Resourcemanager.h new file mode 100644 index 0000000..fb896a7 --- /dev/null +++ b/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/component/common/NOTICE b/component/common/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/dec/Android.mk b/component/video/dec/Android.mk new file mode 100644 index 0000000..80eb32b --- /dev/null +++ b/component/video/dec/Android.mk @@ -0,0 +1,58 @@ +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_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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/include + +LOCAL_STATIC_LIBRARIES := libExynosVideoApi + +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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +ifeq ($(BOARD_USE_ANB), true) +LOCAL_STATIC_LIBRARIES += libExynosOMX_OSAL +LOCAL_CFLAGS += -DUSE_ANB +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 ($(BOARD_USE_QOS_CTRL), true) +LOCAL_CFLAGS += -DUSE_QOS_CTRL +endif + +ifeq ($(BOARD_USE_STOREMETADATA), true) +LOCAL_CFLAGS += -DUSE_STOREMETADATA +endif + +ifeq ($(EXYNOS_OMX_SUPPORT_TUNNELING), true) +LOCAL_CFLAGS += -DTUNNELING_SUPPORT +endif + +include $(BUILD_STATIC_LIBRARY) diff --git a/component/video/dec/Exynos_OMX_Vdec.c b/component/video/dec/Exynos_OMX_Vdec.c new file mode 100644 index 0000000..6d79937 --- /dev/null +++ b/component/video/dec/Exynos_OMX_Vdec.c @@ -0,0 +1,1887 @@ +/* + * + * 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" + +#ifdef USE_ANB +#include "Exynos_OSAL_Android.h" +#endif + +#include "csc.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VIDEO_DEC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +inline 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]; + + 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; + + switch((int)exynosOutputPort->portDefinition.format.video.eColorFormat) { + case OMX_COLOR_FormatYUV420Planar: + case OMX_COLOR_FormatYUV420SemiPlanar: + case OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace: + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanar: + case OMX_SEC_COLOR_FormatNV12Tiled: + case OMX_SEC_COLOR_FormatYVU420Planar: + case OMX_SEC_COLOR_FormatNV21Linear: + if (width && height) + exynosOutputPort->portDefinition.nBufferSize = (ALIGN(width, 16) * ALIGN(height, 16) * 3) / 2; + break; + default: + if (width && height) + exynosOutputPort->portDefinition.nBufferSize = ALIGN(width, 16) * ALIGN(height, 16) * 2; + break; + } + } + + return; +} + +void Exynos_Output_SetSupportFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + OMX_COLOR_FORMATTYPE ret = OMX_COLOR_FormatUnused; + 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. */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s, custom?:(%d)",pExynosComponent->componentName, IS_CUSTOM_COMPONENT(pExynosComponent->componentName)); + 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; + } + + /* 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_SEC_COLOR_FormatNV21Linear); + if (ret == OMX_TRUE) + pOutputPort->supportFormat[nLastIndex++] = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV21Linear; + + for (i = 0; i < nLastIndex; i++) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Support Format[%d] : 0x%x", i, pOutputPort->supportFormat[i]); + + pOutputPort->supportFormat[nLastIndex] = OMX_COLOR_FormatUnused; + } + + return ; +} + +OMX_ERRORTYPE Exynos_ResolutionUpdate(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 *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pOutputPort->cropRectangle.nTop = pOutputPort->newCropRectangle.nTop; + pOutputPort->cropRectangle.nLeft = pOutputPort->newCropRectangle.nLeft; + pOutputPort->cropRectangle.nWidth = pOutputPort->newCropRectangle.nWidth; + pOutputPort->cropRectangle.nHeight = pOutputPort->newCropRectangle.nHeight; + + pInputPort->portDefinition.format.video.nFrameWidth = pInputPort->newPortDefinition.format.video.nFrameWidth; + pInputPort->portDefinition.format.video.nFrameHeight = pInputPort->newPortDefinition.format.video.nFrameHeight; + pInputPort->portDefinition.format.video.nStride = pInputPort->newPortDefinition.format.video.nStride; + pInputPort->portDefinition.format.video.nSliceHeight = pInputPort->newPortDefinition.format.video.nSliceHeight; + + pOutputPort->portDefinition.nBufferCountActual = pOutputPort->newPortDefinition.nBufferCountActual; + pOutputPort->portDefinition.nBufferCountMin = pOutputPort->newPortDefinition.nBufferCountMin; + + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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); + + return ret; +} + +void Exynos_Free_CodecBuffers( + 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; + 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_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, "Failed to Alloc codec buffer"); + 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, "Failed to Alloc plane"); + 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_TRACE, "PORT[%d]: pMFCCodecBuffer[%d]->pVirAddr[%d]: 0x%x", nPortIndex, i, j, ppCodecBuffer[i]->pVirAddr[j]); + } + + ppCodecBuffer[i]->dataSize = 0; + } + + 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, "OMX_ErrorBadParameter : pExynosComponent(%p), nIndex(%p)", pExynosComponent, nIndex); + return; + } + + /* 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_ERROR, "Can not find empty slot of timestamp. Timestamp slot is full."); + + pExynosComponent->timeStamp[*nIndex] = timeStamp; + pExynosComponent->nFlags[*nIndex] = nFlags; + pExynosComponent->bTimestampSlotUsed[*nIndex] = OMX_TRUE; + + 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, "OMX_ErrorBadParameter : pExynosComponent(%p), sCurrentTimestamp(%p)", pExynosComponent, sCurrentTimestamp); + return; + } + + 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_ESSENTIAL, "[%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))) { + 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 old timestamp index for I-frame sync", pExynosComponent, __FUNCTION__); + } + } + } + + if (sCurrentTimestamp->timeStamp == DEFAULT_TIMESTAMP_VAL) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "the index of frame(%d) about I-frame is wrong", nFrameIndex); + + sCurrentTimestamp->nFlags |= OMX_BUFFERFLAG_SYNCFRAME; + } + + if (eFrameType & VIDEO_FRAME_CORRUPT) + sCurrentTimestamp->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + if (sCurrentTimestamp->timeStamp != DEFAULT_TIMESTAMP_VAL) { + if (pExynosOutputPort->latestTimeStamp <= sCurrentTimestamp->timeStamp) { + pExynosOutputPort->latestTimeStamp = sCurrentTimestamp->timeStamp; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "sCurrentTimestamp(%lld) is smaller than latestTimeStamp(%lld), uses latestTimeStamp", + sCurrentTimestamp->timeStamp, pExynosOutputPort->latestTimeStamp); + sCurrentTimestamp->timeStamp = pExynosOutputPort->latestTimeStamp; + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "uses latestTimeStamp(%lld)", pExynosOutputPort->latestTimeStamp); + sCurrentTimestamp->timeStamp = pExynosOutputPort->latestTimeStamp; + } + + 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 == OMX_StateIdle) && + (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]; + + /* 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; + 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_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 | BUFFER_ANBSHARE; +#ifdef USE_ANB + pOutputPort->bIsANBEnabled = OMX_FALSE; +#ifdef USE_STOREMETADATA + pOutputPort->bStoreMetaData = OMX_FALSE; +#endif +#endif + pOutputPort->portWayType = WAY2_PORT; + pOutputPort->latestTimeStamp = DEFAULT_TIMESTAMP_VAL; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(OMX_COLOR_FormatYUV420Planar, pOutputPort->ePlaneType)); + + pOutputPort->cropRectangle.nTop = 0; + pOutputPort->cropRectangle.nLeft = 0; + pOutputPort->cropRectangle.nWidth = DEFAULT_FRAME_WIDTH; + pOutputPort->cropRectangle.nHeight = DEFAULT_FRAME_HEIGHT; + + 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->multiPlaneBuffer.dataBuffer[i] = pCodecBuffer->pVirAddr[i]; + pData->multiPlaneBuffer.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 *exynosOMXInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOMXOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + 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_SignalWait(pExynosComponent->pExynosPort[nPortIndex].pauseEvent, DEF_MAX_WAIT_TIME); + 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 *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; + OMX_U32 copySize = 0; + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = exynosOutputPort->portDefinition.format.video.eColorFormat; + + FunctionIn(); + + void *pOutputBuf = (void *)outputUseBuffer->bufferHeader->pBuffer; + void *pSrcBuf[MAX_BUFFER_PLANE] = {NULL, }; + void *pYUVBuf[MAX_BUFFER_PLANE] = {NULL, }; + + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + + OMX_U32 nFrameWidth = 0, nFrameHeight = 0; + OMX_U32 nImageWidth = 0, nImageHeight = 0, stride = 0; + + CSC_MEMTYPE csc_memType = CSC_MEMORY_USERPTR; + CSC_METHOD csc_method = CSC_METHOD_SW; + CSC_ERRORCODE cscRet = CSC_ErrorNone; + unsigned int srcCacheable = 1, dstCacheable = 1; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)dstOutputData->extInfo; + + nFrameWidth = pBufferInfo->imageStride; + nFrameHeight = exynosOutputPort->portDefinition.format.video.nSliceHeight; + + /* If crop info is used, width & height will be info about frame */ + nImageWidth = pBufferInfo->imageWidth; + nImageHeight = pBufferInfo->imageHeight; + + pSrcBuf[0] = dstOutputData->multiPlaneBuffer.dataBuffer[0]; + pSrcBuf[1] = dstOutputData->multiPlaneBuffer.dataBuffer[1]; + pSrcBuf[2] = dstOutputData->multiPlaneBuffer.dataBuffer[2]; + + if (exynosOutputPort->ePlaneType == PLANE_SINGLE) { /* from H/W. only Y addr is valid */ + /* get a count of color plane */ + int nPlaneCnt = Exynos_OSAL_GetPlaneCount(pBufferInfo->ColorFormat, PLANE_MULTIPLE); + + if (nPlaneCnt == 2) { /* Semi-Planar : interleaved */ + pSrcBuf[1] = (void *)(((char *)pSrcBuf[0]) + + ((pVideoDec->b10bitData == OMX_TRUE)? GET_10B_UV_OFFSET(nImageWidth, nImageHeight):GET_UV_OFFSET(nImageWidth, nImageHeight))); + } else if (nPlaneCnt == 3) { /* Planar */ + pSrcBuf[1] = (void *)(((char *)pSrcBuf[0]) + + ((pVideoDec->b10bitData == OMX_TRUE)? GET_10B_CB_OFFSET(nImageWidth, nImageHeight):GET_CB_OFFSET(nImageWidth, nImageHeight))); + pSrcBuf[2] = (void *)(((char *)pSrcBuf[0]) + + ((pVideoDec->b10bitData == OMX_TRUE)? GET_10B_CR_OFFSET(nImageWidth, nImageHeight):GET_CR_OFFSET(nImageWidth, nImageHeight))); + } + } + + /* calculate each plane info for the application */ + Exynos_OSAL_GetPlaneSize(eColorFormat, PLANE_MULTIPLE, nImageWidth, nImageHeight, nDataLen, nAllocLen); + + pYUVBuf[0] = (void *)((char *)pOutputBuf); + pYUVBuf[1] = (void *)((char *)pOutputBuf + nDataLen[0]); + pYUVBuf[2] = (void *)((char *)pOutputBuf + nDataLen[0] + nDataLen[1]); + +#ifdef USE_ANB + if (exynosOutputPort->bIsANBEnabled == OMX_TRUE) { + if (OMX_ErrorNone != Exynos_OSAL_LockANBHandle(pOutputBuf, nImageWidth, nImageHeight, eColorFormat, &stride, planes)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OSAL_LockANBHandle() failed", __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + + nImageWidth = stride; + outputUseBuffer->dataLen = sizeof(void *); + + pYUVBuf[0] = (void *)planes[0].addr; + pYUVBuf[1] = (void *)planes[1].addr; + pYUVBuf[2] = (void *)planes[2].addr; + } +#ifdef USE_STOREMETADATA + else if (exynosOutputPort->bStoreMetaData == OMX_TRUE) { + if (OMX_ErrorNone != Exynos_OSAL_LockMetaData(pOutputBuf, nImageWidth, nImageHeight, eColorFormat, &stride, planes)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OSAL_LockMetaData() failed", __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + + nImageWidth = stride; + outputUseBuffer->dataLen = sizeof(void *); + + pYUVBuf[0] = (void *)planes[0].addr; + pYUVBuf[1] = (void *)planes[1].addr; + pYUVBuf[2] = (void *)planes[2].addr; + } +#endif +#endif + + if (pVideoDec->exynos_codec_checkFormatSupport(pExynosComponent, eColorFormat) == OMX_TRUE) { + csc_memType = CSC_MEMORY_MFC; /* to remove stride value */ + if (pVideoDec->csc_set_format == OMX_FALSE) { + csc_set_method(pVideoDec->csc_handle, CSC_METHOD_SW); + csc_set_src_format( + pVideoDec->csc_handle, /* handle */ + nFrameWidth, /* width */ + nFrameHeight, /* height */ + 0, /* crop_left */ + 0, /* crop_right */ + nImageWidth, /* crop_width */ + nImageHeight, /* crop_height */ + Exynos_OSAL_OMX2HALPixelFormat( + pBufferInfo->ColorFormat, exynosOutputPort->ePlaneType), /* color_format */ + srcCacheable); /* cacheable */ + } + } else { + csc_get_method(pVideoDec->csc_handle, &csc_method); + if (csc_method == CSC_METHOD_HW) { + srcCacheable = 0; + dstCacheable = 0; + } + +#ifdef USE_DMA_BUF + if (csc_method == CSC_METHOD_HW) { + csc_memType = CSC_MEMORY_DMABUF; + + pSrcBuf[0] = INT_TO_PTR(dstOutputData->multiPlaneBuffer.fd[0]); + pSrcBuf[1] = INT_TO_PTR(dstOutputData->multiPlaneBuffer.fd[1]); + pSrcBuf[2] = INT_TO_PTR(dstOutputData->multiPlaneBuffer.fd[2]); + +#ifdef USE_ANB + if ((exynosOutputPort->bIsANBEnabled == OMX_TRUE) || + (exynosOutputPort->bStoreMetaData == OMX_TRUE)) { + pYUVBuf[0] = INT_TO_PTR(planes[0].fd); + pYUVBuf[1] = INT_TO_PTR(planes[1].fd); + pYUVBuf[2] = INT_TO_PTR(planes[2].fd); + } else { + pYUVBuf[0] = INT_TO_PTR(Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, pOutputBuf)); + pYUVBuf[1] = NULL; + pYUVBuf[2] = NULL; + } +#else + pYUVBuf[0] = INT_TO_PTR(Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, pOutputBuf)); + pYUVBuf[1] = NULL; + pYUVBuf[2] = NULL; +#endif + } +#endif + + if (pVideoDec->csc_set_format == OMX_FALSE) { + csc_set_src_format( + pVideoDec->csc_handle, /* handle */ + nFrameWidth, /* width */ + nFrameHeight, /* height */ + 0, /* crop_left */ + 0, /* crop_right */ + nImageWidth, /* crop_width */ + nImageHeight, /* crop_height */ + Exynos_OSAL_OMX2HALPixelFormat( + pBufferInfo->ColorFormat, exynosOutputPort->ePlaneType), /* color_format */ + srcCacheable); /* cacheable */ + } + } + + if (pVideoDec->csc_set_format == OMX_FALSE) { + unsigned int pixelFormat = Exynos_OSAL_OMX2HALPixelFormat(eColorFormat, PLANE_SINGLE_USER); + + if ((IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) && + (nFrameWidth != nImageWidth) && + (csc_method == CSC_METHOD_HW)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "H/W CSC isn't supported by the constraint (w:%d/h:%d)", nImageWidth, nImageHeight); + ret = OMX_FALSE; + goto EXIT; + } + +#ifdef USE_ANB + if (exynosOutputPort->bIsANBEnabled == OMX_TRUE) + pixelFormat = Exynos_OSAL_OMX2HALPixelFormat(eColorFormat, exynosOutputPort->ePlaneType); +#ifdef USE_STOREMETADATA + else if (exynosOutputPort->bStoreMetaData == OMX_TRUE) + pixelFormat = Exynos_OSAL_OMX2HALPixelFormat(eColorFormat, exynosOutputPort->ePlaneType); +#endif +#endif + + csc_set_dst_format( + pVideoDec->csc_handle, /* handle */ + nImageWidth, /* width */ + nImageHeight, /* height */ + 0, /* crop_left */ + 0, /* crop_right */ + nImageWidth, /* crop_width */ + nImageHeight, /* crop_height */ + pixelFormat, /* color_format */ + dstCacheable); /* 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; + } + + csc_set_src_buffer( + pVideoDec->csc_handle, /* handle */ + pSrcBuf, + csc_memType); /* YUV Addr or FD */ + csc_set_dst_buffer( + pVideoDec->csc_handle, /* handle */ + pYUVBuf, + csc_memType); /* YUV Addr or FD */ + cscRet = csc_convert(pVideoDec->csc_handle); + if (cscRet != CSC_ErrorNone) + ret = OMX_FALSE; + else + ret = OMX_TRUE; + +#ifdef USE_ANB + if (exynosOutputPort->bIsANBEnabled == OMX_TRUE) + Exynos_OSAL_UnlockANBHandle(pOutputBuf); +#ifdef USE_STOREMETADATA + else if (exynosOutputPort->bStoreMetaData == OMX_TRUE) + Exynos_OSAL_UnlockMetaData(pOutputBuf); +#endif +#endif + +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_U32 copySize = 0; + OMX_BYTE checkInputStream = NULL; + OMX_U32 checkInputStreamLen = 0; + + FunctionIn(); + + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + if ((srcInputData->multiPlaneBuffer.dataBuffer[0] == NULL) || + (srcInputData->pPrivate == NULL)) { + ret = OMX_FALSE; + goto EXIT; + } + } + + if (inputUseBuffer->dataValid == OMX_TRUE) { + if (exynosInputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_Shared_BufferToData(inputUseBuffer, srcInputData, ONE_PLANE); + + if (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) { + int ionFD = -1; + OMX_PTR dataBuffer = NULL; + + /* caution : data loss */ + ionFD = PTR_TO_INT(srcInputData->multiPlaneBuffer.dataBuffer[0]); + + dataBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoDec->hSharedMemory, ionFD); + if (dataBuffer == NULL) { + ret = OMX_FALSE; + goto EXIT; + } + + srcInputData->multiPlaneBuffer.fd[0] = ionFD; + srcInputData->multiPlaneBuffer.dataBuffer[0] = dataBuffer; + } else { + srcInputData->multiPlaneBuffer.fd[0] = + Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, + srcInputData->multiPlaneBuffer.dataBuffer[0]); + } + + /* reset dataBuffer */ + Exynos_ResetDataBuffer(inputUseBuffer); + } else if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + checkInputStream = inputUseBuffer->bufferHeader->pBuffer + inputUseBuffer->usedDataLen; + checkInputStreamLen = inputUseBuffer->remainDataLen; + + pExynosComponent->bUseFlagEOF = OMX_TRUE; + + copySize = checkInputStreamLen; + + if (((srcInputData->allocSize) - (srcInputData->dataLen)) >= copySize) { + if (copySize > 0) { + Exynos_OSAL_Memcpy((OMX_PTR)((char *)srcInputData->multiPlaneBuffer.dataBuffer[0] + srcInputData->dataLen), + checkInputStream, 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; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "input codec buffer is smaller than decoded input data size Out Length"); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + ret = OMX_FALSE; + } + + Exynos_InputBufferReturn(pOMXComponent, inputUseBuffer); + } + + if ((srcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] bSaveFlagEOS : OMX_TRUE", pExynosComponent, __FUNCTION__); + if (srcInputData->dataLen != 0) + pExynosComponent->bBehaviorEOS = OMX_TRUE; + } + + 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, srcInputData->timeStamp / 1E6); + } + + ret = OMX_TRUE; + } + +EXIT: + + 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; + OMX_U32 copySize = 0; + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + + FunctionIn(); + + if (exynosOutputPort->bufferProcessType & BUFFER_SHARE) { +#ifdef USE_ANB + if ((exynosOutputPort->bIsANBEnabled == OMX_FALSE) && + (exynosOutputPort->bStoreMetaData == OMX_FALSE)) { + if (Exynos_Shared_DataToBuffer(dstOutputData, outputUseBuffer) == OMX_ErrorNone) + outputUseBuffer->dataValid = OMX_TRUE; + } else { + if (Exynos_Shared_DataToANBBuffer(dstOutputData, outputUseBuffer, exynosOutputPort) == OMX_ErrorNone) { + outputUseBuffer->dataValid = OMX_TRUE; + } else { + ret = OMX_FALSE; + goto EXIT; + } + } +#else + if (Exynos_Shared_DataToBuffer(dstOutputData, outputUseBuffer) == OMX_ErrorNone) + outputUseBuffer->dataValid = OMX_TRUE; +#endif + } + + if (outputUseBuffer->dataValid == OMX_TRUE) { + if ((pExynosComponent->checkTimeStamp.needCheckStartTimeStamp == OMX_TRUE) && + ((dstOutputData->nFlags & OMX_BUFFERFLAG_EOS) != OMX_BUFFERFLAG_EOS)) { + if ((pExynosComponent->checkTimeStamp.startTimeStamp == dstOutputData->timeStamp) && + (pExynosComponent->checkTimeStamp.nStartFlags == + (dstOutputData->nFlags & ~(OMX_BUFFERFLAG_SYNCFRAME | OMX_BUFFERFLAG_DATACORRUPT)))) { + 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", pExynosComponent, __FUNCTION__); + 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 timestame after seeking", pExynosComponent, __FUNCTION__); + goto EXIT; + } + + if (exynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((dstOutputData->remainDataLen <= (outputUseBuffer->allocSize - outputUseBuffer->dataLen)) && + (!CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + copySize = dstOutputData->remainDataLen; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE,"copySize: %d", copySize); + + outputUseBuffer->dataLen += copySize; + outputUseBuffer->remainDataLen += copySize; + outputUseBuffer->nFlags = dstOutputData->nFlags; + outputUseBuffer->timeStamp = dstOutputData->timeStamp; + + if (outputUseBuffer->remainDataLen > 0) { + ret = Exynos_CSC_OutputData(pOMXComponent, dstOutputData); + } else { + ret = OMX_TRUE; + } + + if (ret == OMX_TRUE) { + if ((outputUseBuffer->remainDataLen > 0) || + ((outputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) || + (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer); + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "csc_convert Error"); + 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, "output buffer is smaller than decoded data size Out Length"); + 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) == 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_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; + OMX_BOOL bValidCodecData = 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_ENABLED(exynosInputPort))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_SemaphoreWait(exynosInputPort->semWaitPortEnable[INPUT_WAY_INDEX]); + continue; + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) && + (!pVideoDec->bExitBufferProcessThread)) { + Exynos_OSAL_SleepMillisec(0); + + if ((CHECK_PORT_BEING_FLUSHED(exynosInputPort)) || + ((exynosOutputPort->exceptionFlag != GENERAL_STATE) && + (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorInputDataDecodeYet) || + ((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorNoneSrcSetupFinish))) || + (exynosOutputPort->exceptionFlag == INVALID_STATE)) + break; + if (exynosInputPort->portState != OMX_StateIdle) + break; + + Exynos_OSAL_MutexLock(srcInputUseBuffer->bufferMutex); + if ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorInputDataDecodeYet) { + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + OMX_PTR codecBuffer; + if ((pSrcInputData->multiPlaneBuffer.dataBuffer[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)) { + 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_ENABLED(exynosInputPort))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_SemaphoreWait(exynosInputPort->semWaitPortEnable[OUTPUT_WAY_INDEX]); + 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(&srcOutputData, srcOutputUseBuffer); + 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_ENABLED(exynosOutputPort))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_SemaphoreWait(exynosOutputPort->semWaitPortEnable[INPUT_WAY_INDEX]); + continue; + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) && + (!pVideoDec->bExitBufferProcessThread)) { + Exynos_OSAL_SleepMillisec(0); + + if ((CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) || + (!CHECK_PORT_POPULATED(exynosOutputPort)) || + (exynosOutputPort->exceptionFlag != GENERAL_STATE)) + break; + if (exynosOutputPort->portState != OMX_StateIdle) + break; + + Exynos_OSAL_MutexLock(dstInputUseBuffer->bufferMutex); + if ((EXYNOS_OMX_ERRORTYPE)ret != OMX_ErrorOutputBufferUseYet) { + if (exynosOutputPort->bufferProcessType & BUFFER_COPY) { + 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; + } +#ifdef USE_ANB + if ((exynosOutputPort->bIsANBEnabled == OMX_FALSE) && + (exynosOutputPort->bStoreMetaData == OMX_FALSE)) { + Exynos_Shared_BufferToData(dstInputUseBuffer, &dstInputData, TWO_PLANE); + } else { + ret = Exynos_Shared_ANBBufferToData(dstInputUseBuffer, &dstInputData, exynosOutputPort); + if (ret != OMX_ErrorNone) { + dstInputUseBuffer->dataValid = OMX_FALSE; + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + + OMX_PTR pANBHandle = NULL; +#ifdef USE_STOREMETADATA + if (exynosOutputPort->bStoreMetaData == OMX_TRUE) { + OMX_PTR ppBuf[MAX_BUFFER_PLANE] = {NULL, NULL, NULL}; + + ret = Exynos_OSAL_GetInfoFromMetaData(dstInputData.bufferHeader->pBuffer, ppBuf); + if (ret != OMX_ErrorNone) { + /* actually, the error will be happen at ANBBufferToData, if metadata is invalid. */ + dstInputUseBuffer->dataValid = OMX_FALSE; + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + + pANBHandle = ppBuf[0]; + } else +#endif + { + pANBHandle = dstInputData.bufferHeader->pBuffer; + } + + Exynos_OSAL_RefANB_Increase(pVideoDec->hRefHandle, pANBHandle, exynosOutputPort->ePlaneType); + } +#else + Exynos_Shared_BufferToData(dstInputUseBuffer, &dstInputData, TWO_PLANE); +#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) { + 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_ENABLED(exynosOutputPort))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_SemaphoreWait(exynosOutputPort->semWaitPortEnable[OUTPUT_WAY_INDEX]); + 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) { + 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_ANB + if (exynosOutputPort->bufferProcessType == BUFFER_SHARE) { + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + int i; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + for (i = 0; i < VIDEO_BUFFER_MAX_NUM; i++) { + if (pBufferInfo->PDSB.dpbFD[i].fd > -1) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "decRefCnt-FD:%d", pBufferInfo->PDSB.dpbFD[i].fd); + Exynos_OSAL_RefANB_Decrease(pVideoDec->hRefHandle, pBufferInfo->PDSB.dpbFD[i].fd); + } else { + break; + } + } + } +#endif + Exynos_Postprocess_OutputData(pOMXComponent, pDstOutputData); + } + + if (exynosOutputPort->bufferProcessType & BUFFER_COPY) { + 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; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = 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; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + 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; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = 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; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + 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; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = 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; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + 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; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = 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; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + 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; + unsigned int i = 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_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); + + pVideoDec->exynos_codec_stop(pOMXComponent, INPUT_PORT_INDEX); + pVideoDec->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(pVideoDec->hSrcOutputThread); + pVideoDec->hSrcOutputThread = NULL; + Exynos_OSAL_Set_SemaphoreCount(pExynosComponent->pExynosPort[INPUT_PORT_INDEX].semWaitPortEnable[OUTPUT_WAY_INDEX], 0); + + pVideoDec->exynos_codec_stop(pOMXComponent, OUTPUT_PORT_INDEX); + pVideoDec->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(pVideoDec->hDstOutputThread); + pVideoDec->hDstOutputThread = NULL; + Exynos_OSAL_Set_SemaphoreCount(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].semWaitPortEnable[OUTPUT_WAY_INDEX], 0); + + 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; + + 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; + + pVideoDec = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_VIDEODEC_COMPONENT)); + if (pVideoDec == NULL) { + Exynos_OMX_Port_Destructor(pOMXComponent); + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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->b10bitData = OMX_FALSE; + pVideoDec->bQosChanged = OMX_FALSE; + pVideoDec->nQosRatio = 0; + pExynosComponent->hComponentHandle = (OMX_HANDLETYPE)pVideoDec; + + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + pExynosComponent->bMultiThreadProcess = OMX_TRUE; + + /* 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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)); + Exynos_OSAL_Memset(((char *)pExynosPort->processData.extInfo), 0, sizeof(DECODE_CODEC_EXTRA_BUFFERINFO)); + + int i = 0; + DECODE_CODEC_EXTRA_BUFFERINFO *pBufferInfo = NULL; + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)(pExynosPort->processData.extInfo); + for (i = 0; i < VIDEO_BUFFER_MAX_NUM; i++) { + pBufferInfo->PDSB.dpbFD[i].fd = -1; + pBufferInfo->PDSB.dpbFD[i].fd1 = -1; + pBufferInfo->PDSB.dpbFD[i].fd2 = -1; + } + + 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; + +#ifdef USE_ANB + pVideoDec->hRefHandle = Exynos_OSAL_RefANB_Create(); +#endif + +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) { + 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; + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + +#ifdef USE_ANB + Exynos_OSAL_RefANB_Terminate(pVideoDec->hRefHandle); +#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/component/video/dec/Exynos_OMX_Vdec.h b/component/video/dec/Exynos_OMX_Vdec.h new file mode 100644 index 0000000..6a7f3cb --- /dev/null +++ b/component/video/dec/Exynos_OMX_Vdec.h @@ -0,0 +1,199 @@ +/* + * + * 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 "ExynosVideoApi.h" + +#define MAX_VIDEO_INPUTBUFFER_NUM 5 +#define MIN_VIDEO_INPUTBUFFER_NUM 1 +#define MAX_VIDEO_OUTPUTBUFFER_NUM 2 + +#define DEFAULT_FRAME_WIDTH 176 +#define DEFAULT_FRAME_HEIGHT 144 + +#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 +#define DEFAULT_MFC_INPUT_BUFFER_SIZE MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2 + +/* input buffer size for custom component */ +#define CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE (1024 * 1024 * 3 / 2) /* 1.5MB */ +#define CUSTOM_FHD_VIDEO_INPUT_BUFFER_SIZE (1920 * 1080 * 3 / 2) +#define CUSTOM_UHD_VIDEO_INPUT_BUFFER_SIZE (1024 * 1024 * 6) /* 6MB */ + +#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 2 /* I420P, NV12 */ +#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 */ + int fd[MAX_BUFFER_PLANE]; /* buffer FD */ + int dataSize; /* total data length */ +} CODEC_DEC_BUFFER; + +typedef struct _DECODE_CODEC_EXTRA_BUFFERINFO +{ + /* For Decode Output */ + OMX_U32 imageWidth; + OMX_U32 imageHeight; + OMX_U32 imageStride; + OMX_COLOR_FORMATTYPE ColorFormat; + PrivateDataShareBuffer PDSB; +} 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 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 */ + OMX_BOOL b10bitData; /* true: 10bit decoding, false: 8bit decoding */ + OMX_BOOL bQosChanged; + OMX_U32 nQosRatio; + 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 Ref Cnt handling about graphic buffer */ + OMX_HANDLETYPE hRefHandle; + + /* CSC handle */ + OMX_PTR csc_handle; + OMX_U32 csc_set_format; + + 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); + +#if 0 /* unused code */ + int (*exynos_checkInputFrame) (OMX_U8 *pInputStream, OMX_U32 buffSize, OMX_U32 flag, + OMX_BOOL bPreviousFrameEOF, OMX_BOOL *pbEndOfFrame); + OMX_ERRORTYPE (*exynos_codec_getCodecInputPrivateData) (OMX_PTR codecBuffer, OMX_PTR *addr, OMX_U32 *size); +#endif + 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); +} EXYNOS_OMX_VIDEODEC_COMPONENT; + +#ifdef __cplusplus +extern "C" { +#endif + +inline void Exynos_UpdateFrameSize(OMX_COMPONENTTYPE *pOMXComponent); +void Exynos_Output_SetSupportFormat(EXYNOS_OMX_BASECOMPONENT *pExynosComponent); +OMX_ERRORTYPE Exynos_ResolutionUpdate(OMX_COMPONENTTYPE *pOMXComponent); +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/component/video/dec/Exynos_OMX_VdecControl.c b/component/video/dec/Exynos_OMX_VdecControl.c new file mode 100644 index 0000000..8fd33da --- /dev/null +++ b/component/video/dec/Exynos_OMX_VdecControl.c @@ -0,0 +1,2057 @@ +/* + * + * 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) + * @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_Thread.h" +#include "Exynos_OSAL_Semaphore.h" +#include "Exynos_OSAL_Mutex.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_SharedMemory.h" + +#ifdef USE_ANB +#include "Exynos_OSAL_Android.h" +#endif + +#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) { + 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 (pExynosPort->portState != OMX_StateIdle) { + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + +#ifdef USE_ANB + if (pExynosPort->bIsANBEnabled == OMX_TRUE) { + OMX_U32 nAllocLen; + OMX_U32 width, height; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "useAndroidNativeBuffer2"); + pExynosPort->eANBType = NATIVE_GRAPHIC_BUFFER2; + + width = pExynosPort->portDefinition.format.video.nFrameWidth; + height = pExynosPort->portDefinition.format.video.nFrameHeight; + + nAllocLen = ALIGN(width, 16) * ALIGN(height, 16) + \ + ALIGN(width / 2, 16) * ALIGN(height / 2, 16) * 2; + + ret = useAndroidNativeBuffer(pExynosPort, ppBufferHdr, nPortIndex, pAppPrivate, nAllocLen, pBuffer); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: useAndroidNativeBuffer2 is failed: err=0x%x", __func__, ret); + goto EXIT; + } + + ret = OMX_ErrorNone; + goto EXIT; + } else +#endif + { + 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_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + OMX_U8 *temp_buffer = NULL; + int temp_buffer_fd = -1; + OMX_U32 i = 0; + MEMORY_TYPE mem_type = NORMAL_MEMORY; + + 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; + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } +/* + if (pExynosPort->portState != OMX_StateIdle ) { + 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; + + temp_buffer = Exynos_OSAL_SharedMemory_Alloc(pVideoDec->hSharedMemory, nSizeBytes, mem_type); + if (temp_buffer == NULL) { + 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_SharedMemory_Free(pVideoDec->hSharedMemory, temp_buffer); + 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) + temp_bufferHeader->pBuffer = INT_TO_PTR(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++; + 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_SharedMemory_Free(pVideoDec->hSharedMemory, 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_VIDEODEC_COMPONENT *pVideoDec = 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; + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (((pExynosPort->portState != OMX_StateLoaded) && + (pExynosPort->portState != OMX_StateInvalid)) && + (pExynosPort->portDefinition.bEnabled != OMX_FALSE)) { + (*(pExynosComponent->pCallbacks->EventHandler)) (pOMXComponent, + pExynosComponent->callbackData, + (OMX_U32)OMX_EventError, + (OMX_U32)OMX_ErrorPortUnpopulated, + nPortIndex, NULL); + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + for (i = 0; i < /*pExynosPort->portDefinition.nBufferCountActual*/MAX_BUFFER_NUM; 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) { + if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) && + (nPortIndex == INPUT_PORT_INDEX)) { + /* caution : data loss */ + int ionFD = PTR_TO_INT(pExynosPort->extendBufferHeader[i].OMXBufferHeader->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, 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; +} + +#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; + + FunctionIn(); + + *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); + } + +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_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_BUFFERHEADERTYPE *bufferHeader = NULL; + EXYNOS_OMX_DATABUFFER *pDataPortBuffer[2] = {NULL, NULL}; + EXYNOS_OMX_MESSAGE *message = NULL; + OMX_U32 flushNum = 0; + OMX_S32 semValue = 0; + int i = 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) && (message->messageType != 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 (pExynosComponent->bMultiThreadProcess == OMX_TRUE) { + 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) { +#ifdef USE_ANB + if (pExynosPort->bIsANBEnabled == OMX_TRUE) + Exynos_OSAL_UnlockANBHandle(pExynosPort->processData.bufferHeader->pBuffer); +#ifdef USE_STOREMETADATA + else if (pExynosPort->bStoreMetaData == OMX_TRUE) + Exynos_OSAL_UnlockMetaData(pExynosPort->processData.bufferHeader->pBuffer); +#endif +#endif + 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) { +#ifdef USE_ANB + if (pExynosPort->bIsANBEnabled == OMX_TRUE) + Exynos_OSAL_UnlockANBHandle(pExynosPort->extendBufferHeader[i].OMXBufferHeader->pBuffer); +#ifdef USE_STOREMETADATA + else if (pExynosPort->bStoreMetaData == OMX_TRUE) + Exynos_OSAL_UnlockMetaData(pExynosPort->extendBufferHeader[i].OMXBufferHeader->pBuffer); +#endif +#endif + Exynos_OMX_OutputBufferReturn(pOMXComponent, pExynosPort->extendBufferHeader[i].OMXBufferHeader); + } else if (portIndex == INPUT_PORT_INDEX) { + Exynos_OMX_InputBufferReturn(pOMXComponent, pExynosPort->extendBufferHeader[i].OMXBufferHeader); + } + } + } + } + } else { + Exynos_ResetCodecData(&pExynosPort->processData); + } + +#ifdef USE_ANB + if ((pExynosPort->bufferProcessType == BUFFER_SHARE) && + (portIndex == OUTPUT_PORT_INDEX)) + Exynos_OSAL_RefANB_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 (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->multiPlaneBuffer.dataBuffer[0] == 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); + switch ((int)ret) { + case OMX_ErrorNone: + { + bSubmitCSD = OMX_TRUE; + } + break; + 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_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; + } + } else { + /* pre-processing is failed : 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); + } + + /* 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}; + 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; + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE,"OMX_CommandFlush start, port:%d", nPortIndex); + + pExynosComponent->pExynosPort[nPortIndex].bIsPortFlushed = OMX_TRUE; + + if (pExynosComponent->bMultiThreadProcess == OMX_FALSE) { + Exynos_OSAL_SignalSet(pExynosComponent->pauseEvent); + } else { + Exynos_OSAL_SignalSet(pExynosComponent->pExynosPort[nPortIndex].pauseEvent); + } + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + Exynos_OMX_GetFlushBuffer(pExynosPort, flushPortBuffer); + + if (pExynosComponent->pExynosPort[nPortIndex].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); + } + } + + pVideoDec->exynos_codec_bufferProcessRun(pOMXComponent, nPortIndex); + Exynos_OSAL_MutexLock(flushPortBuffer[0]->bufferMutex); + pVideoDec->exynos_codec_stop(pOMXComponent, nPortIndex); + Exynos_OSAL_MutexLock(flushPortBuffer[1]->bufferMutex); + + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { + 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 (pVideoDec->bReconfigDPB == OMX_TRUE) { + ret = pVideoDec->exynos_codec_reconfigAllBuffers(pOMXComponent, nPortIndex); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_MutexUnlock(flushPortBuffer[1]->bufferMutex); + Exynos_OSAL_MutexUnlock(flushPortBuffer[0]->bufferMutex); + goto EXIT; + } + } else if (pExynosComponent->pExynosPort[nPortIndex].bufferProcessType & BUFFER_COPY) { + 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; + } + + pExynosComponent->pExynosPort[nPortIndex].bIsPortFlushed = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE,"OMX_CommandFlush EventCmdComplete, port:%d", nPortIndex); + if (bEvent == OMX_TRUE) + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandFlush, nPortIndex, NULL); + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_CountReset(pExynosPort->hBufferCount); +#endif + } + Exynos_OSAL_MutexUnlock(flushPortBuffer[1]->bufferMutex); + Exynos_OSAL_MutexUnlock(flushPortBuffer[0]->bufferMutex); + +EXIT: + if ((ret != OMX_ErrorNone) && (pOMXComponent != NULL) && (pExynosComponent != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR,"%s : %d", __FUNCTION__, __LINE__); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_InputBufferReturn( + OMX_COMPONENTTYPE *pOMXComponent, + EXYNOS_OMX_DATABUFFER *pDataBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + OMX_BUFFERHEADERTYPE *pBufferHdr = NULL; + + FunctionIn(); + + 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 = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_MESSAGE *message = NULL; + EXYNOS_OMX_DATABUFFER *inputUseBuffer = NULL; + + FunctionIn(); + + inputUseBuffer = &(pExynosPort->way.port2WayDataBuffer.inputDataBuffer); + + if (pExynosComponent->currentState != OMX_StateExecuting) { + 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_SemaphoreWait(pExynosPort->bufferSemID); + + if (inputUseBuffer->dataValid != OMX_TRUE) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + if (message->messageType == EXYNOS_OMX_CommandFakeBuffer) { + Exynos_OSAL_Free(message); + ret = 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, "Input Buffer Full, Check input buffer size! allocSize:%d, dataLen:%d", 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 = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_BUFFERHEADERTYPE *pBufferHdr = pDataBuffer->bufferHeader; + + FunctionIn(); + + if (pBufferHdr != NULL) { + pBufferHdr->nFilledLen = pDataBuffer->remainDataLen; + pBufferHdr->nOffset = 0; + pBufferHdr->nFlags = pDataBuffer->nFlags; + pBufferHdr->nTimeStamp = pDataBuffer->timeStamp; + + if ((pOutputPort->bStoreMetaData == OMX_TRUE) && + (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,"event OMX_BUFFERFLAG_EOS!!!"); + 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 = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_MESSAGE *message = NULL; + EXYNOS_OMX_DATABUFFER *outputUseBuffer = NULL; + + FunctionIn(); + + if (pExynosPort->bufferProcessType & BUFFER_COPY) { + 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) { + ret = OMX_ErrorUndefined; + goto EXIT; + } else if ((pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (!CHECK_PORT_BEING_FLUSHED(pExynosPort))){ + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + if (outputUseBuffer->dataValid != OMX_TRUE) { + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + if (message->messageType == EXYNOS_OMX_CommandFakeBuffer) { + Exynos_OSAL_Free(message); + ret = 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 = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_OMX_MESSAGE *message = NULL; + + FunctionIn(); + + if (pExynosComponent->currentState != OMX_StateExecuting) { + retBuffer = NULL; + goto EXIT; + } else if ((pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (!CHECK_PORT_BEING_FLUSHED(pExynosPort))){ + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + + message = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (message == NULL) { + retBuffer = NULL; + goto EXIT; + } + if (message->messageType == 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(); + + pExynosPort= &pExynosComponent->pExynosPort[PortIndex]; + + if (data == NULL) { + ret = OMX_ErrorInsufficientResources; + 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(); + + pExynosPort = &pExynosComponent->pExynosPort[PortIndex]; + Exynos_OSAL_SemaphoreWait(pExynosPort->codecSemID); + 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(); + + 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_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 ((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) { + goto EXIT; + } + + portParam->nPorts = pExynosComponent->portParam.nPorts; + portParam->nStartPortNumber = pExynosComponent->portParam.nStartPortNumber; + ret = OMX_ErrorNone; + } + break; + case OMX_IndexParamVideoPortFormat: + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + OMX_VIDEO_PARAM_PORTFORMATTYPE *pPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)ComponentParameterStructure; + OMX_U32 nPortIndex = pPortFormat->nPortIndex; + OMX_U32 nIndex = pPortFormat->nIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + 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) { + 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; + +#ifdef USE_ANB + if ((pExynosPort->bIsANBEnabled == OMX_FALSE) && + (pExynosPort->bStoreMetaData == OMX_FALSE)) +#endif + { + if (pExynosPort->supportFormat[nIndex] == OMX_COLOR_FormatUnused) { + ret = OMX_ErrorNoMore; + goto EXIT; + } + pPortFormat->eColorFormat = pExynosPort->supportFormat[nIndex]; + } +#ifdef USE_ANB + 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 = (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled; + else + pPortFormat->eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + } +#endif + } + + ret = OMX_ErrorNone; + } + break; +#ifdef USE_ANB + case OMX_IndexParamGetAndroidNativeBuffer: + { + ret = Exynos_OSAL_GetAndroidParameter(hComponent, nParamIndex, ComponentParameterStructure); + } + break; + case OMX_IndexParamPortDefinition: + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)ComponentParameterStructure; + OMX_U32 portIndex = portDefinition->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + ret = Exynos_OMX_GetParameter(hComponent, nParamIndex, ComponentParameterStructure); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + /* at this point, GetParameter has done all the verification, we + * just dereference things directly here + */ + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + if ((pExynosPort->bIsANBEnabled == OMX_TRUE) || + (pExynosPort->bStoreMetaData == OMX_TRUE)) { + if (pVideoDec->b10bitData == OMX_TRUE) { + portDefinition->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)Exynos_OSAL_OMX2HALPixelFormat((OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYUV420SemiPlanar, pExynosPort->ePlaneType); + } else { + portDefinition->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)Exynos_OSAL_OMX2HALPixelFormat(portDefinition->format.video.eColorFormat, pExynosPort->ePlaneType); + } + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] portDefinition->format.video.eColorFormat: 0x%x", pExynosComponent, __FUNCTION__, portDefinition->format.video.eColorFormat); + } + } + break; +#endif + case OMX_IndexVendorNeedContigMemory: + { + EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *pPortMemType = (EXYNOS_OMX_VIDEO_PARAM_PORTMEMTYPE *)ComponentParameterStructure; + OMX_U32 nPortIndex = pPortMemType->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort; + + 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) + goto EXIT; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + pPortMemType->bNeedContigMem = pExynosPort->bNeedContigMem; + } + break; + case OMX_IndexExynosParamCorruptedHeader: + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pCorruptedHeader->bDiscardEvent = pVideoDec->bDiscardCSDError; + } + 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_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 ((int)nIndex) { + case OMX_IndexParamVideoPortFormat: + { + OMX_VIDEO_PARAM_PORTFORMATTYPE *pPortFormat = (OMX_VIDEO_PARAM_PORTFORMATTYPE *)ComponentParameterStructure; + OMX_U32 nPortIndex = pPortFormat->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (ret != OMX_ErrorNone) { + 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; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "nPortIndex:%d, pPortFormat->eColorFormat:0x%x", nPortIndex, pPortFormat->eColorFormat); + } + } + break; + case OMX_IndexParamPortDefinition: + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)ComponentParameterStructure; + OMX_U32 portIndex = pPortDefinition->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + 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) { + 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_ANB + /* 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_ANB // Modified by Google engineer + /* should not affect the format since in ANB case, the caller + * is providing us a HAL format */ + if ((pExynosPort->bIsANBEnabled == OMX_TRUE) || + (pExynosPort->bStoreMetaData == OMX_TRUE)) { + 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) { + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + pExynosOutputPort->portDefinition.format.video.nFrameWidth = pExynosPort->portDefinition.format.video.nFrameWidth; + pExynosOutputPort->portDefinition.format.video.nFrameHeight = pExynosPort->portDefinition.format.video.nFrameHeight; + pExynosOutputPort->portDefinition.format.video.nStride = realWidth; + pExynosOutputPort->portDefinition.format.video.nSliceHeight = realHeight; + + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { + if ((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) && + (pExynosPort->portDefinition.nBufferSize > CUSTOM_FHD_VIDEO_INPUT_BUFFER_SIZE)) { + pExynosPort->portDefinition.nBufferSize = (CUSTOM_UHD_VIDEO_INPUT_BUFFER_SIZE > pExynosPort->portDefinition.nBufferSize) ? + CUSTOM_UHD_VIDEO_INPUT_BUFFER_SIZE : pExynosPort->portDefinition.nBufferSize; + } else if ((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) && + (pExynosPort->portDefinition.nBufferSize > MAX_SECURE_INPUT_BUFFER_SIZE)) { + pExynosPort->portDefinition.nBufferSize = MAX_SECURE_INPUT_BUFFER_SIZE; + } + } + + switch ((int)pExynosOutputPort->portDefinition.format.video.eColorFormat) { + case OMX_COLOR_FormatYUV420Planar: + case OMX_COLOR_FormatYUV420SemiPlanar: + case OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace: + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanar: + case OMX_SEC_COLOR_FormatNV12Tiled: + pExynosOutputPort->portDefinition.nBufferSize = (ALIGN(realWidth, 16) * ALIGN(realHeight, 16) * 3) / 2; + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Color format is not support!! use default YUV size!!"); + ret = OMX_ErrorUnsupportedSetting; + break; + } + } + } + break; +#ifdef USE_ANB + case OMX_IndexParamEnableAndroidBuffers: + case OMX_IndexParamUseAndroidNativeBuffer: +#ifdef USE_STOREMETADATA + case OMX_IndexParamStoreMetaDataBuffer: +#endif + { + ret = Exynos_OSAL_SetAndroidParameter(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; + EXYNOS_OMX_BASEPORT *pExynosPort; + + 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) + 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_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pVideoDec->bDTSMode = pDTSParam->bDTSMode; + } + break; + case OMX_IndexParamEnableThumbnailMode: + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + 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_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pVideoDec->bDiscardCSDError = pCorruptedHeader->bDiscardEvent; + 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; + + 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 ((int)nIndex) { + case OMX_IndexVendorGetBufferFD: + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pBufferInfo->fd = Exynos_OSAL_SharedMemory_VirtToION(pVideoDec->hSharedMemory, pBufferInfo->pVirAddr); + } + break; + case OMX_IndexExynosConfigPTSMode: /* MSRND */ + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + + *((OMX_BOOL *)pComponentConfigStructure) = (pVideoDec->bDTSMode == OMX_TRUE)? OMX_FALSE:OMX_TRUE; + } + break; + 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)) { + 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 (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + switch ((int)nIndex) { + case OMX_IndexVendorThumbnailMode: /* It is for backward compatibility */ + { + pVideoDec->bThumbnailMode = *((OMX_BOOL *)pComponentConfigStructure); + + ret = OMX_ErrorNone; + } + 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) + goto EXIT; + + xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + if ((xFramerate >> 16) == 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : xFramerate is zero. can't calculate QosRatio", __FUNCTION__); + pVideoDec->nQosRatio = 100; + } else { + pVideoDec->nQosRatio = (OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + } + + pVideoDec->bQosChanged = OMX_TRUE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] operating rate(%.1lf) / frame rate(%.1lf) / ratio(%d)", pExynosComponent, __FUNCTION__, + pConfigRate->nU32 / (double)65536, xFramerate / (double)65536, pVideoDec->nQosRatio); + + ret = OMX_ErrorNone; + } + break; +#ifdef USE_QOS_CTRL + case OMX_IndexVendorSetQosRatio: /* MSRND */ + { + EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *pQosInfo = (EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pQosInfo, sizeof(EXYNOS_OMX_VIDEO_CONFIG_QOSINFO)); + if (ret != OMX_ErrorNone) + goto EXIT; + + pVideoDec->nQosRatio = pQosInfo->nQosRatio; + pVideoDec->bQosChanged = OMX_TRUE; + + ret = OMX_ErrorNone; + } + break; +#endif + case OMX_IndexExynosConfigPTSMode: /* MSRND */ + { + pVideoDec->bDTSMode = ((*((OMX_BOOL *)pComponentConfigStructure)) == OMX_TRUE)? OMX_FALSE:OMX_TRUE; + ret = OMX_ErrorNone; + } + break; + 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) { + 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; + } + + 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_CONFIG_OPERATING_RATE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigOperatingRate; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_QOS_CTRL + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_SET_QOS_RATIO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorSetQosRatio; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + +#ifdef USE_ANB + 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_GET_ANB) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamGetAndroidNativeBuffer; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_USE_ANB) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamUseAndroidNativeBuffer; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_USE_ANB2) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamUseAndroidNativeBuffer2; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_THUMBNAIL) == 0) { + *pIndexType = OMX_IndexVendorThumbnailMode; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_ENABLE_THUMBNAIL) == 0) { + *pIndexType = OMX_IndexParamEnableThumbnailMode; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_STOREMETADATA + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_STORE_METADATA_BUFFER) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexParamStoreMetaDataBuffer; + 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; +} + +#ifdef USE_ANB +OMX_ERRORTYPE Exynos_Shared_ANBBufferToData(EXYNOS_OMX_DATABUFFER *pUseBuffer, EXYNOS_OMX_DATA *pData, EXYNOS_OMX_BASEPORT *pExynosPort) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_U32 width, height; + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + + Exynos_OSAL_Memset(planes, 0, sizeof(planes)); + + width = pExynosPort->portDefinition.format.video.nFrameWidth; + height = pExynosPort->portDefinition.format.video.nFrameHeight; + +#ifdef USE_STOREMETADATA + if ((pExynosPort->bIsANBEnabled == OMX_TRUE) || + (pExynosPort->bStoreMetaData == OMX_TRUE)) { +#else + if (pExynosPort->bIsANBEnabled == OMX_TRUE) { +#endif + OMX_U32 stride; + + if ((pUseBuffer->bufferHeader != NULL) && + (pUseBuffer->bufferHeader->pBuffer != NULL) && + (pExynosPort->exceptionFlag == GENERAL_STATE)) { + + if (pExynosPort->bIsANBEnabled == OMX_TRUE) + ret = Exynos_OSAL_LockANBHandle(pUseBuffer->bufferHeader->pBuffer, width, height, pExynosPort->portDefinition.format.video.eColorFormat, &stride, planes); +#ifdef USE_STOREMETADATA + else if (pExynosPort->bStoreMetaData == OMX_TRUE) + ret = Exynos_OSAL_LockMetaData(pUseBuffer->bufferHeader->pBuffer, width, height, pExynosPort->portDefinition.format.video.eColorFormat, &stride, planes); +#endif + + if (ret != OMX_ErrorNone) + goto EXIT; + + pUseBuffer->dataLen = sizeof(void *); + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pData->multiPlaneBuffer.dataBuffer[0] = planes[0].addr; + pData->multiPlaneBuffer.dataBuffer[1] = planes[1].addr; + pData->multiPlaneBuffer.dataBuffer[2] = planes[2].addr; + +#ifdef USE_DMA_BUF + pData->multiPlaneBuffer.fd[0] = planes[0].fd; + pData->multiPlaneBuffer.fd[1] = planes[1].fd; + pData->multiPlaneBuffer.fd[2] = planes[2].fd; +#endif + + 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: + return ret; +} + +OMX_ERRORTYPE Exynos_Shared_DataToANBBuffer(EXYNOS_OMX_DATA *pData, EXYNOS_OMX_DATABUFFER *pUseBuffer, EXYNOS_OMX_BASEPORT *pExynosPort) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + 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 ((pUseBuffer->bufferHeader == NULL) || + (pUseBuffer->bufferHeader->pBuffer == NULL)) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if (pExynosPort->bIsANBEnabled == OMX_TRUE) { + Exynos_OSAL_UnlockANBHandle(pUseBuffer->bufferHeader->pBuffer); +#ifdef USE_STOREMETADATA + } else if (pExynosPort->bStoreMetaData == OMX_TRUE) { + Exynos_OSAL_UnlockMetaData(pUseBuffer->bufferHeader->pBuffer); +#endif + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +EXIT: + return ret; +} +#endif + +OMX_ERRORTYPE Exynos_Shared_DataToBuffer(EXYNOS_OMX_DATA *pData, EXYNOS_OMX_DATABUFFER *pUseBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + 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; + + return ret; +} diff --git a/component/video/dec/Exynos_OMX_VdecControl.h b/component/video/dec/Exynos_OMX_VdecControl.h new file mode 100644 index 0000000..b21bbfa --- /dev/null +++ b/component/video/dec/Exynos_OMX_VdecControl.h @@ -0,0 +1,116 @@ +/* + * + * 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) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#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); + +#ifdef USE_ANB +OMX_ERRORTYPE Exynos_Shared_ANBBufferToData(EXYNOS_OMX_DATABUFFER *pUseBuffer, EXYNOS_OMX_DATA *pData, EXYNOS_OMX_BASEPORT *pExynosPort); +OMX_ERRORTYPE Exynos_Shared_DataToANBBuffer(EXYNOS_OMX_DATA *pData, EXYNOS_OMX_DATABUFFER *pUseBuffer, EXYNOS_OMX_BASEPORT *pExynosPort); +#endif + +OMX_ERRORTYPE Exynos_Shared_DataToBuffer(EXYNOS_OMX_DATA *pData, EXYNOS_OMX_DATABUFFER *pUseBuffer); +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); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/video/dec/NOTICE b/component/video/dec/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/dec/h264/Android.mk b/component/video/dec/h264/Android.mk new file mode 100644 index 0000000..a45e78f --- /dev/null +++ b/component/video/dec/h264/Android.mk @@ -0,0 +1,83 @@ +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_CFLAGS := + +ifeq ($(BOARD_USE_ANB), true) +LOCAL_CFLAGS += -DUSE_ANB +endif + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_S3D_SUPPORT), true) +ifeq ($(BOARD_USES_HWC_SERVICES), true) +LOCAL_CFLAGS += -DUSE_S3D_SUPPORT +else +ifeq ($(TARGET_BOARD_PLATFORM), exynos5) +LOCAL_CFLAGS += -DUSE_S3D_SUPPORT +endif +endif +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_TIMESTAMP_REORDER_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_TIMESTAMP_REORDER_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/include + +ifeq ($(BOARD_USE_SKYPE_HD), true) +LOCAL_CFLAGS += -DUSE_SKYPE_HD +LOCAL_CFLAGS += -DBUILD_DEC +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/skype +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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/dec/h264/Exynos_OMX_H264dec.c b/component/video/dec/h264/Exynos_OMX_H264dec.c new file mode 100644 index 0000000..c8d42e6 --- /dev/null +++ b/component/video/dec/h264/Exynos_OMX_H264dec.c @@ -0,0 +1,3423 @@ +/* + * + * 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" + +#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" + +#define H264_DEC_NUM_OF_EXTRA_BUFFERS 7 + +//#define ADD_SPS_PPS_I_FRAME +//#define FULL_FRAME_SEARCH + +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; + + FunctionIn(); + + 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_100: + case MFC_101: + pH264Dec->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel52; + break; + case MFC_80: + case MFC_90: + case MFC_1010: + 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: + 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; + } + + while ((pH264Dec->hMFCH264Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pH264Dec->hMFCH264Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : there is no any profile/level", __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); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s : supported profile(%x), level(%x)", __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + 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, "%s : there is no any profile/level", __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, "%s : profile(%x)/level(%x) is %ssupported", __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +#if 0 /* unused code */ +static OMX_ERRORTYPE GetCodecInputPrivateData(OMX_PTR codecBuffer, OMX_PTR *pVirtAddr, OMX_U32 *dataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +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; +} + +#if 0 /* unused code */ +int Check_H264_Frame( + OMX_U8 *pInputStream, + OMX_U32 buffSize, + OMX_U32 flag, + OMX_BOOL bPreviousFrameEOF, + OMX_BOOL *pbEndOfFrame) +{ + OMX_U32 preFourByte = (OMX_U32)-1; + int accessUnitSize = 0; + int frameTypeBoundary = 0; + int nextNaluSize = 0; + int naluStart = 0; + + if (bPreviousFrameEOF == OMX_TRUE) + naluStart = 0; + else + naluStart = 1; + + while (1) { + int inputOneByte = 0; + + if (accessUnitSize == (int)buffSize) + goto EXIT; + + inputOneByte = *(pInputStream++); + accessUnitSize += 1; + + if (preFourByte == 0x00000001 || (preFourByte << 8) == 0x00000100) { + int naluType = inputOneByte & 0x1F; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "NaluType : %d", naluType); + if (naluStart == 0) { +#ifdef ADD_SPS_PPS_I_FRAME + if (naluType == 1 || naluType == 5) +#else + if (naluType == 1 || naluType == 5 || naluType == 7 || naluType == 8) +#endif + naluStart = 1; + } else { +#ifdef OLD_DETECT + frameTypeBoundary = (8 - naluType) & (naluType - 10); //AUD(9) +#else + if (naluType == 9) + frameTypeBoundary = -2; +#endif + if (naluType == 1 || naluType == 5) { + if (accessUnitSize == (int)buffSize) { + accessUnitSize--; + goto EXIT; + } + inputOneByte = *pInputStream++; + accessUnitSize += 1; + + if (inputOneByte >= 0x80) + frameTypeBoundary = -1; + } + if (frameTypeBoundary < 0) { + break; + } + } + + } + preFourByte = (preFourByte << 8) + inputOneByte; + } + + *pbEndOfFrame = OMX_TRUE; + nextNaluSize = -5; + if (frameTypeBoundary == -1) + nextNaluSize = -6; + if (preFourByte != 0x00000001) + nextNaluSize++; + return (accessUnitSize + nextNaluSize); + +EXIT: + *pbEndOfFrame = OMX_FALSE; + + return accessUnitSize; +} +#endif + +static OMX_BOOL Check_H264_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize) +{ + if (streamSize < 4) { + return OMX_FALSE; + } + + 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, "NaluType : %d, 0x%x, 0x%x, 0x%x", (pInputStream[4] & 0x1F), pInputStream[3], pInputStream[4], pInputStream[5]); + return 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, "NaluType : %d, 0x%x, 0x%x, 0x%x", (pInputStream[3] & 0x1F), pInputStream[2], pInputStream[3], pInputStream[4]); + return OMX_TRUE; + } else { + return OMX_FALSE; + } +} + +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_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate decoder ops buffer"); + 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); + + Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps); + + /* check mandatory functions for decoder ops */ + if ((pDecOps->Init == NULL) || (pDecOps->Finalize == NULL) || + (pDecOps->Get_ActualBufferCount == NULL) || (pDecOps->Set_FrameTag == NULL) || +#ifdef USE_S3D_SUPPORT + (pDecOps->Enable_SEIParsing == NULL) || (pDecOps->Get_FramePackingInfo == NULL) || +#endif + (pDecOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pH264Dec->hMFCH264Handle.hMFCHandle = pH264Dec->hMFCH264Handle.pDecOps->Init(pVideoInstInfo); + if (pH264Dec->hMFCH264Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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, "Failed to Enable SEI Parsing"); + 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; + } + + /* 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Dec->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_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = 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; + pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + 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) && + (pOutputPort->bDynamicDPBMode == OMX_TRUE)) + 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + + 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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + CODEC_DEC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoDecBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]); + pBufOps = pH264Dec->hMFCH264Handle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]); + pBufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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) { + /**********************************/ + /* 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); + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = H264CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to H264CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType & BUFFER_SHARE) { + /**********************************/ + /* Codec Buffer Unregister */ + /**********************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + } + + Exynos_ResolutionUpdate(pOMXComponent); + } 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + int i, nOutbufs; + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + 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) && + (pH264Dec->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, "pVideoDec->pMFCDecInputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecInputBuffer[%d]->pVirAddr[0]: 0x%x", i, 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->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pH264Dec->hMFCH264Handle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, 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; + + /* Get Frame packing information*/ + if (pDecOps->Get_FramePackingInfo(pH264Dec->hMFCH264Handle.hMFCHandle, &framePacking) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Get Frame Packing Information"); + ret = OMX_FALSE; + goto EXIT; + } + + if (framePacking.available) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "arrangement ID: 0x%08x", framePacking.arrangement_id); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "arrangement_type: %d", framePacking.arrangement_type); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "content_interpretation_type: %d", framePacking.content_interpretation_type); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "current_frame_is_frame0_flag: %d", framePacking.current_frame_is_frame0_flag); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "spatial_flipping_flag: %d", framePacking.spatial_flipping_flag); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "fr0X:%d fr0Y:%d fr0X:%d fr0Y:%d", 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; + /** Send Port Settings changed call back - output color format change */ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + 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: + return ret; +} +#endif + +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); + 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 ((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) || + (codecOutbufConf.bInterlaced != pH264Dec->hMFCH264Handle.codecOutbufConf.bInterlaced) || +#endif + (maxDPBNum != pH264Dec->hMFCH264Handle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] DRC: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight, + pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth, + pH264Dec->hMFCH264Handle.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__, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType, + pH264Dec->hMFCH264Handle.maxDPBNum, + pH264Dec->hMFCH264Handle.codecOutbufConf.eColorFormat, + pH264Dec->hMFCH264Handle.codecOutbufConf.eFilledDataType); + + 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 (pOutputPort->bufferProcessType & BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = pH264Dec->hMFCH264Handle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pH264Dec->hMFCH264Handle.maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + /** 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); + } + } + + 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] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight, + pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nWidth, + pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nHeight); + + 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; + + /** 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; + + 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, "Failed to get geometry for parsed header info"); + ret = OMX_ErrorCorruptedHeader; + 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] H264CodecSetup maxDPBNum: %d", pExynosComponent, __FUNCTION__, pH264Dec->hMFCH264Handle.maxDPBNum); + + /* get interlace info */ + if (pH264Dec->hMFCH264Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "detect an interlaced type"); + + pH264Dec->hMFCH264Handle.bConfiguredMFCSrc = OMX_TRUE; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pCropRectangle = &(pOutputPort->cropRectangle); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + } else { + pCropRectangle = &(pOutputPort->newCropRectangle); + pInputPortDefinition = &(pInputPort->newPortDefinition); + pOutputPortDefinition = &(pOutputPort->newPortDefinition); + } + + 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) { + if ((pVideoDec->bReconfigDPB) || + (pInputPort->portDefinition.format.video.nFrameWidth != pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.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; + + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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) || + (pH264Dec->hMFCH264Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) || + (pInputPort->portDefinition.format.video.nFrameWidth != pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.format.video.nFrameHeight != pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPort->portDefinition.nBufferCountActual != 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; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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); + } + } + if ((pVideoDec->bReconfigDPB != OMX_TRUE) && + ((pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameWidth != pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nWidth) || + (pH264Dec->hMFCH264Handle.codecOutbufConf.nFrameHeight != pH264Dec->hMFCH264Handle.codecOutbufConf.cropRect.nHeight))) { + /* Check Crop */ + 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); + + /** 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 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 oneFrameSize = pSrcInputData->dataLen; + OMX_COLOR_FORMATTYPE eOutputFormat = pExynosOutputPort->portDefinition.format.video.eColorFormat; + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + int i; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + 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); + Exynos_OSAL_SignalSet(pH264Dec->hDestinationStartEvent); + + 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->bLowLatency == OMX_TRUE) + pDecOps->Set_DisplayDelay(hMFCHandle, 0); +#endif + + if ((pDecOps->Enable_DTSMode != NULL) && + (pVideoDec->bDTSMode == OMX_TRUE)) + pDecOps->Enable_DTSMode(hMFCHandle); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eCompressionFormat = VIDEO_CODING_AVC; + pInbufOps->Set_Shareable(hMFCHandle); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + bufferConf.nSizeImage = pExynosInputPort->portDefinition.nBufferSize; + } else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + bufferConf.nSizeImage = DEFAULT_MFC_INPUT_BUFFER_SIZE; + } + 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + if ((pH264Dec->hMFCH264Handle.videoInstInfo.specificInfo.dec.bDualDPBSupport == VIDEO_TRUE) && + (eOutputFormat != (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled)) { + /* Needs to eanble DualDPB feature */ + if (pDecOps->Enable_DualDPBMode(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorHardware; + goto EXIT; + } + } + 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; + goto EXIT; + } + } + + pH264Dec->hMFCH264Handle.MFCOutputColorType = bufferConf.eColorFormat; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + /* set buffer process type */ + if (pDecOps->Set_BufferProcessType(hMFCHandle, pExynosOutputPort->bufferProcessType) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set buffer process type(not supported)"); + } + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enqueue input buffer for header parsing"); +// 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, "Failed to run input buffer for header parsing"); + ret = OMX_ErrorCodecInit; + goto EXIT; + } + + ret = H264CodecUpdateResolution(pOMXComponent); + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0]) , *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 1), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 2), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 3), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 4), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 5), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 6), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 7)); + if (ret != OMX_ErrorNone) { + H264CodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + ret = OMX_ErrorInputDataDecodeYet; + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + 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] = {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]; + + if (pExynosOutputPort->bDynamicDPBMode == OMX_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enable Dynamic DPB"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + /* get dpb count */ + nOutbufs = pH264Dec->hMFCH264Handle.maxDPBNum; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Register output buffer */ + ret = H264CodecRegistCodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) + pOutbufOps->Enqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + nDataLen, + nPlaneCnt, + NULL); + } else { + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + 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; + + /* without Register output buffer */ + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (int *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { +#ifdef USE_ANB + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + int plane; + + Exynos_OSAL_Memset((OMX_PTR)planes, 0, sizeof(ExynosVideoPlane) * MAX_BUFFER_PLANE); + + /* get dpb count */ + nOutbufs = pExynosOutputPort->portDefinition.nBufferCountActual; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_TRUE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + for (i = 0; i < pExynosOutputPort->assignedBufferNum; i++) { + for (plane = 0; plane < nPlaneCnt; plane++) { + planes[plane].fd = pExynosOutputPort->extendBufferHeader[i].buf_fd[plane]; + planes[plane].addr = pExynosOutputPort->extendBufferHeader[i].pYUVBuf[plane]; + planes[plane].allocSize = nAllocLen[plane]; + } + + if (pOutbufOps->Register(hMFCHandle, planes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Register output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pOutbufOps->Enqueue(hMFCHandle, + (void **)pExynosOutputPort->extendBufferHeader[i].pYUVBuf, + nDataLen, + nPlaneCnt, + NULL); + } + + if (pOutbufOps->Apply_RegisteredBuffer(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Apply output buffer"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } else { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } else { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_FALSE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } +#else + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; +#endif + } + + pH264Dec->hMFCH264Handle.bConfiguredMFCDst = OMX_TRUE; + + 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; + + 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 ((int)nParamIndex) { + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = (OMX_VIDEO_PARAM_AVCTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCTYPE *pSrcAVCComponent = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = 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) { + goto EXIT; + } + + if (pDstAVCComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + 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) { + 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; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + EXYNOS_H264DEC_HANDLE *pH264Dec = 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; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + case OMX_IndexExynosParamReorderMode: /* MSRND */ + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pReorderParam->bReorderMode = pVideoDec->bReorderMode; + } + break; +#endif + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 portIndex = portDefinition->nPortIndex; + 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 *pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (((pExynosPort->bIsANBEnabled == OMX_TRUE) || (pExynosPort->bStoreMetaData == OMX_TRUE)) && + (pH264Dec->hMFCH264Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) && + (portIndex == OUTPUT_PORT_INDEX)) { + portDefinition->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)Exynos_OSAL_OMX2HALPixelFormat((OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace, pExynosPort->ePlaneType); + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "portDefinition->format.video.eColorFormat: 0x%x", portDefinition->format.video.eColorFormat); + } + 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; + + 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 ((int)nIndex) { + case OMX_IndexParamVideoAvc: + { + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = NULL; + OMX_VIDEO_PARAM_AVCTYPE *pSrcAVCComponent = (OMX_VIDEO_PARAM_AVCTYPE *)pComponentParameterStructure; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + /* 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) { + goto EXIT; + } + + if (pSrcAVCComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + 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_ErrorBadParameter; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_AVCTYPE *pDstAVCComponent = NULL; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + 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; + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + case OMX_IndexExynosParamReorderMode: /* MSRND */ + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pVideoDec->bReorderMode = pReorderParam->bReorderMode; + } + break; +#endif + 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; + + 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 ((int)nIndex) { + case OMX_IndexConfigCommonOutputCrop: + { + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + OMX_CONFIG_RECTTYPE *pDstRectType = NULL; + pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + if (pH264Dec->hMFCH264Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + break; + } + + pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + + if ((pDstRectType->nPortIndex != INPUT_PORT_INDEX) && + (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[pDstRectType->nPortIndex]; + + pSrcRectType = &(pExynosPort->cropRectangle); + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + break; +#ifdef USE_S3D_SUPPORT + case OMX_IndexVendorS3DMode: + { + EXYNOS_H264DEC_HANDLE *pH264Dec = NULL; + OMX_U32 *pS3DMode = NULL; + pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + pS3DMode = (OMX_U32 *)pComponentConfigStructure; + *pS3DMode = (OMX_U32) pH264Dec->hMFCH264Handle.S3DFPArgmtType; + } + break; +#endif + case OMX_IndexExynosConfigDisplayDelay: /* MSRND */ + { + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + (*((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; + + 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 ((int)nIndex) { + case OMX_IndexExynosConfigDisplayDelay: /* MSRND */ + { + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + OMX_U32 nDisplayDelay; + + if (pH264Dec->hMFCH264Handle.bConfiguredMFCSrc == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + break; + } + + nDisplayDelay = (*((OMX_U32 *)pComponentConfigStructure)); + 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) { + 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; + } + +#ifdef USE_S3D_SUPPORT + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_GET_S3D) == 0) { + *pIndexType = OMX_IndexVendorS3DMode; + 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; + } + +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_REORDER_MODE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamReorderMode; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + } + +#ifdef USE_SKYPE_HD + ret = Exynos_H264Dec_GetExtensionIndex_SkypeHD(hComponent, cParameterName, pIndexType); + if (ret != OMX_ErrorNone) +#endif + 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; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + 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; + OMX_PTR hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + ExynosVideoInstInfo *pVideoInstInfo = &(pH264Dec->hMFCH264Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i, plane; + + FunctionIn(); + + pH264Dec->hMFCH264Handle.bConfiguredMFCSrc = OMX_FALSE; + pH264Dec->hMFCH264Handle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + pVideoDec->bDiscardCSDError = 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; + } + + pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {DEFAULT_MFC_INPUT_BUFFER_SIZE, 0, 0}; + 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) { + 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->hDestinationStartEvent); + + 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 = (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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + OMX_PTR hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + + int i, plane; + + FunctionIn(); + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pH264Dec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pH264Dec->hDestinationStartEvent); + pH264Dec->hDestinationStartEvent = NULL; + pH264Dec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalTerminate(pH264Dec->hSourceStartEvent); + pH264Dec->hSourceStartEvent = NULL; + pH264Dec->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); + } 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); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + 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]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pH264Dec->hMFCH264Handle.pOutbufOps; + 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; + int i; + + FunctionIn(); + + if (pH264Dec->hMFCH264Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = H264CodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pH264Dec->hMFCH264Handle.bConfiguredMFCDst == OMX_FALSE) && + (pVideoDec->bForceHeaderParsing == OMX_FALSE)) { + ret = H264CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to H264CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + } + + if (((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) || + ((bInStartCode = Check_H264_StartCode(pSrcInputData->multiPlaneBuffer.dataBuffer[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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x, oneFrameSize: %d", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pH264Dec->hMFCH264Handle.indexTimestamp, pSrcInputData->nFlags, oneFrameSize); + + pDecOps->Set_FrameTag(hMFCHandle, pH264Dec->hMFCH264Handle.indexTimestamp); + pH264Dec->hMFCH264Handle.indexTimestamp++; + pH264Dec->hMFCH264Handle.indexTimestamp %= MAX_TIMESTAMP; + + if ((pVideoDec->bQosChanged == OMX_TRUE) && + (pDecOps->Set_QosRatio != NULL)) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + pVideoDec->bQosChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] bufferHeader: 0x%x, dataBuffer: 0x%x", pExynosComponent, __FUNCTION__, pSrcInputData->bufferHeader, pSrcInputData->multiPlaneBuffer.dataBuffer[0]); + + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + if (pExynosInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pH264Dec->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + ret = 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pH264Dec->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pH264Dec->hMFCH264Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[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, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#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]; + + ExynosVideoDecOps *pDecOps = pH264Dec->hMFCH264Handle.pDecOps; + 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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + 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] : %d => ADDR[%d]: 0x%x", pExynosComponent, __FUNCTION__, __LINE__, i, + pDstInputData->multiPlaneBuffer.dataBuffer[i]); + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + ret = H264CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to H264CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + pVideoDec->bReconfigDPB = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + codecReturn = pOutbufOps->Enqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } else { + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &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; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + FunctionIn(); + + if (pH264Dec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + pVideoBuffer = pOutbufOps->Dequeue(hMFCHandle); + if (pVideoBuffer == (ExynosVideoBuffer *)VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "HW is not available"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + if (pVideoBuffer == NULL) { + ret = OMX_ErrorNone; + goto EXIT; + } + } else { + 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, "HW is not available"); + 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(pExynosOutputPort))) { + 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) { + pExynosOutputPort->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(pExynosOutputPort); + + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->multiPlaneBuffer.fd[plane] = pVideoBuffer->planes[plane].fd; + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->multiPlaneBuffer.dataBuffer[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + /* get interlace frame info */ + if ((pExynosOutputPort->bufferProcessType & BUFFER_SHARE) && + (pH264Dec->hMFCH264Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) && + (pVideoBuffer->planes[2].addr != NULL)) { + /* only NV12 case */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] interlace type = %x", pExynosComponent, __FUNCTION__, pVideoBuffer->interlacedType); + *(int *)(pVideoBuffer->planes[2].addr) = pVideoBuffer->interlacedType; + } + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pH264Dec->hMFCH264Handle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->ColorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + 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; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output timestamp %lld us (%.2f secs), indexTimestamp: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, indexTimestamp, pDstOutputData->nFlags); + } + } 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 reorder timestamp %lld us (%.2f secs), sCurrentTimestamp.nIndex: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, sCurrentTimestamp.nIndex, pDstOutputData->nFlags); + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pExynosOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if (pH264Dec->hMFCH264Handle.videoInstInfo.specificInfo.dec.bLastFrameSupport == VIDEO_FALSE) { + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + 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] indexTimestamp(%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 = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + } + } else { + if ((displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + + if ((pExynosComponent->bBehaviorEOS == OMX_TRUE) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME)) { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (displayStatus != VIDEO_FRAME_STATUS_LAST_FRAME) { + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } else { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 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_ErrorNone; + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + 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; + } + + 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_SignalReset(pH264Dec->hSourceStartEvent); + } + + ret = Exynos_H264Dec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && (pExynosComponent->currentState == OMX_StateExecuting)) { + 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_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pH264Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pH264Dec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pH264Dec->hDestinationStartEvent); + } + 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; + } + + 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 (pH264Dec->hMFCH264Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_H264Dec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +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 (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pH264Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pH264Dec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pH264Dec->hDestinationStartEvent); + } + + if (Exynos_OSAL_GetElemNum(&pH264Dec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && (pExynosComponent->currentState == OMX_StateExecuting)) { + 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, "OMX_ErrorBadParameter, Line:%d", __LINE__); + goto EXIT; + } + if ((Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H264_DEC, componentName) == 0) || + (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H264_CUSTOM_DEC, componentName) == 0)) { + bSecureMode = OMX_FALSE; + } else if ((Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H264_DRM_DEC, componentName) == 0) || + (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H264_CUSTOM_DRM_DEC, componentName) == 0)) { + bSecureMode = OMX_TRUE; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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) + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_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.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 | BUFFER_ANBSHARE; + 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; + +#if 0 /* unused code */ + pVideoDec->exynos_checkInputFrame = &Check_H264_Frame; + pVideoDec->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &H264CodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &H264CodecCheckResolution; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + Exynos_OSAL_Free(pH264Dec); + pH264Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->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]: Exynos_Video_GetInstInfo is failed", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pH264Dec); + pH264Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec %d %d %d %d", pExynosComponent, __FUNCTION__, + (pH264Dec->hMFCH264Handle.videoInstInfo.specificInfo.dec.bDualDPBSupport), + (pH264Dec->hMFCH264Handle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport), + (pH264Dec->hMFCH264Handle.videoInstInfo.specificInfo.dec.bLastFrameSupport), + (pH264Dec->hMFCH264Handle.videoInstInfo.specificInfo.dec.bSkypeSupport)); + + if (pH264Dec->hMFCH264Handle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport == VIDEO_TRUE) + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bDynamicDPBMode = OMX_TRUE; + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + 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; + + 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; + } + + ret = Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/dec/h264/Exynos_OMX_H264dec.h b/component/video/dec/h264/Exynos_OMX_H264dec.h new file mode 100644 index 0000000..539b34f --- /dev/null +++ b/component/video/dec/h264/Exynos_OMX_H264dec.h @@ -0,0 +1,101 @@ +/* + * + * 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" + +#ifdef USE_SKYPE_HD +#include "OMX_Video_Extensions.h" +#endif + +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; + +#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 hDestinationStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; + + OMX_BOOL bLowLatency; +} 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/component/video/dec/h264/NOTICE b/component/video/dec/h264/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/dec/h264/library_register.c b/component/video/dec/h264/library_register.c new file mode 100644 index 0000000..b3c77f9 --- /dev/null +++ b/component/video/dec/h264/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 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; +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + /* component 3 - video custom decoder H.264 */ + Exynos_OSAL_Strcpy(exynosComponents[2]->componentName, EXYNOS_OMX_COMPONENT_H264_CUSTOM_DEC); + Exynos_OSAL_Strcpy(exynosComponents[2]->roles[0], EXYNOS_OMX_COMPONENT_H264_DEC_ROLE); + exynosComponents[2]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 4 - video custom decoder H.264 for DRM */ + Exynos_OSAL_Strcpy(exynosComponents[3]->componentName, EXYNOS_OMX_COMPONENT_H264_CUSTOM_DRM_DEC); + Exynos_OSAL_Strcpy(exynosComponents[3]->roles[0], EXYNOS_OMX_COMPONENT_H264_DEC_ROLE); + exynosComponents[3]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; +#endif +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/component/video/dec/h264/library_register.h b/component/video/dec/h264/library_register.h new file mode 100644 index 0000000..20de9ad --- /dev/null +++ b/component/video/dec/h264/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 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 4 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* H.264 */ +#define EXYNOS_OMX_COMPONENT_H264_DEC "OMX.Exynos.AVC.Decoder" +#define EXYNOS_OMX_COMPONENT_H264_DRM_DEC "OMX.Exynos.AVC.Decoder.secure" + +#define EXYNOS_OMX_COMPONENT_H264_CUSTOM_DEC "OMX.Exynos.avc.dec" +#define EXYNOS_OMX_COMPONENT_H264_CUSTOM_DRM_DEC "OMX.Exynos.avc.dec.secure" + +#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/component/video/dec/hevc/Android.mk b/component/video/dec/hevc/Android.mk new file mode 100644 index 0000000..46cab60 --- /dev/null +++ b/component/video/dec/hevc/Android.mk @@ -0,0 +1,77 @@ +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_CFLAGS := +LOCAL_CFLAGS += -DUSE_HEVC_SUPPORT + +ifeq ($(BOARD_USE_ANB), true) +LOCAL_CFLAGS += -DUSE_ANB +endif + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_S3D_SUPPORT), true) +ifeq ($(BOARD_USES_HWC_SERVICES), true) +LOCAL_CFLAGS += -DUSE_S3D_SUPPORT +else +ifeq ($(TARGET_BOARD_PLATFORM), exynos5) +LOCAL_CFLAGS += -DUSE_S3D_SUPPORT +endif +endif +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_TIMESTAMP_REORDER_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_TIMESTAMP_REORDER_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/dec/hevc/Exynos_OMX_HEVCdec.c b/component/video/dec/hevc/Exynos_OMX_HEVCdec.c new file mode 100644 index 0000000..a94e076 --- /dev/null +++ b/component/video/dec/hevc/Exynos_OMX_HEVCdec.c @@ -0,0 +1,3392 @@ +/* + * + * 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" + +#ifdef USE_ANB +#include "Exynos_OSAL_Android.h" +#endif + +/* 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" + +#define HEVC_DEC_NUM_OF_EXTRA_BUFFERS 7 + +//#define FULL_FRAME_SEARCH /* Full frame search not support*/ + +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; + + FunctionIn(); + + 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_100: + case MFC_101: + pHevcDec->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel51; + break; + case HEVC_10: + case MFC_90: + case MFC_1010: + pHevcDec->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel5; + break; + case MFC_1011: + case MFC_1020: + 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; + } + + while ((pHevcDec->hMFCHevcHandle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pHevcDec->hMFCHevcHandle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : there is no any profile/level", __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); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s : supported profile(%x), level(%x)", __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + 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, "%s : there is no any profile/level", __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, "%s : profile(%x)/level(%x) is %ssupported", __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +#if 0 /* unused code */ +static OMX_ERRORTYPE GetCodecInputPrivateData( + OMX_PTR codecBuffer, + OMX_PTR *pVirtAddr, + OMX_U32 *dataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +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; +} + +#if 0 /* unused code */ +static int Check_HEVC_Frame( + OMX_U8 *pInputStream, + OMX_U32 buffSize, + OMX_U32 flag, + OMX_BOOL bPreviousFrameEOF, + OMX_BOOL *pbEndOfFrame) +{ + OMX_U32 preFourByte = (OMX_U32)-1; + int accessUnitSize = 0; + int frameTypeBoundary = 0; + int nextNaluSize = 0; + int naluStart = 0; +#if 0 + if (bPreviousFrameEOF == OMX_TRUE) + naluStart = 0; + else + naluStart = 1; + + while (1) { + int inputOneByte = 0; + + if (accessUnitSize == (int)buffSize) + goto EXIT; + + inputOneByte = *(pInputStream++); + accessUnitSize += 1; + + if (preFourByte == 0x00000001 || (preFourByte << 8) == 0x00000100) { + int naluType = inputOneByte & 0x1F; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "NaluType : %d", naluType); + if (naluStart == 0) { +#ifdef ADD_SPS_PPS_I_FRAME + if (naluType == 1 || naluType == 5) +#else + if (naluType == 1 || naluType == 5 || naluType == 7 || naluType == 8) +#endif + naluStart = 1; + } else { +#ifdef OLD_DETECT + frameTypeBoundary = (8 - naluType) & (naluType - 10); //AUD(9) +#else + if (naluType == 9) + frameTypeBoundary = -2; +#endif + if (naluType == 1 || naluType == 5) { + if (accessUnitSize == (int)buffSize) { + accessUnitSize--; + goto EXIT; + } + inputOneByte = *pInputStream++; + accessUnitSize += 1; + + if (inputOneByte >= 0x80) + frameTypeBoundary = -1; + } + if (frameTypeBoundary < 0) { + break; + } + } + + } + preFourByte = (preFourByte << 8) + inputOneByte; + } + + *pbEndOfFrame = OMX_TRUE; + nextNaluSize = -5; + if (frameTypeBoundary == -1) + nextNaluSize = -6; + if (preFourByte != 0x00000001) + nextNaluSize++; + return (accessUnitSize + nextNaluSize); + +EXIT: + *pbEndOfFrame = OMX_FALSE; +#endif + return accessUnitSize; +} +#endif + +static OMX_BOOL Check_HEVC_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize) +{ + if (streamSize < 4) { + return OMX_FALSE; + } + + if ((pInputStream[0] == 0x00) && + (pInputStream[1] == 0x00) && + (pInputStream[2] == 0x01)) + return OMX_TRUE; + + if ((pInputStream[0] == 0x00) && + (pInputStream[1] == 0x00) && + (pInputStream[2] == 0x00) && + (pInputStream[3] == 0x01)) + return OMX_TRUE; + + return OMX_FALSE; +} + +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_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate decoder ops buffer"); + 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); + + Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps); + + /* check mandatory functions for decoder ops */ + if ((pDecOps->Init == NULL) || (pDecOps->Finalize == NULL) || + (pDecOps->Get_ActualBufferCount == NULL) || (pDecOps->Set_FrameTag == NULL) || +#ifdef USE_S3D_SUPPORT + (pDecOps->Enable_SEIParsing == NULL) || (pDecOps->Get_FramePackingInfo == NULL) || +#endif + (pDecOps->Get_FrameTag == NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pHevcDec->hMFCHevcHandle.hMFCHandle = pHevcDec->hMFCHevcHandle.pDecOps->Init(pVideoInstInfo); + + if (pHevcDec->hMFCHevcHandle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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, "Failed to Enable SEI Parsing"); + 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; + } + + /* 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; + void *hMFCHandle = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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->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_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) && + (pOutputPort->bDynamicDPBMode == OMX_TRUE)) + 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_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HevcCodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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; + CODEC_DEC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoDecBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]); + pBufOps = pHevcDec->hMFCHevcHandle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]); + pBufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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) { + /**********************************/ + /* 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); + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = HevcCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to HevcCodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType & BUFFER_SHARE) { + /**********************************/ + /* Codec Buffer Unregister */ + /**********************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + } + + Exynos_ResolutionUpdate(pOMXComponent); + } 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; + + ExynosVideoDecOps *pDecOps = pHevcDec->hMFCHevcHandle.pDecOps; + 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) && + (pHevcDec->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, "pVideoDec->pMFCDecInputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecInputBuffer[%d]->pVirAddr[0]: 0x%x", i, 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->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pHevcDec->hMFCHevcHandle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, 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; + + /* Get Frame packing information*/ + if (pDecOps->Get_FramePackingInfo(pHevcDec->hMFCHevcHandle.hMFCHandle, &framePacking) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Get Frame Packing Information"); + ret = OMX_FALSE; + goto EXIT; + } + + if (framePacking.available) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "arrangement ID: 0x%08x", framePacking.arrangement_id); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "arrangement_type: %d", framePacking.arrangement_type); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "content_interpretation_type: %d", framePacking.content_interpretation_type); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "current_frame_is_frame0_flag: %d", framePacking.current_frame_is_frame0_flag); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "spatial_flipping_flag: %d", framePacking.spatial_flipping_flag); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "fr0X:%d fr0Y:%d fr0X:%d fr0Y:%d", 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; + /** Send Port Settings changed call back - output color format change */ + (*(pExynosComponent->pCallbacks->EventHandler)) + (pOMXComponent, + pExynosComponent->callbackData, + 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: + return ret; +} +#endif + +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); + 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 ((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) || + (codecOutbufConf.bInterlaced != pHevcDec->hMFCHevcHandle.codecOutbufConf.bInterlaced) || +#endif + (maxDPBNum != pHevcDec->hMFCHevcHandle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] DRC: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight, + pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth, + pHevcDec->hMFCHevcHandle.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__, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType, + pHevcDec->hMFCHevcHandle.maxDPBNum, + pHevcDec->hMFCHevcHandle.codecOutbufConf.eColorFormat, + pHevcDec->hMFCHevcHandle.codecOutbufConf.eFilledDataType); + + 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 (pOutputPort->bufferProcessType & BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = pHevcDec->hMFCHevcHandle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pHevcDec->hMFCHevcHandle.maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + /** 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); + } + } + + 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] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight, + pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nWidth, + pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nHeight); + + 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; + + /** 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; + + 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, "parsed header info has only VPS"); + ret = OMX_ErrorNeedNextHeaderInfo; + goto EXIT; + } else if (codecRet != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to get geometry for parsed header info"); + ret = OMX_ErrorCorruptedHeader; + 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] HevcCodecSetup maxDPBNum: %d", pExynosComponent, __FUNCTION__, pHevcDec->hMFCHevcHandle.maxDPBNum); + + pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc = OMX_TRUE; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pCropRectangle = &(pOutputPort->cropRectangle); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + } else { + pCropRectangle = &(pOutputPort->newCropRectangle); + pInputPortDefinition = &(pInputPort->newPortDefinition); + pOutputPortDefinition = &(pOutputPort->newPortDefinition); + } + + 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 (pHevcDec->hMFCHevcHandle.codecOutbufConf.eFilledDataType & DATA_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, "The format(%x) is changed to %x by H/W Codec", + pHevcDec->hMFCHevcHandle.MFCOutputColorType, + pHevcDec->hMFCHevcHandle.codecOutbufConf.eColorFormat); + + pHevcDec->hMFCHevcHandle.MFCOutputColorType = pHevcDec->hMFCHevcHandle.codecOutbufConf.eColorFormat; + Exynos_SetPlaneToPort(pOutputPort, Exynos_OSAL_GetPlaneCount(eOutputFormat, pOutputPort->ePlaneType)); + } + + pVideoDec->b10bitData = OMX_TRUE; + } + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pVideoDec->bReconfigDPB) || + (pVideoDec->b10bitData) || + (pInputPort->portDefinition.format.video.nFrameWidth != pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.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; + + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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) || + (pVideoDec->b10bitData) || + (pInputPort->portDefinition.format.video.nFrameWidth != pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.format.video.nFrameHeight != pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPort->portDefinition.nBufferCountActual != 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; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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); + } + } + + if ((pVideoDec->bReconfigDPB != OMX_TRUE) && + ((pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth != pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nWidth) || + (pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight != pHevcDec->hMFCHevcHandle.codecOutbufConf.cropRect.nHeight))) { + /* Check Crop */ + pInputPort->portDefinition.format.video.nFrameWidth = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth; + pInputPort->portDefinition.format.video.nFrameHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight; + pInputPort->portDefinition.format.video.nStride = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameWidth; + pInputPort->portDefinition.format.video.nSliceHeight = pHevcDec->hMFCHevcHandle.codecOutbufConf.nFrameHeight; + + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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 (pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc == OMX_FALSE) { + 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 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 oneFrameSize = pSrcInputData->dataLen; + OMX_COLOR_FORMATTYPE eOutputFormat = pExynosOutputPort->portDefinition.format.video.eColorFormat; + + ExynosVideoDecOps *pDecOps = pHevcDec->hMFCHevcHandle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pHevcDec->hMFCHevcHandle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pHevcDec->hMFCHevcHandle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + int i; + + FunctionIn(); + + if ((oneFrameSize <= 0) && + (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + 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); + Exynos_OSAL_SignalSet(pHevcDec->hDestinationStartEvent); + + 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); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eCompressionFormat = VIDEO_CODING_HEVC; + pInbufOps->Set_Shareable(hMFCHandle); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + bufferConf.nSizeImage = pExynosInputPort->portDefinition.nBufferSize; + } else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + bufferConf.nSizeImage = DEFAULT_MFC_INPUT_BUFFER_SIZE; + } + 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + 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, "Can not support this format (0x%x)", eOutputFormat); + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } + + pHevcDec->hMFCHevcHandle.MFCOutputColorType = bufferConf.eColorFormat; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pVideoDec->bReorderMode == OMX_TRUE) + Exynos_SetReorderTimestamp(pExynosComponent, &(pHevcDec->hMFCHevcHandle.indexTimestamp), pSrcInputData->timeStamp, pSrcInputData->nFlags); + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enqueue input buffer for header parsing"); +// 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, "Failed to run input buffer for header parsing"); + ret = OMX_ErrorCodecInit; + goto EXIT; + } + + ret = HevcCodecUpdateResolution(pOMXComponent); + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0]) , *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 1), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 2), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 3), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 4), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 5), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 6), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 7)); + if (ret != OMX_ErrorNone) { + HevcCodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + + if ((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorNeedNextHeaderInfo) { + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + EXYNOS_OMX_DATABUFFER directReturnUseBuffer; + Exynos_Shared_DataToBuffer(pSrcInputData, &directReturnUseBuffer); + Exynos_InputBufferReturn(pOMXComponent, &directReturnUseBuffer); + } else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + OMX_PTR codecBuffer; + codecBuffer = pSrcInputData->pPrivate; + if (codecBuffer != NULL) + Exynos_CodecBufferEnQueue(pExynosComponent, INPUT_PORT_INDEX, codecBuffer); + } + } + + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + /* disable header info re-input scheme + ret = OMX_ErrorInputDataDecodeYet; + HevcCodecStop(pOMXComponent, INPUT_PORT_INDEX); + */ + ret = OMX_ErrorNoneSrcSetupFinish; + +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]; + + if (pExynosOutputPort->bDynamicDPBMode == OMX_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enable Dynamic DPB"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + /* get dpb count */ + nOutbufs = pHevcDec->hMFCHevcHandle.maxDPBNum; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Register output buffer */ + ret = HevcCodecRegistCodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) + pOutbufOps->Enqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + nDataLen, + nPlaneCnt, + NULL); + } else { + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + 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; + + /* without Register output buffer */ + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (int *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { +#ifdef USE_ANB + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + int plane; + + Exynos_OSAL_Memset((OMX_PTR)planes, 0, sizeof(ExynosVideoPlane) * MAX_BUFFER_PLANE); + + /* get dpb count */ + nOutbufs = pExynosOutputPort->portDefinition.nBufferCountActual; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_TRUE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + for (i = 0; i < pExynosOutputPort->assignedBufferNum; i++) { + for (plane = 0; plane < nPlaneCnt; plane++) { + planes[plane].fd = pExynosOutputPort->extendBufferHeader[i].buf_fd[plane]; + planes[plane].addr = pExynosOutputPort->extendBufferHeader[i].pYUVBuf[plane]; + planes[plane].allocSize = nAllocLen[plane]; + } + + if (pOutbufOps->Register(hMFCHandle, planes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Register output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pOutbufOps->Enqueue(hMFCHandle, + (void **)pExynosOutputPort->extendBufferHeader[i].pYUVBuf, + nDataLen, + nPlaneCnt, + NULL); + } + + if (pOutbufOps->Apply_RegisteredBuffer(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Apply output buffer"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } else { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } else { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_FALSE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } +#else + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; +#endif + } + + pHevcDec->hMFCHevcHandle.bConfiguredMFCDst = OMX_TRUE; + + 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; + + 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 ((int)nParamIndex) { + case OMX_IndexParamVideoHevc: + { + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = (OMX_VIDEO_PARAM_HEVCTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_HEVCTYPE *pSrcHevcComponent = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = 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) { + goto EXIT; + } + + if (pDstHevcComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + 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) { + 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; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = 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; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + case OMX_IndexExynosParamReorderMode: /* MSRND */ + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pReorderParam->bReorderMode = pVideoDec->bReorderMode; + } + 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; + + 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 ((int)nIndex) { + case OMX_IndexParamVideoHevc: + { + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = NULL; + OMX_VIDEO_PARAM_HEVCTYPE *pSrcHevcComponent = (OMX_VIDEO_PARAM_HEVCTYPE *)pComponentParameterStructure; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + /* 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) { + goto EXIT; + } + + if (pSrcHevcComponent->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + 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_ErrorBadParameter; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_HEVCTYPE *pDstHevcComponent = NULL; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + 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; + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + case OMX_IndexExynosParamReorderMode: /* MSRND */ + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pVideoDec->bReorderMode = pReorderParam->bReorderMode; + } + 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; + + 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 ((int)nIndex) { + case OMX_IndexConfigCommonOutputCrop: + { + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + OMX_CONFIG_RECTTYPE *pDstRectType = NULL; + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + if (pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + break; + } + + pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + + if ((pDstRectType->nPortIndex != INPUT_PORT_INDEX) && + (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[pDstRectType->nPortIndex]; + + pSrcRectType = &(pExynosPort->cropRectangle); + + pDstRectType->nTop = pSrcRectType->nTop; + pDstRectType->nLeft = pSrcRectType->nLeft; + pDstRectType->nHeight = pSrcRectType->nHeight; + pDstRectType->nWidth = pSrcRectType->nWidth; + } + break; +#ifdef USE_S3D_SUPPORT + case OMX_IndexVendorS3DMode: + { + EXYNOS_HEVCDEC_HANDLE *pHevcDec = NULL; + OMX_U32 *pS3DMode = NULL; + pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + pS3DMode = (OMX_U32 *)pComponentConfigStructure; + *pS3DMode = (OMX_U32) pHevcDec->hMFCHevcHandle.S3DFPArgmtType; + } + break; +#endif + case OMX_IndexExynosConfigDisplayDelay: /* MSRND */ + { + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + (*((OMX_U32 *)pComponentConfigStructure)) = pHevcDec->hMFCHevcHandle.nDisplayDelay; + } + break; + 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; + + 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 ((int)nIndex) { + case OMX_IndexExynosConfigDisplayDelay: /* MSRND */ + { + EXYNOS_HEVCDEC_HANDLE *pHevcDec = (EXYNOS_HEVCDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + OMX_U32 nDisplayDelay; + + if (pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc == OMX_TRUE) { + ret = OMX_ErrorIncorrectStateOperation; + break; + } + + nDisplayDelay = (*((OMX_U32 *)pComponentConfigStructure)); + if (nDisplayDelay > MAX_HEVC_DISPLAYDELAY_VALIDNUM) { + ret = OMX_ErrorBadParameter; + break; + } + + pHevcDec->hMFCHevcHandle.nDisplayDelay = nDisplayDelay; + } + break; + 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) { + 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; + } + +#ifdef USE_S3D_SUPPORT + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_GET_S3D) == 0) { + *pIndexType = OMX_IndexVendorS3DMode; + 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; + } + +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_REORDER_MODE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamReorderMode; + 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; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + 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, plane; + + FunctionIn(); + + pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc = OMX_FALSE; + pHevcDec->hMFCHevcHandle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + pVideoDec->bDiscardCSDError = 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] = {DEFAULT_MFC_INPUT_BUFFER_SIZE, 0, 0}; + 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) { + 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->hDestinationStartEvent); + + 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 = (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; + + FunctionIn(); + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pHevcDec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pHevcDec->hDestinationStartEvent); + pHevcDec->hDestinationStartEvent = NULL; + pHevcDec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalTerminate(pHevcDec->hSourceStartEvent); + pHevcDec->hSourceStartEvent = NULL; + pHevcDec->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); + } 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); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + 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; + int i; + + FunctionIn(); + + if (pHevcDec->hMFCHevcHandle.bConfiguredMFCSrc == OMX_FALSE) { + ret = HevcCodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_FALSE) && + (pVideoDec->bForceHeaderParsing == OMX_FALSE)) { + ret = HevcCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to HevcCodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + } + + if (((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) || + ((bInStartCode = Check_HEVC_StartCode(pSrcInputData->multiPlaneBuffer.dataBuffer[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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x, oneFrameSize: %d", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pHevcDec->hMFCHevcHandle.indexTimestamp, pSrcInputData->nFlags, oneFrameSize); + + pDecOps->Set_FrameTag(hMFCHandle, pHevcDec->hMFCHevcHandle.indexTimestamp); + pHevcDec->hMFCHevcHandle.indexTimestamp++; + pHevcDec->hMFCHevcHandle.indexTimestamp %= MAX_TIMESTAMP; + + if ((pVideoDec->bQosChanged == OMX_TRUE) && + (pDecOps->Set_QosRatio != NULL)) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + pVideoDec->bQosChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] bufferHeader: 0x%x, dataBuffer: 0x%x", pExynosComponent, __FUNCTION__, pSrcInputData->bufferHeader, pSrcInputData->multiPlaneBuffer.dataBuffer[0]); + + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + if (pExynosInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pHevcDec->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + ret = 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 (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[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, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + 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] : %d => ADDR[%d]: 0x%x", pExynosComponent, __FUNCTION__, __LINE__, i, + pDstInputData->multiPlaneBuffer.dataBuffer[i]); + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + ret = HevcCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to HevcCodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + pVideoDec->bReconfigDPB = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + codecReturn = pOutbufOps->Enqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } else { + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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 *pExynosOutputPort = &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; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + FunctionIn(); + + if (pHevcDec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + pVideoBuffer = pOutbufOps->Dequeue(hMFCHandle); + if (pVideoBuffer == (ExynosVideoBuffer *)VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "HW is not available"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + if (pVideoBuffer == NULL) { + ret = OMX_ErrorNone; + goto EXIT; + } + } else { + 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, "HW is not available"); + 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(pExynosOutputPort))) { + 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) { + pExynosOutputPort->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(pExynosOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->multiPlaneBuffer.fd[plane] = pVideoBuffer->planes[plane].fd; + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->multiPlaneBuffer.dataBuffer[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pHevcDec->hMFCHevcHandle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->ColorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + 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; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output timestamp %lld us (%.2f secs), indexTimestamp: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, indexTimestamp, pDstOutputData->nFlags); + } + } 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 reorder timestamp %lld us (%.2f secs), sCurrentTimestamp.nIndex: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, sCurrentTimestamp.nIndex, pDstOutputData->nFlags); + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pExynosOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if (pHevcDec->hMFCHevcHandle.videoInstInfo.specificInfo.dec.bLastFrameSupport == VIDEO_FALSE) { + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) != OMX_TRUE) { + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + 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] indexTimestamp(%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 = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) != OMX_TRUE) { + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } else { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + } + } else { + if ((displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + + if ((pExynosComponent->bBehaviorEOS == OMX_TRUE) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME)) { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (displayStatus != VIDEO_FRAME_STATUS_LAST_FRAME) { + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } else { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 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_ErrorNone; + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + 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; + } + + 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_SignalReset(pHevcDec->hSourceStartEvent); + } + + ret = Exynos_HevcDec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + + if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pHevcDec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pHevcDec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pHevcDec->hDestinationStartEvent); + } + 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; + } + + 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 (pHevcDec->hMFCHevcHandle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_HevcDec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +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 (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pHevcDec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pHevcDec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pHevcDec->hDestinationStartEvent); + } + if (Exynos_OSAL_GetElemNum(&pHevcDec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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, "OMX_ErrorBadParameter, Line:%d", __LINE__); + goto EXIT; + } + if ((Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_HEVC_DEC, componentName) == 0) || + (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_HEVC_CUSTOM_DEC, componentName) == 0)) { + bSecureMode = OMX_FALSE; + } else if ((Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_HEVC_DRM_DEC, componentName) == 0) || + (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_HEVC_CUSTOM_DRM_DEC, componentName) == 0)) { + bSecureMode = OMX_TRUE; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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) + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + + 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 | BUFFER_ANBSHARE; + 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; + +#if 0 /* unused code */ + pVideoDec->exynos_checkInputFrame = &Check_HEVC_Frame; + pVideoDec->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &HevcCodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &HevcCodecCheckResolution; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + Exynos_OSAL_Free(pHevcDec); + pHevcDec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->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]: Exynos_Video_GetInstInfo is failed", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pHevcDec); + pHevcDec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec %d %d %d %d", pExynosComponent, __FUNCTION__, + (pHevcDec->hMFCHevcHandle.videoInstInfo.specificInfo.dec.bDualDPBSupport), + (pHevcDec->hMFCHevcHandle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport), + (pHevcDec->hMFCHevcHandle.videoInstInfo.specificInfo.dec.bLastFrameSupport), + (pHevcDec->hMFCHevcHandle.videoInstInfo.specificInfo.dec.bSkypeSupport)); + + if (pHevcDec->hMFCHevcHandle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport == VIDEO_TRUE) + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bDynamicDPBMode = OMX_TRUE; + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + 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; + + 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) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/dec/hevc/Exynos_OMX_HEVCdec.h b/component/video/dec/hevc/Exynos_OMX_HEVCdec.h new file mode 100644 index 0000000..121dc0b --- /dev/null +++ b/component/video/dec/hevc/Exynos_OMX_HEVCdec.h @@ -0,0 +1,96 @@ +/* + * + * 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; + +#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 1 + 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 hDestinationStartEvent; + + 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/component/video/dec/hevc/NOTICE b/component/video/dec/hevc/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/dec/hevc/library_register.c b/component/video/dec/hevc/library_register.c new file mode 100644 index 0000000..1450a29 --- /dev/null +++ b/component/video/dec/hevc/library_register.c @@ -0,0 +1,76 @@ +/* + * + * 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; + +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + /* component 3 - video custom decoder HEVC */ + Exynos_OSAL_Strcpy(ppExynosComponent[2]->componentName, EXYNOS_OMX_COMPONENT_HEVC_CUSTOM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[2]->roles[0], EXYNOS_OMX_COMPONENT_HEVC_DEC_ROLE); + ppExynosComponent[2]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 4 - video custom decoder HEVC for DRM */ + Exynos_OSAL_Strcpy(ppExynosComponent[3]->componentName, EXYNOS_OMX_COMPONENT_HEVC_CUSTOM_DRM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[3]->roles[0], EXYNOS_OMX_COMPONENT_HEVC_DEC_ROLE); + ppExynosComponent[3]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; +#endif +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/component/video/dec/hevc/library_register.h b/component/video/dec/hevc/library_register.h new file mode 100644 index 0000000..c390b68 --- /dev/null +++ b/component/video/dec/hevc/library_register.h @@ -0,0 +1,60 @@ +/* + * + * 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 4 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* HEVC */ +#define EXYNOS_OMX_COMPONENT_HEVC_DEC "OMX.Exynos.HEVC.Decoder" +#define EXYNOS_OMX_COMPONENT_HEVC_DRM_DEC "OMX.Exynos.HEVC.Decoder.secure" + +#define EXYNOS_OMX_COMPONENT_HEVC_CUSTOM_DEC "OMX.Exynos.hevc.dec" +#define EXYNOS_OMX_COMPONENT_HEVC_CUSTOM_DRM_DEC "OMX.Exynos.hevc.dec.secure" + +#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/component/video/dec/mpeg2/Android.mk b/component/video/dec/mpeg2/Android.mk new file mode 100644 index 0000000..eb92ddc --- /dev/null +++ b/component/video/dec/mpeg2/Android.mk @@ -0,0 +1,62 @@ +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_CFLAGS := + +ifeq ($(BOARD_USE_ANB), true) +LOCAL_CFLAGS += -DUSE_ANB +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 ($(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 + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.c b/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.c new file mode 100644 index 0000000..02bee95 --- /dev/null +++ b/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.c @@ -0,0 +1,3085 @@ +/* + * + * 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" + +/* 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" + +#define MPEG2_DEC_NUM_OF_EXTRA_BUFFERS 7 + +//#define FULL_FRAME_SEARCH /* Full frame search not support*/ + +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; + + FunctionIn(); + + 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; + } + + 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, "%s : there is no any profile/level", __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); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s : supported profile(%x), level(%x)", __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + 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, "%s : there is no any profile/level", __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, "%s : profile(%x)/level(%x) is %ssupported", __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +#if 0 /* unused code */ +static OMX_ERRORTYPE GetCodecInputPrivateData(OMX_PTR codecBuffer, OMX_PTR *pVirtAddr, OMX_U32 *dataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +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; +} + +#if 0 /* unused code */ +int Check_Mpeg2_Frame( + OMX_U8 *pInputStream, + OMX_U32 buffSize, + OMX_U32 flag, + OMX_BOOL bPreviousFrameEOF, + OMX_BOOL *pbEndOfFrame) +{ + FunctionIn(); + + *pbEndOfFrame = OMX_TRUE; + + /* Frame Start code*/ + if (pInputStream[0] != 0x00 || pInputStream[1] != 0x00 || pInputStream[2]!=0x01) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Mpeg2 Frame Start Code not Found"); + *pbEndOfFrame = OMX_FALSE; + } + + FunctionOut(); + return buffSize; +} +#endif + +static OMX_BOOL Check_Mpeg2_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize) +{ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "streamSize: %d",streamSize); + + if (streamSize < 3) { + return OMX_FALSE; + } + + /* Frame Start code*/ + if (pInputStream[0] != 0x00 || pInputStream[1] != 0x00 || pInputStream[2]!=0x01) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Mpeg2 Frame Start Code not Found"); + 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_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate decoder ops buffer"); + 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); + + Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps); + + /* 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, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.pDecOps->Init(pVideoInstInfo); + if (pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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; + } + + /* 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.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 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; + ExynosVideoDecOps *pDecOps = 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; + pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + 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) && + (pOutputPort->bDynamicDPBMode == OMX_TRUE)) + 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + + 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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg2CodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + CODEC_DEC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoDecBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]); + pBufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]); + pBufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + } + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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) { + /**********************************/ + /* 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); + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = Mpeg2CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to Mpeg2CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType & BUFFER_SHARE) { + /**********************************/ + /* Codec Buffer Unregister */ + /**********************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + } + + Exynos_ResolutionUpdate(pOMXComponent); + } 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + int i, nOutbufs; + + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pMpeg2Dec->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, "pVideoDec->pMFCDecInputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecInputBuffer[%d]->pVirAddr[0]: 0x%x", i, 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->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +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); + 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 ((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) || + (codecOutbufConf.bInterlaced != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.bInterlaced) || +#endif + (maxDPBNum != pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] DRC: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth, + pMpeg2Dec->hMFCMpeg2Handle.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__, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType, + pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eColorFormat, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.eFilledDataType); + + 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 (pOutputPort->bufferProcessType & BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + /** 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); + } + } + + 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] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nWidth, + pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nHeight); + + 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; + + /** 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; + + 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, "Failed to get geometry for parsed header info"); + ret = OMX_ErrorCorruptedHeader; + 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] Mpeg2CodecSetup maxDPBNum: %d", pExynosComponent, __FUNCTION__, pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum); + + /* get interlace info */ + if (pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "detect an interlaced type"); + + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc = OMX_TRUE; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pCropRectangle = &(pOutputPort->cropRectangle); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + } else { + pCropRectangle = &(pOutputPort->newCropRectangle); + pInputPortDefinition = &(pInputPort->newPortDefinition); + pOutputPortDefinition = &(pOutputPort->newPortDefinition); + } + + 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) { + if ((pVideoDec->bReconfigDPB) || + (pInputPort->portDefinition.format.video.nFrameWidth != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.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; + + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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) || + (pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) || + (pInputPort->portDefinition.format.video.nFrameWidth != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.format.video.nFrameHeight != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPort->portDefinition.nBufferCountActual != 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; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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); + } + } + + if ((pVideoDec->bReconfigDPB != OMX_TRUE) && + ((pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameWidth != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nWidth) || + (pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.nFrameHeight != pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.cropRect.nHeight))) { + /* Check Crop */ + 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); + + /** 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 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 oneFrameSize = pSrcInputData->dataLen; + 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; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + int i; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + 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); + Exynos_OSAL_SignalSet(pMpeg2Dec->hDestinationStartEvent); + + 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); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eCompressionFormat = VIDEO_CODING_MPEG2; + pInbufOps->Set_Shareable(hMFCHandle); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + bufferConf.nSizeImage = pExynosInputPort->portDefinition.nBufferSize; + } else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + bufferConf.nSizeImage = DEFAULT_MFC_INPUT_BUFFER_SIZE; + } + 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + if ((pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.specificInfo.dec.bDualDPBSupport == VIDEO_TRUE) && + (eOutputFormat != (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled)) { + /* Needs to eanble DualDPB feature */ + if (pDecOps->Enable_DualDPBMode(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorHardware; + goto EXIT; + } + } + 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; + goto EXIT; + } + } + + pMpeg2Dec->hMFCMpeg2Handle.MFCOutputColorType = bufferConf.eColorFormat; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enqueue input buffer for header parsing"); +// 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, "Failed to run input buffer for header parsing"); + ret = OMX_ErrorCodecInit; + goto EXIT; + } + + ret = Mpeg2CodecUpdateResolution(pOMXComponent); + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0]) , *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 1), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 2), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 3), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 4), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 5), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 6), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 7)); + if (ret != OMX_ErrorNone) { + Mpeg2CodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + ret = OMX_ErrorInputDataDecodeYet; + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + 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]; + + if (pExynosOutputPort->bDynamicDPBMode == OMX_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enable Dynamic DPB"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + /* get dpb count */ + nOutbufs = pMpeg2Dec->hMFCMpeg2Handle.maxDPBNum; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Register output buffer */ + ret = Mpeg2CodecRegistCodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) + pOutbufOps->Enqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + nDataLen, + nPlaneCnt, + NULL); + } else { + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + 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; + + /* without Register output buffer */ + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (int *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { +#ifdef USE_ANB + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + int plane; + + Exynos_OSAL_Memset((OMX_PTR)planes, 0, sizeof(ExynosVideoPlane) * MAX_BUFFER_PLANE); + + /* get dpb count */ + nOutbufs = pExynosOutputPort->portDefinition.nBufferCountActual; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_TRUE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + for (i = 0; i < pExynosOutputPort->assignedBufferNum; i++) { + for (plane = 0; plane < nPlaneCnt; plane++) { + planes[plane].fd = pExynosOutputPort->extendBufferHeader[i].buf_fd[plane]; + planes[plane].addr = pExynosOutputPort->extendBufferHeader[i].pYUVBuf[plane]; + planes[plane].allocSize = nAllocLen[plane]; + } + + if (pOutbufOps->Register(hMFCHandle, planes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Register output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pOutbufOps->Enqueue(hMFCHandle, + (void **)pExynosOutputPort->extendBufferHeader[i].pYUVBuf, + nDataLen, + nPlaneCnt, + NULL); + } + + if (pOutbufOps->Apply_RegisteredBuffer(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Apply output buffer"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } else { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + } else { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_FALSE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } +#else + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; +#endif + } + + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst = OMX_TRUE; + + 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; + + 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_IndexParamVideoMpeg2: + { + OMX_VIDEO_PARAM_MPEG2TYPE *pDstMpeg2Param = (OMX_VIDEO_PARAM_MPEG2TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG2TYPE *pSrcMpeg2Param = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = 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) { + goto EXIT; + } + + if (pDstMpeg2Param->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + 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) { + 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; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = 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; + } + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 portIndex = portDefinition->nPortIndex; + 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 *pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (((pExynosPort->bIsANBEnabled == OMX_TRUE) || (pExynosPort->bStoreMetaData == OMX_TRUE)) && + (pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) && + (portIndex == OUTPUT_PORT_INDEX)) { + portDefinition->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)Exynos_OSAL_OMX2HALPixelFormat((OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace, pExynosPort->ePlaneType); + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "portDefinition->format.video.eColorFormat: 0x%x", portDefinition->format.video.eColorFormat); + } + 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; + + 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_IndexParamVideoMpeg2: + { + OMX_VIDEO_PARAM_MPEG2TYPE *pDstMpeg2Param = NULL; + OMX_VIDEO_PARAM_MPEG2TYPE *pSrcMpeg2Param = (OMX_VIDEO_PARAM_MPEG2TYPE *)pComponentParameterStructure; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + /* 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) { + goto EXIT; + } + + if (pSrcMpeg2Param->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + 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_ErrorBadParameter; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG2TYPE *pDstMpeg2Component = NULL; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + 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; + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + + 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 (nIndex) { + case OMX_IndexConfigCommonOutputCrop: + { + EXYNOS_MPEG2DEC_HANDLE *pMpeg2Dec = NULL; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + OMX_CONFIG_RECTTYPE *pDstRectType = NULL; + + pMpeg2Dec = (EXYNOS_MPEG2DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + if (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + break; + } + + pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + + if ((pDstRectType->nPortIndex != INPUT_PORT_INDEX) && + (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[pDstRectType->nPortIndex]; + + pSrcRectType = &(pExynosPort->cropRectangle); + + 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; + + 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 (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) { + 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_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; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + 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; + OMX_PTR hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + ExynosVideoInstInfo *pVideoInstInfo = &(pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i, plane; + + FunctionIn(); + + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc = OMX_FALSE; + pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + pVideoDec->bDiscardCSDError = 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; + } + + pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {DEFAULT_MFC_INPUT_BUFFER_SIZE, 0, 0}; + 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) { + 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->hDestinationStartEvent); + + 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 = (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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + OMX_PTR hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + + int i, plane; + + FunctionIn(); + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pMpeg2Dec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pMpeg2Dec->hDestinationStartEvent); + pMpeg2Dec->hDestinationStartEvent = NULL; + pMpeg2Dec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalTerminate(pMpeg2Dec->hSourceStartEvent); + pMpeg2Dec->hSourceStartEvent = NULL; + pMpeg2Dec->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); + } 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); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + 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]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg2Dec->hMFCMpeg2Handle.pOutbufOps; + 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; + int i; + + FunctionIn(); + + if (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = Mpeg2CodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst == OMX_FALSE) && + (pVideoDec->bForceHeaderParsing == OMX_FALSE)) { + ret = Mpeg2CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to Mpeg2CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + } + + if (((bInStartCode = Check_Mpeg2_StartCode(pSrcInputData->multiPlaneBuffer.dataBuffer[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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x, oneFrameSize: %d", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pMpeg2Dec->hMFCMpeg2Handle.indexTimestamp, pSrcInputData->nFlags, oneFrameSize); + pDecOps->Set_FrameTag(hMFCHandle, pMpeg2Dec->hMFCMpeg2Handle.indexTimestamp); + pMpeg2Dec->hMFCMpeg2Handle.indexTimestamp++; + pMpeg2Dec->hMFCMpeg2Handle.indexTimestamp %= MAX_TIMESTAMP; + + if ((pVideoDec->bQosChanged == OMX_TRUE) && + (pDecOps->Set_QosRatio != NULL)) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + pVideoDec->bQosChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] bufferHeader: 0x%x, dataBuffer: 0x%x", pExynosComponent, __FUNCTION__, pSrcInputData->bufferHeader, pSrcInputData->multiPlaneBuffer.dataBuffer[0]); + + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + if (pExynosInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pMpeg2Dec->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + ret = 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pMpeg2Dec->hMFCMpeg2Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg2Dec->hMFCMpeg2Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[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, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#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]; + + ExynosVideoDecOps *pDecOps = pMpeg2Dec->hMFCMpeg2Handle.pDecOps; + 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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + 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] : %d => ADDR[%d]: 0x%x", pExynosComponent, __FUNCTION__, __LINE__, i, + pDstInputData->multiPlaneBuffer.dataBuffer[i]); + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + ret = Mpeg2CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to Mpeg2CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + pVideoDec->bReconfigDPB = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + codecReturn = pOutbufOps->Enqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } else { + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &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; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + FunctionIn(); + + if (pMpeg2Dec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + pVideoBuffer = pOutbufOps->Dequeue(hMFCHandle); + if (pVideoBuffer == (ExynosVideoBuffer *)VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "HW is not available"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + if (pVideoBuffer == NULL) { + ret = OMX_ErrorNone; + goto EXIT; + } + } else { + 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, "HW is not available"); + 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(pExynosOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL)) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pExynosOutputPort->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(pExynosOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->multiPlaneBuffer.fd[plane] = pVideoBuffer->planes[plane].fd; + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->multiPlaneBuffer.dataBuffer[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + /* get interlace frame info */ + if ((pExynosOutputPort->bufferProcessType & BUFFER_SHARE) && + (pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) && + (pVideoBuffer->planes[2].addr != NULL)) { + /* only NV12 case */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] interlace type = %x", pExynosComponent, __FUNCTION__, pVideoBuffer->interlacedType); + *(int *)(pVideoBuffer->planes[2].addr) = pVideoBuffer->interlacedType; + } + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pMpeg2Dec->hMFCMpeg2Handle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->ColorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + 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; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output timestamp %lld us (%.2f secs), indexTimestamp: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, indexTimestamp, pDstOutputData->nFlags); + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pExynosOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.specificInfo.dec.bLastFrameSupport == VIDEO_FALSE) { + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + 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] indexTimestamp(%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 = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + } + } else { + if ((displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + + if ((pExynosComponent->bBehaviorEOS == OMX_TRUE) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME)) { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (displayStatus != VIDEO_FRAME_STATUS_LAST_FRAME) { + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } else { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 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_ErrorNone; + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + 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; + } + + 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_SignalReset(pMpeg2Dec->hSourceStartEvent); + } + + ret = Exynos_Mpeg2Dec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pMpeg2Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg2Dec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pMpeg2Dec->hDestinationStartEvent); + } + 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; + } + + 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 (pMpeg2Dec->hMFCMpeg2Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_Mpeg2Dec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +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 (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pMpeg2Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg2Dec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pMpeg2Dec->hDestinationStartEvent); + } + if (Exynos_OSAL_GetElemNum(&pMpeg2Dec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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, "OMX_ErrorBadParameter, Line:%d", __LINE__); + goto EXIT; + } + if ((Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MPEG2_DEC, componentName) != 0) && + (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MPEG2_CUSTOM_DEC, componentName) != 0)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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) + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + + 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 | BUFFER_ANBSHARE; + 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; + +#if 0 /* unused code */ + pVideoDec->exynos_checkInputFrame = &Check_Mpeg2_Frame; + pVideoDec->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &Mpeg2CodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &Mpeg2CodecCheckResolution; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + Exynos_OSAL_Free(pMpeg2Dec); + pMpeg2Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->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]: Exynos_Video_GetInstInfo is failed", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pMpeg2Dec); + pMpeg2Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec %d %d %d %d", pExynosComponent, __FUNCTION__, + (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.specificInfo.dec.bDualDPBSupport), + (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport), + (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.specificInfo.dec.bLastFrameSupport), + (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.specificInfo.dec.bSkypeSupport)); + + if (pMpeg2Dec->hMFCMpeg2Handle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport == VIDEO_TRUE) + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bDynamicDPBMode = OMX_TRUE; + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + 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; + + 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) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.h b/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.h new file mode 100644 index 0000000..af36386 --- /dev/null +++ b/component/video/dec/mpeg2/Exynos_OMX_Mpeg2dec.h @@ -0,0 +1,91 @@ +/* + * + * 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; + + 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 hDestinationStartEvent; + + 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/component/video/dec/mpeg2/NOTICE b/component/video/dec/mpeg2/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/dec/mpeg2/library_register.c b/component/video/dec/mpeg2/library_register.c new file mode 100644 index 0000000..73bf949 --- /dev/null +++ b/component/video/dec/mpeg2/library_register.c @@ -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.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; +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + /* component 2 - video custom decoder MPEG2 */ + Exynos_OSAL_Strcpy(ppExynosComponent[1]->componentName, EXYNOS_OMX_COMPONENT_MPEG2_CUSTOM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[1]->roles[0], EXYNOS_OMX_COMPONENT_MPEG2_DEC_ROLE); + ppExynosComponent[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; +#endif +EXIT: + FunctionOut(); + return MAX_COMPONENT_NUM; +} diff --git a/component/video/dec/mpeg2/library_register.h b/component/video/dec/mpeg2/library_register.h new file mode 100644 index 0000000..07fbb46 --- /dev/null +++ b/component/video/dec/mpeg2/library_register.h @@ -0,0 +1,56 @@ +/* + * + * 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 2 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* MPEG2 */ +#define EXYNOS_OMX_COMPONENT_MPEG2_DEC "OMX.Exynos.MPEG2.Decoder" +#define EXYNOS_OMX_COMPONENT_MPEG2_CUSTOM_DEC "OMX.Exynos.mpeg2.dec" +#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/component/video/dec/mpeg4/Android.mk b/component/video/dec/mpeg4/Android.mk new file mode 100644 index 0000000..31c771d --- /dev/null +++ b/component/video/dec/mpeg4/Android.mk @@ -0,0 +1,66 @@ +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_CFLAGS := + +ifeq ($(BOARD_USE_ANB), true) +LOCAL_CFLAGS += -DUSE_ANB +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 ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_TIMESTAMP_REORDER_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_TIMESTAMP_REORDER_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.c b/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.c new file mode 100644 index 0000000..8163701 --- /dev/null +++ b/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.c @@ -0,0 +1,3470 @@ +/* + * + * 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" + +/* 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" + +#define MPEG4_DEC_NUM_OF_EXTRA_BUFFERS 7 + +//#define FULL_FRAME_SEARCH + +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; + + FunctionIn(); + + 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; + } + + while ((pMpeg4Dec->hMFCMpeg4Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pMpeg4Dec->hMFCMpeg4Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : there is no any profile/level", __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); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s : supported profile(%x), level(%x)", __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + 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, "%s : there is no any profile/level", __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, "%s : profile(%x)/level(%x) is %ssupported", __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +#if 0 /* unused code */ +static OMX_ERRORTYPE GetCodecInputPrivateData(OMX_PTR codecBuffer, OMX_PTR *pVirtAddr, OMX_U32 *dataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +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; + +#if 0 /* unused code */ +static int Check_Mpeg4_Frame( + OMX_U8 *pInputStream, + OMX_U32 buffSize, + OMX_U32 flag, + OMX_BOOL bPreviousFrameEOF, + OMX_BOOL *pbEndOfFrame) +{ + OMX_U32 len; + int readStream; + unsigned startCode; + OMX_BOOL bFrameStart; + + len = 0; + bFrameStart = OMX_FALSE; + + if (flag & OMX_BUFFERFLAG_CODECCONFIG) { + if (*pInputStream == 0x03) { /* FIMV1 */ + BitmapInfoHhr *pInfoHeader; + + pInfoHeader = (BitmapInfoHhr *)(pInputStream + 1); + /* FIXME */ + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "############## NOT SUPPORTED #################"); + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "width(%d), height(%d)", pInfoHeader->BiWidth, pInfoHeader->BiHeight); + gbFIMV1 = OMX_TRUE; + *pbEndOfFrame = OMX_TRUE; + return buffSize; + } + } + + if (gbFIMV1) { + *pbEndOfFrame = OMX_TRUE; + return buffSize; + } + + if (bPreviousFrameEOF == OMX_FALSE) + bFrameStart = OMX_TRUE; + + startCode = 0xFFFFFFFF; + if (bFrameStart == OMX_FALSE) { + /* find VOP start code */ + while(startCode != 0x1B6) { + readStream = *(pInputStream + len); + startCode = (startCode << 8) | readStream; + len++; + if (len > buffSize) + goto EXIT; + } + } + + /* find next VOP start code */ + startCode = 0xFFFFFFFF; + while ((startCode != 0x1B6)) { + readStream = *(pInputStream + len); + startCode = (startCode << 8) | readStream; + len++; + if (len > buffSize) + goto EXIT; + } + + *pbEndOfFrame = OMX_TRUE; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "1. Check_Mpeg4_Frame returned EOF = %d, len = %d, buffSize = %d", *pbEndOfFrame, len - 4, buffSize); + + return len - 4; + +EXIT : + *pbEndOfFrame = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "2. Check_Mpeg4_Frame returned EOF = %d, len = %d, buffSize = %d", *pbEndOfFrame, len - 1, buffSize); + + return --len; +} + +static int Check_H263_Frame( + OMX_U8 *pInputStream, + OMX_U32 buffSize, + OMX_U32 flag, + OMX_BOOL bPreviousFrameEOF, + OMX_BOOL *pbEndOfFrame) +{ + OMX_U32 len; + int readStream; + unsigned startCode; + OMX_BOOL bFrameStart = 0; + unsigned pTypeMask = 0x03; + unsigned pType = 0; + + len = 0; + bFrameStart = OMX_FALSE; + + if (bPreviousFrameEOF == OMX_FALSE) + bFrameStart = OMX_TRUE; + + startCode = 0xFFFFFFFF; + if (bFrameStart == OMX_FALSE) { + /* find 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 > buffSize) + goto EXIT; + } + } + + /* find next PSC */ + startCode = 0xFFFFFFFF; + pType = 0; + while (((startCode << 8 >> 10) != 0x20) || (pType != 0x02)) { + readStream = *(pInputStream + len); + startCode = (startCode << 8) | readStream; + + readStream = *(pInputStream + len + 1); + pType = readStream & pTypeMask; + + len++; + if (len > buffSize) + goto EXIT; + } + + *pbEndOfFrame = OMX_TRUE; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "1. Check_H263_Frame returned EOF = %d, len = %d, iBuffSize = %d", *pbEndOfFrame, len - 3, buffSize); + + return len - 3; + +EXIT : + + *pbEndOfFrame = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "2. Check_H263_Frame returned EOF = %d, len = %d, iBuffSize = %d", *pbEndOfFrame, len - 1, buffSize); + + return --len; +} +#endif + +static OMX_BOOL Check_Stream_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize, + CODEC_TYPE codecType) +{ + switch (codecType) { + case CODEC_TYPE_MPEG4: + if (gbFIMV1) { + return OMX_TRUE; + } else { + if (streamSize < 3) { + return OMX_FALSE; + } else if ((pInputStream[0] == 0x00) && + (pInputStream[1] == 0x00) && + (pInputStream[2] == 0x01)) { + return OMX_TRUE; + } else { + return OMX_FALSE; + } + } + 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__); + return OMX_FALSE; + } else { + return OMX_TRUE; + } + } else { + return OMX_FALSE; + } + default: + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: undefined codec type (%d)", __FUNCTION__, codecType); + return OMX_FALSE; + } +} + +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_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate decoder ops buffer"); + 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); + + Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps); + + /* 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, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.pDecOps->Init(pVideoInstInfo); + if (pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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; + } + + /* 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + pOutbufOps = pMpeg4Dec->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; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = 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; + pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + 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) && + (pOutputPort->bDynamicDPBMode == OMX_TRUE)) + 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + + 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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + CODEC_DEC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoDecBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]); + pBufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]); + pBufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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) { + /**********************************/ + /* 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); + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = Mpeg4CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to Mpeg4CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType & BUFFER_SHARE) { + /**********************************/ + /* Codec Buffer Unregister */ + /**********************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + } + + Exynos_ResolutionUpdate(pOMXComponent); + } 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; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + int i, nOutbufs; + + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pMpeg4Dec->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, "pVideoDec->pMFCDecInputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecInputBuffer[%d]->pVirAddr[0]: 0x%x", i, 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->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +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); + 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 ((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) || + (codecOutbufConf.bInterlaced != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.bInterlaced) || +#endif + (maxDPBNum != pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] DRC: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth, + pMpeg4Dec->hMFCMpeg4Handle.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__, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType, + pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eColorFormat, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.eFilledDataType); + + 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 (pOutputPort->bufferProcessType & BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + /** 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); + } + } + + 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] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nWidth, + pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nHeight); + + 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; + + /** 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; + + 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, "Failed to get geometry for parsed header info"); + ret = OMX_ErrorCorruptedHeader; + 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] Mpeg4CodecSetup maxDPBNum: %d", pExynosComponent, __FUNCTION__, pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum); + + /* get interlace info */ + if (pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "detect an interlaced type"); + + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc = OMX_TRUE; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pCropRectangle = &(pOutputPort->cropRectangle); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + } else { + pCropRectangle = &(pOutputPort->newCropRectangle); + pInputPortDefinition = &(pInputPort->newPortDefinition); + pOutputPortDefinition = &(pOutputPort->newPortDefinition); + } + + 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) { + if ((pVideoDec->bReconfigDPB) || + (pInputPort->portDefinition.format.video.nFrameWidth != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.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; + + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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) || + (pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) || + (pInputPort->portDefinition.format.video.nFrameWidth != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.format.video.nFrameHeight != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPort->portDefinition.nBufferCountActual != 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; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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); + } + } + + if ((pVideoDec->bReconfigDPB != OMX_TRUE) && + ((pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameWidth != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nWidth) || + (pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.nFrameHeight != pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.cropRect.nHeight))) { + /* Check Crop */ + 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); + + /** 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 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 oneFrameSize = pSrcInputData->dataLen; + 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; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + int i; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + 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); + Exynos_OSAL_SignalSet(pMpeg4Dec->hDestinationStartEvent); + + 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); + + /* 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); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + bufferConf.nSizeImage = pExynosInputPort->portDefinition.nBufferSize; + } else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + bufferConf.nSizeImage = DEFAULT_MFC_INPUT_BUFFER_SIZE; + } + 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + if ((pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.specificInfo.dec.bDualDPBSupport == VIDEO_TRUE) && + (eOutputFormat != (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled)) { + /* Needs to eanble DualDPB feature */ + if (pDecOps->Enable_DualDPBMode(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorHardware; + goto EXIT; + } + } + 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; + goto EXIT; + } + } + + pMpeg4Dec->hMFCMpeg4Handle.MFCOutputColorType = bufferConf.eColorFormat; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enqueue input buffer for header parsing"); +// 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, "Failed to run input buffer for header parsing"); + ret = OMX_ErrorCodecInit; + goto EXIT; + } + + ret = Mpeg4CodecUpdateResolution(pOMXComponent); + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0]) , *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 1), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 2), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 3), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 4), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 5), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 6), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 7)); + if (ret != OMX_ErrorNone) { + Mpeg4CodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + ret = OMX_ErrorInputDataDecodeYet; + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + 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]; + + if (pExynosOutputPort->bDynamicDPBMode == OMX_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enable Dynamic DPB"); + 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) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + /* get dpb count */ + nOutbufs = pMpeg4Dec->hMFCMpeg4Handle.maxDPBNum; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Register output buffer */ + ret = Mpeg4CodecRegistCodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) + pOutbufOps->Enqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + nDataLen, + nPlaneCnt, + NULL); + } else { + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + 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; + + /* without Register output buffer */ + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (int *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { +#ifdef USE_ANB + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + int plane; + + Exynos_OSAL_Memset((OMX_PTR)planes, 0, sizeof(ExynosVideoPlane) * MAX_BUFFER_PLANE); + + /* get dpb count */ + nOutbufs = pExynosOutputPort->portDefinition.nBufferCountActual; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_TRUE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + for (i = 0; i < pExynosOutputPort->assignedBufferNum; i++) { + for (plane = 0; plane < nPlaneCnt; plane++) { + planes[plane].fd = pExynosOutputPort->extendBufferHeader[i].buf_fd[plane]; + planes[plane].addr = pExynosOutputPort->extendBufferHeader[i].pYUVBuf[plane]; + planes[plane].allocSize = nAllocLen[plane]; + } + + if (pOutbufOps->Register(hMFCHandle, planes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Register output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pOutbufOps->Enqueue(hMFCHandle, + (void **)pExynosOutputPort->extendBufferHeader[i].pYUVBuf, + nDataLen, + nPlaneCnt, + NULL); + } + + if (pOutbufOps->Apply_RegisteredBuffer(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Apply output buffer"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } else { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } else { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_FALSE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } +#else + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; +#endif + } + + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_TRUE; + + 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; + + 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 ((int)nParamIndex) { + case OMX_IndexParamVideoMpeg4: + { + OMX_VIDEO_PARAM_MPEG4TYPE *pDstMpeg4Param = (OMX_VIDEO_PARAM_MPEG4TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_MPEG4TYPE *pSrcMpeg4Param = NULL; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = 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) { + goto EXIT; + } + + if (pDstMpeg4Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = 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) { + goto EXIT; + } + + if (pDstH263Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + goto EXIT; + } + + codecType = ((EXYNOS_MPEG4DEC_HANDLE *)(((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle))->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) { + 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; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + OMX_S32 codecType; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = 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; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + case OMX_IndexExynosParamReorderMode: /* MSRND */ + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pReorderParam->bReorderMode = pVideoDec->bReorderMode; + } + break; +#endif + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 portIndex = portDefinition->nPortIndex; + 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 *pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (((pExynosPort->bIsANBEnabled == OMX_TRUE) || (pExynosPort->bStoreMetaData == OMX_TRUE)) && + (pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) && + (portIndex == OUTPUT_PORT_INDEX)) { + portDefinition->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)Exynos_OSAL_OMX2HALPixelFormat((OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace, pExynosPort->ePlaneType); + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "portDefinition->format.video.eColorFormat: 0x%x", portDefinition->format.video.eColorFormat); + } + 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; + + 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 ((int)nIndex) { + case OMX_IndexParamVideoMpeg4: + { + OMX_VIDEO_PARAM_MPEG4TYPE *pDstMpeg4Param = NULL; + OMX_VIDEO_PARAM_MPEG4TYPE *pSrcMpeg4Param = (OMX_VIDEO_PARAM_MPEG4TYPE *)pComponentParameterStructure; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + /* 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) { + goto EXIT; + } + + if (pSrcMpeg4Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + /* 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) { + goto EXIT; + } + + if (pSrcH263Param->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + 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_ErrorBadParameter; + 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; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + OMX_S32 codecType; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + 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; + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + case OMX_IndexExynosParamReorderMode: /* MSRND */ + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pVideoDec->bReorderMode = pReorderParam->bReorderMode; + } + break; +#endif + 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; + + 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) { + case OMX_IndexConfigCommonOutputCrop: + { + EXYNOS_MPEG4DEC_HANDLE *pMpeg4Dec = NULL; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + OMX_CONFIG_RECTTYPE *pDstRectType = NULL; + + pMpeg4Dec = (EXYNOS_MPEG4DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + if (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + break; + } + + pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + + if ((pDstRectType->nPortIndex != INPUT_PORT_INDEX) && + (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[pDstRectType->nPortIndex]; + + pSrcRectType = &(pExynosPort->cropRectangle); + + 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; + + 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_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) { + 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; + } + +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_REORDER_MODE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamReorderMode; + ret = OMX_ErrorNone; + goto EXIT; + } + } +#endif + + 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; + OMX_PTR hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + ExynosVideoInstInfo *pVideoInstInfo = &(pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i, plane; + + FunctionIn(); + + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc = OMX_FALSE; + pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + pVideoDec->bDiscardCSDError = 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; + } + + pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {DEFAULT_MFC_INPUT_BUFFER_SIZE, 0, 0}; + 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) { + 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->hDestinationStartEvent); + + 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 = (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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + OMX_PTR hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + + int i, plane; + + FunctionIn(); + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pMpeg4Dec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pMpeg4Dec->hDestinationStartEvent); + pMpeg4Dec->hDestinationStartEvent = NULL; + pMpeg4Dec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalTerminate(pMpeg4Dec->hSourceStartEvent); + pMpeg4Dec->hSourceStartEvent = NULL; + pMpeg4Dec->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); + } 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); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + 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]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pMpeg4Dec->hMFCMpeg4Handle.pOutbufOps; + 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; + int i; + + FunctionIn(); + + if (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = Mpeg4CodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_FALSE) && + (pVideoDec->bForceHeaderParsing == OMX_FALSE)) { + ret = Mpeg4CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to Mpeg4CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + } + + if (((pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC) || + ((bInStartCode = Check_Stream_StartCode(pSrcInputData->multiPlaneBuffer.dataBuffer[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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x, oneFrameSize: %d", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp, pSrcInputData->nFlags, oneFrameSize); + + pDecOps->Set_FrameTag(hMFCHandle, pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp); + pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp++; + pMpeg4Dec->hMFCMpeg4Handle.indexTimestamp %= MAX_TIMESTAMP; + + if ((pVideoDec->bQosChanged == OMX_TRUE) && + (pDecOps->Set_QosRatio != NULL)) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + pVideoDec->bQosChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] bufferHeader: 0x%x, dataBuffer: 0x%x", pExynosComponent, __FUNCTION__, pSrcInputData->bufferHeader, pSrcInputData->multiPlaneBuffer.dataBuffer[0]); + + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + if (pExynosInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pMpeg4Dec->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + ret = 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pMpeg4Dec->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pMpeg4Dec->hMFCMpeg4Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[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, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#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]; + + ExynosVideoDecOps *pDecOps = pMpeg4Dec->hMFCMpeg4Handle.pDecOps; + 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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + 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] : %d => ADDR[%d]: 0x%x", pExynosComponent, __FUNCTION__, __LINE__, i, + pDstInputData->multiPlaneBuffer.dataBuffer[i]); + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + ret = Mpeg4CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to Mpeg4CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + pVideoDec->bReconfigDPB = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + codecReturn = pOutbufOps->Enqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } else { + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &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; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + FunctionIn(); + + if (pMpeg4Dec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + pVideoBuffer = pOutbufOps->Dequeue(hMFCHandle); + if (pVideoBuffer == (ExynosVideoBuffer *)VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "HW is not available"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + if (pVideoBuffer == NULL) { + ret = OMX_ErrorNone; + goto EXIT; + } + } else { + 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, "HW is not available"); + 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(pExynosOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL)) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pExynosOutputPort->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(pExynosOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->multiPlaneBuffer.fd[plane] = pVideoBuffer->planes[plane].fd; + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->multiPlaneBuffer.dataBuffer[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + /* get interlace frame info */ + if ((pExynosOutputPort->bufferProcessType & BUFFER_SHARE) && + (pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf.bInterlaced == VIDEO_TRUE) && + (pVideoBuffer->planes[2].addr != NULL)) { + /* only NV12 case */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] interlace type = %x", pExynosComponent, __FUNCTION__, pVideoBuffer->interlacedType); + *(int *)(pVideoBuffer->planes[2].addr) = pVideoBuffer->interlacedType; + } + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pMpeg4Dec->hMFCMpeg4Handle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->ColorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + 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; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output timestamp %lld us (%.2f secs), indexTimestamp: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, indexTimestamp, pDstOutputData->nFlags); + } + } 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 reorder timestamp %lld us (%.2f secs), sCurrentTimestamp.nIndex: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, sCurrentTimestamp.nIndex, pDstOutputData->nFlags); + } + + if (pMpeg4Dec->hMFCMpeg4Handle.codecType == CODEC_TYPE_H263) { + pMpeg4Dec->hMFCMpeg4Handle.outputIndexTimestamp++; + pMpeg4Dec->hMFCMpeg4Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pExynosOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.specificInfo.dec.bLastFrameSupport == VIDEO_FALSE) { + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + 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] indexTimestamp(%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 = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + } + } else { + if ((displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + + if ((pExynosComponent->bBehaviorEOS == OMX_TRUE) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME)) { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (displayStatus != VIDEO_FRAME_STATUS_LAST_FRAME) { + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } else { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 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_ErrorNone; + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + 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; + } + + 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_SignalReset(pMpeg4Dec->hSourceStartEvent); + } + + ret = Exynos_Mpeg4Dec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pMpeg4Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg4Dec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pMpeg4Dec->hDestinationStartEvent); + } + 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; + } + + 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 (pMpeg4Dec->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_Mpeg4Dec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +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 (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pMpeg4Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg4Dec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pMpeg4Dec->hDestinationStartEvent); + } + if (Exynos_OSAL_GetElemNum(&pMpeg4Dec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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, "OMX_ErrorBadParameter, Line:%d", __LINE__); + goto EXIT; + } + if ((Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MPEG4_DEC, componentName) == 0) || + (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MPEG4_CUSTOM_DEC, componentName) == 0)) { + codecType = CODEC_TYPE_MPEG4; + bSecureMode = OMX_FALSE; + } else if ((Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H263_DEC, componentName) == 0) || + (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_H263_CUSTOM_DEC, componentName) == 0)) { + codecType = CODEC_TYPE_H263; + bSecureMode = OMX_FALSE; + } else if ((Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MPEG4_DRM_DEC, componentName) == 0) || + (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_MPEG4_CUSTOM_DRM_DEC, componentName) == 0)) { + codecType = CODEC_TYPE_MPEG4; + bSecureMode = OMX_TRUE; + } else { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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) + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_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; + + /* 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 | BUFFER_ANBSHARE; + 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; + +#if 0 /* unused code */ + if (codecType == CODEC_TYPE_MPEG4) + pVideoDec->exynos_checkInputFrame = &Check_Mpeg4_Frame; + else + pVideoDec->exynos_checkInputFrame = &Check_H263_Frame; + + pVideoDec->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &Mpeg4CodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &Mpeg4CodecCheckResolution; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + Exynos_OSAL_Free(pMpeg4Dec); + pMpeg4Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->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]: Exynos_Video_GetInstInfo is failed", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pMpeg4Dec); + pMpeg4Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec %d %d %d %d", pExynosComponent, __FUNCTION__, + (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.specificInfo.dec.bDualDPBSupport), + (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport), + (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.specificInfo.dec.bLastFrameSupport), + (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.specificInfo.dec.bSkypeSupport)); + + if (pMpeg4Dec->hMFCMpeg4Handle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport == VIDEO_TRUE) + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bDynamicDPBMode = OMX_TRUE; + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + 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; + + 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) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.h b/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.h new file mode 100644 index 0000000..bcc0181 --- /dev/null +++ b/component/video/dec/mpeg4/Exynos_OMX_Mpeg4dec.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_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; + + 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 hDestinationStartEvent; + + 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/component/video/dec/mpeg4/NOTICE b/component/video/dec/mpeg4/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/dec/mpeg4/library_register.c b/component/video/dec/mpeg4/library_register.c new file mode 100644 index 0000000..a3c40e7 --- /dev/null +++ b/component/video/dec/mpeg4/library_register.c @@ -0,0 +1,84 @@ +/* + * + * 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; +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + /* component 4 - video custom decoder MPEG4 */ + Exynos_OSAL_Strcpy(ppExynosComponent[3]->componentName, EXYNOS_OMX_COMPONENT_MPEG4_CUSTOM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[3]->roles[0], EXYNOS_OMX_COMPONENT_MPEG4_DEC_ROLE); + ppExynosComponent[3]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 5 - video custom decoder MPEG4 for DRM */ + Exynos_OSAL_Strcpy(ppExynosComponent[4]->componentName, EXYNOS_OMX_COMPONENT_MPEG4_CUSTOM_DRM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[4]->roles[0], EXYNOS_OMX_COMPONENT_MPEG4_DEC_ROLE); + ppExynosComponent[4]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + + /* component 6 - video custom decoder H.263 */ + Exynos_OSAL_Strcpy(ppExynosComponent[5]->componentName, EXYNOS_OMX_COMPONENT_H263_CUSTOM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[5]->roles[0], EXYNOS_OMX_COMPONENT_H263_DEC_ROLE); + ppExynosComponent[5]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; +#endif +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} diff --git a/component/video/dec/mpeg4/library_register.h b/component/video/dec/mpeg4/library_register.h new file mode 100644 index 0000000..5ba7384 --- /dev/null +++ b/component/video/dec/mpeg4/library_register.h @@ -0,0 +1,66 @@ +/* + * + * 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 6 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* MPEG4 */ +#define EXYNOS_OMX_COMPONENT_MPEG4_DEC "OMX.Exynos.MPEG4.Decoder" +#define EXYNOS_OMX_COMPONENT_MPEG4_DRM_DEC "OMX.Exynos.MPEG4.Decoder.secure" + +#define EXYNOS_OMX_COMPONENT_MPEG4_CUSTOM_DEC "OMX.Exynos.mpeg4.dec" +#define EXYNOS_OMX_COMPONENT_MPEG4_CUSTOM_DRM_DEC "OMX.Exynos.mpeg4.dec.secure" + +#define EXYNOS_OMX_COMPONENT_MPEG4_DEC_ROLE "video_decoder.mpeg4" + + +/* H.263 */ +#define EXYNOS_OMX_COMPONENT_H263_DEC "OMX.Exynos.H263.Decoder" +#define EXYNOS_OMX_COMPONENT_H263_CUSTOM_DEC "OMX.Exynos.h263.dec" +#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/component/video/dec/vc1/Android.mk b/component/video/dec/vc1/Android.mk new file mode 100644 index 0000000..9d96ea9 --- /dev/null +++ b/component/video/dec/vc1/Android.mk @@ -0,0 +1,66 @@ +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_CFLAGS := + +ifeq ($(BOARD_USE_ANB), true) +LOCAL_CFLAGS += -DUSE_ANB +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 ($(BOARD_USE_CUSTOM_COMPONENT_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_CUSTOM_COMPONENT_SUPPORT +endif + +ifeq ($(BOARD_USE_TIMESTAMP_REORDER_SUPPORT), true) +LOCAL_CFLAGS += -DUSE_TIMESTAMP_REORDER_SUPPORT +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/dec/vc1/Exynos_OMX_Wmvdec.c b/component/video/dec/vc1/Exynos_OMX_Wmvdec.c new file mode 100644 index 0000000..d1ebdbc --- /dev/null +++ b/component/video/dec/vc1/Exynos_OMX_Wmvdec.c @@ -0,0 +1,3443 @@ +/* + * + * 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" + +/* 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 WMV_DEC_NUM_OF_EXTRA_BUFFERS 7 + +#define SL_META_LEN 36 /* sequence layer metadata length in bytes */ + +/* parser does not send start code on Stagefright */ +#define WO_START_CODE + +/* Enable or disable "WMV3_ADDITIONAL_START_CODE" based on MFC F/W's need */ +//#define WMV3_ADDITIONAL_START_CODE + +//#define FULL_FRAME_SEARCH + +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; + + FunctionIn(); + + 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, "%s : there is no any profile/level", __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, "%s : supported profile(%x), level(%x)", __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + 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, "%s : there is no any profile/level", __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, "%s : profile(%x)/level(%x) is %ssupported", __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (ret == OMX_TRUE)? "":"not "); +EXIT: + return ret; +} + +#if 0 /* unused code */ +static OMX_ERRORTYPE GetCodecInputPrivateData(OMX_PTR codecBuffer, OMX_PTR *pVirtAddr, OMX_U32 *dataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +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, "WMV_FORMAT_WMV3"); + ret = WMV_FORMAT_WMV3; + } else if (((pCheckBuffer[3] == 0x01) && + (pCheckBuffer[4] == 0x0F)) || + ((pCheckBuffer[2] == 0x01) && + (pCheckBuffer[3] == 0x0F))) { + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "WMV_FORMAT_VC1"); + ret = WMV_FORMAT_VC1; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "WMV_FORMAT_UNKNOWN"); + } + + return ret; +} + +#if 0 /* unused code */ +int Check_Wmv_Frame( + OMX_U8 *pInputStream, + OMX_U32 buffSize, + OMX_U32 flag, + OMX_BOOL bPreviousFrameEOF, + OMX_BOOL *pbEndOfFrame) +{ + OMX_U32 compressionID; + OMX_BOOL bFrameStart; + OMX_U32 len, readStream; + OMX_U32 startCode; + + int retVal = (int)buffSize; + static WMV_FORMAT wmvFormat; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "buffSize = %d", buffSize); + + len = 0; + bFrameStart = OMX_FALSE; + + if (flag & OMX_BUFFERFLAG_CODECCONFIG) + wmvFormat = getFormatType(pInputStream); + + if (wmvFormat == WMV_FORMAT_WMV3) { + *pbEndOfFrame = OMX_TRUE; + return retVal; + } + +#ifdef WO_START_CODE + /* parser does not send start code on Stagefright */ + if (wmvFormat == WMV_FORMAT_VC1) { + *pbEndOfFrame = OMX_TRUE; + return retVal; + } +#else + /* TODO : for comformanc test based on common buffer scheme w/o parser */ + + if (bPreviousFrameEOF == OMX_FALSE) + bFrameStart = OMX_TRUE; + + startCode = 0xFFFFFFFF; + if (bFrameStart == OMX_FALSE) { + /* find Frame start code */ + while(startCode != 0x10D) { + readStream = *(pInputStream + len); + startCode = (startCode << 8) | readStream; + len++; + if (len > retVal) + goto EXIT; + } + } + + /* find next Frame start code */ + startCode = 0xFFFFFFFF; + while ((startCode != 0x10D)) { + readStream = *(pInputStream + len); + startCode = (startCode << 8) | readStream; + len++; + if (len > retVal) + goto EXIT; + } + + *pbEndOfFrame = OMX_TRUE; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "1. Check_Wmv_Frame returned EOF = %d, len = %d, buffSize = %d", *pbEndOfFrame, len - 4, buffSize); + + return len - 4; +#endif + +EXIT : + *pbEndOfFrame = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "2. Check_Wmv_Frame returned EOF = %d, len = %d, buffSize = %d", *pbEndOfFrame, len - 1, buffSize); + + return --len; +} +#endif + +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_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate decoder ops buffer"); + 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); + + Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps); + + /* 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, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pWmvDec->hMFCWmvHandle.hMFCHandle = pWmvDec->hMFCWmvHandle.pDecOps->Init(pVideoInstInfo); + if (pWmvDec->hMFCWmvHandle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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; + } + + /* 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + pOutbufOps = pWmvDec->hMFCWmvHandle.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 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; + ExynosVideoDecOps *pDecOps = 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; + pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + 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) && + (pOutputPort->bDynamicDPBMode == OMX_TRUE)) + 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + + 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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE WMVCodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + CODEC_DEC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoDecBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]); + pBufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]); + pBufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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) { + /**********************************/ + /* 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); + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = WmvCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to WmvCodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType & BUFFER_SHARE) { + /**********************************/ + /* Codec Buffer Unregister */ + /**********************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + } + + Exynos_ResolutionUpdate(pOMXComponent); + } 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + int i, nOutbufs; + + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.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, "pVideoDec->pMFCDecInputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecInputBuffer[%d]->pVirAddr[0]: 0x%x", i, 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->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pWmvDec->hMFCWmvHandle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +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); + 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 ((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) || + (codecOutbufConf.bInterlaced != pWmvDec->hMFCWmvHandle.codecOutbufConf.bInterlaced) || +#endif + (maxDPBNum != pWmvDec->hMFCWmvHandle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] DRC: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight, + pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth, + pWmvDec->hMFCWmvHandle.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__, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType, + pWmvDec->hMFCWmvHandle.maxDPBNum, + pWmvDec->hMFCWmvHandle.codecOutbufConf.eColorFormat, + pWmvDec->hMFCWmvHandle.codecOutbufConf.eFilledDataType); + + 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 (pOutputPort->bufferProcessType & BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = pWmvDec->hMFCWmvHandle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pWmvDec->hMFCWmvHandle.maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + /** 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); + } + } + + 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] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight, + pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nWidth, + pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nHeight); + + 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; + + /** 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; + + 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, "Failed to get geometry for parsed header info"); + ret = OMX_ErrorCorruptedHeader; + 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] WmvCodecSetup maxDPBNum: %d", pExynosComponent, __FUNCTION__, pWmvDec->hMFCWmvHandle.maxDPBNum); + + /* get interlace info */ + if (pWmvDec->hMFCWmvHandle.codecOutbufConf.bInterlaced == VIDEO_TRUE) + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "detect an interlaced type"); + + pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc = OMX_TRUE; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pCropRectangle = &(pOutputPort->cropRectangle); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + } else { + pCropRectangle = &(pOutputPort->newCropRectangle); + pInputPortDefinition = &(pInputPort->newPortDefinition); + pOutputPortDefinition = &(pOutputPort->newPortDefinition); + } + + 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) { + if ((pVideoDec->bReconfigDPB) || + (pInputPort->portDefinition.format.video.nFrameWidth != pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.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; + + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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) || + (pWmvDec->hMFCWmvHandle.codecOutbufConf.bInterlaced == VIDEO_TRUE) || + (pInputPort->portDefinition.format.video.nFrameWidth != pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.format.video.nFrameHeight != pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPort->portDefinition.nBufferCountActual != 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; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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); + } + } + + if ((pVideoDec->bReconfigDPB != OMX_TRUE) && + ((pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameWidth != pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nWidth) || + (pWmvDec->hMFCWmvHandle.codecOutbufConf.nFrameHeight != pWmvDec->hMFCWmvHandle.codecOutbufConf.cropRect.nHeight))) { + /* Check Crop */ + 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); + + /** 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 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 oneFrameSize = pSrcInputData->dataLen; + OMX_COLOR_FORMATTYPE eOutputFormat = pExynosOutputPort->portDefinition.format.video.eColorFormat; + OMX_BOOL bMetaData = OMX_FALSE; + + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + int i; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + 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); + Exynos_OSAL_SignalSet(pWmvDec->hDestinationStartEvent); + + 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); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + if (pSrcInputData->nFlags & OMX_BUFFERFLAG_CODECCONFIG) + pWmvDec->hMFCWmvHandle.wmvFormat = getFormatType(pSrcInputData->multiPlaneBuffer.dataBuffer[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, "Unsupported WMV Codec Format Type"); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pInbufOps->Set_Shareable(hMFCHandle); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + bufferConf.nSizeImage = pExynosInputPort->portDefinition.nBufferSize; + } else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + bufferConf.nSizeImage = DEFAULT_MFC_INPUT_BUFFER_SIZE; + } + 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + if ((pWmvDec->hMFCWmvHandle.videoInstInfo.specificInfo.dec.bDualDPBSupport == VIDEO_TRUE) && + (eOutputFormat != (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled)) { + /* Needs to eanble DualDPB feature */ + if (pDecOps->Enable_DualDPBMode(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorHardware; + goto EXIT; + } + } + 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; + goto EXIT; + } + } + + pWmvDec->hMFCWmvHandle.MFCOutputColorType = bufferConf.eColorFormat; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + bMetaData = Make_Stream_MetaData(pSrcInputData->multiPlaneBuffer.dataBuffer[0], &oneFrameSize, pWmvDec->hMFCWmvHandle.wmvFormat); + if (bMetaData == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Fail to Make Stream MetaData"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + nDataLen[0] = oneFrameSize; /* it is possible to be changed at Make_Stream_MetaData() */ + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enqueue input buffer for header parsing"); +// 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, "Failed to run input buffer for header parsing"); + ret = OMX_ErrorCodecInit; + goto EXIT; + } + + ret = WmvCodecUpdateResolution(pOMXComponent); + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0]) , *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 1), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 2), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 3), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 4), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 5), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 6), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 7)); + if (ret != OMX_ErrorNone) { + 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_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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + 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] = {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]; + + if (pExynosOutputPort->bDynamicDPBMode == OMX_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enable Dynamic DPB"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + /* get dpb count */ + nOutbufs = pWmvDec->hMFCWmvHandle.maxDPBNum; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Register output buffer */ + ret = WMVCodecRegistCodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) + pOutbufOps->Enqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + nDataLen, + nPlaneCnt, + NULL); + } else { + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + 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, + (int *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { +#ifdef USE_ANB + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + int plane; + + Exynos_OSAL_Memset((OMX_PTR)planes, 0, sizeof(ExynosVideoPlane) * MAX_BUFFER_PLANE); + + /* get dpb count */ + nOutbufs = pExynosOutputPort->portDefinition.nBufferCountActual; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_TRUE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + for (i = 0; i < pExynosOutputPort->assignedBufferNum; i++) { + for (plane = 0; plane < nPlaneCnt; plane++) { + planes[plane].fd = pExynosOutputPort->extendBufferHeader[i].buf_fd[plane]; + planes[plane].addr = pExynosOutputPort->extendBufferHeader[i].pYUVBuf[plane]; + planes[plane].allocSize = nAllocLen[plane]; + } + + if (pOutbufOps->Register(hMFCHandle, planes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Register output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pOutbufOps->Enqueue(hMFCHandle, + (void **)pExynosOutputPort->extendBufferHeader[i].pYUVBuf, + nDataLen, + nPlaneCnt, + NULL); + } + + if (pOutbufOps->Apply_RegisteredBuffer(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Apply output buffer"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } else { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } else { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_FALSE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } +#else + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; +#endif + } + + pWmvDec->hMFCWmvHandle.bConfiguredMFCDst = OMX_TRUE; + + 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; + + 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 ((int)nParamIndex) { + case OMX_IndexParamVideoWmv: + { + OMX_VIDEO_PARAM_WMVTYPE *pDstWmvParam = (OMX_VIDEO_PARAM_WMVTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_WMVTYPE *pSrcWmvParam = NULL; + EXYNOS_WMVDEC_HANDLE *pWmvDec = 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) { + goto EXIT; + } + + if (pDstWmvParam->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + EXYNOS_WMVDEC_HANDLE *pWmvDec = 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) { + goto EXIT; + } + + if (pDstVc1Param->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + 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) { + 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; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + EXYNOS_WMVDEC_HANDLE *pWmvDec = 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; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + case OMX_IndexExynosParamReorderMode: /* MSRND */ + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pReorderParam->bReorderMode = pVideoDec->bReorderMode; + } + break; +#endif + case OMX_IndexParamPortDefinition: + { + OMX_PARAM_PORTDEFINITIONTYPE *portDefinition = (OMX_PARAM_PORTDEFINITIONTYPE *)pComponentParameterStructure; + OMX_U32 portIndex = portDefinition->nPortIndex; + 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 *pExynosPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ret = Exynos_OMX_VideoDecodeGetParameter(hComponent, nParamIndex, pComponentParameterStructure); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (((pExynosPort->bIsANBEnabled == OMX_TRUE) || (pExynosPort->bStoreMetaData == OMX_TRUE)) && + (pWmvDec->hMFCWmvHandle.codecOutbufConf.bInterlaced == VIDEO_TRUE) && + (portIndex == OUTPUT_PORT_INDEX)) { + portDefinition->format.video.eColorFormat = + (OMX_COLOR_FORMATTYPE)Exynos_OSAL_OMX2HALPixelFormat((OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace, pExynosPort->ePlaneType); + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "portDefinition->format.video.eColorFormat: 0x%x", portDefinition->format.video.eColorFormat); + } + 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; + + 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 ((int)nIndex) { + case OMX_IndexParamVideoWmv: + { + OMX_VIDEO_PARAM_WMVTYPE *pDstWmvParam = NULL; + OMX_VIDEO_PARAM_WMVTYPE *pSrcWmvParam = (OMX_VIDEO_PARAM_WMVTYPE *)pComponentParameterStructure; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + /* 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) { + goto EXIT; + } + + if (pSrcWmvParam->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + /* 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) { + goto EXIT; + } + + if (pSrcVc1Param->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + 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_ErrorBadParameter; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VC1TYPE *pDstVc1Component = NULL; + EXYNOS_WMVDEC_HANDLE *pVc1Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pVc1Dec = (EXYNOS_WMVDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + pDstVc1Component = &pVc1Dec->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; + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + case OMX_IndexExynosParamReorderMode: /* MSRND */ + { + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + goto EXIT; + + pVideoDec->bReorderMode = pReorderParam->bReorderMode; + } + break; +#endif + 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; + + 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) { + case OMX_IndexConfigCommonOutputCrop: + { + EXYNOS_WMVDEC_HANDLE *pWmvDec = NULL; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + OMX_CONFIG_RECTTYPE *pDstRectType = NULL; + + pWmvDec = (EXYNOS_WMVDEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + if (pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + break; + } + + pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + + if ((pDstRectType->nPortIndex != INPUT_PORT_INDEX) && + (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[pDstRectType->nPortIndex]; + + pSrcRectType = &(pExynosPort->cropRectangle); + + 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; + + 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_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) { + 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; + } + + if (IS_CUSTOM_COMPONENT(pExynosComponent->componentName) == OMX_TRUE) { +#ifdef USE_TIMESTAMP_REORDER_SUPPORT + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_CUSTOM_INDEX_PARAM_REORDER_MODE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexExynosParamReorderMode; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + } + + 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; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + 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; + OMX_PTR hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + ExynosVideoInstInfo *pVideoInstInfo = &(pWmvDec->hMFCWmvHandle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i, plane; + + FunctionIn(); + + pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc = OMX_FALSE; + pWmvDec->hMFCWmvHandle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + pVideoDec->bDiscardCSDError = 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; + } + + pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {DEFAULT_MFC_INPUT_BUFFER_SIZE, 0, 0}; + 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) { + 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->hDestinationStartEvent); + + 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 = (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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + OMX_PTR hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + + int i, plane; + + FunctionIn(); + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pWmvDec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pWmvDec->hDestinationStartEvent); + pWmvDec->hDestinationStartEvent = NULL; + pWmvDec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalTerminate(pWmvDec->hSourceStartEvent); + pWmvDec->hSourceStartEvent = NULL; + pWmvDec->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); + } 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); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + 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]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pWmvDec->hMFCWmvHandle.pOutbufOps; + 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; + int i; + + FunctionIn(); + + if (pWmvDec->hMFCWmvHandle.bConfiguredMFCSrc == OMX_FALSE) { + ret = WmvCodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pWmvDec->hMFCWmvHandle.bConfiguredMFCDst == OMX_FALSE) && + (pVideoDec->bForceHeaderParsing == OMX_FALSE)) { + ret = WmvCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to WmvCodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + } + + bStartCode = Check_Stream_PrefixCode(pSrcInputData->multiPlaneBuffer.dataBuffer[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_ERROR, "Can't attach startcode due to lack of buffer space"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + + bStartCode = Make_Stream_StartCode(pSrcInputData->multiPlaneBuffer.dataBuffer[0], &oneFrameSize, pWmvDec->hMFCWmvHandle.wmvFormat); + if (bStartCode == OMX_FALSE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Fail to Make Stream Start Code"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + 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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x, oneFrameSize: %d", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pWmvDec->hMFCWmvHandle.indexTimestamp, pSrcInputData->nFlags, oneFrameSize); + + pDecOps->Set_FrameTag(hMFCHandle, pWmvDec->hMFCWmvHandle.indexTimestamp); + pWmvDec->hMFCWmvHandle.indexTimestamp++; + pWmvDec->hMFCWmvHandle.indexTimestamp %= MAX_TIMESTAMP; + + if ((pVideoDec->bQosChanged == OMX_TRUE) && + (pDecOps->Set_QosRatio != NULL)) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + pVideoDec->bQosChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] bufferHeader: 0x%x, dataBuffer: 0x%x", pExynosComponent, __FUNCTION__, pSrcInputData->bufferHeader, pSrcInputData->multiPlaneBuffer.dataBuffer[0]); + + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + nDataLen[0] = oneFrameSize; /* it is possible to be changed at Make_Stream_MetaData() */ + + if (pExynosInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pWmvDec->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bStartCode == OMX_FALSE) { + ret = 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pWmvDec->hMFCWmvHandle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pWmvDec->hMFCWmvHandle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + pSrcOutputData->bufferHeader = NULL; + } else { + pSrcOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[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, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#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]; + + ExynosVideoDecOps *pDecOps = pWmvDec->hMFCWmvHandle.pDecOps; + 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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + 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] : %d => ADDR[%d]: 0x%x", pExynosComponent, __FUNCTION__, __LINE__, i, + pDstInputData->multiPlaneBuffer.dataBuffer[i]); + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + ret = WmvCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to WmvCodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + pVideoDec->bReconfigDPB = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + codecReturn = pOutbufOps->Enqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } else { + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &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; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + FunctionIn(); + + if (pWmvDec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + pVideoBuffer = pOutbufOps->Dequeue(hMFCHandle); + if (pVideoBuffer == (ExynosVideoBuffer *)VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "HW is not available"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + if (pVideoBuffer == NULL) { + ret = OMX_ErrorNone; + goto EXIT; + } + } else { + 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, "HW is not available"); + 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(pExynosOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL)) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pExynosOutputPort->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(pExynosOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->multiPlaneBuffer.fd[plane] = pVideoBuffer->planes[plane].fd; + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->multiPlaneBuffer.dataBuffer[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + /* get interlace frame info */ + if ((pExynosOutputPort->bufferProcessType & BUFFER_SHARE) && + (pWmvDec->hMFCWmvHandle.codecOutbufConf.bInterlaced == VIDEO_TRUE) && + (pVideoBuffer->planes[2].addr != NULL)) { + /* only NV12 case */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] interlace type = %x", pExynosComponent, __FUNCTION__, pVideoBuffer->interlacedType); + *(int *)(pVideoBuffer->planes[2].addr) = pVideoBuffer->interlacedType; + } + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pWmvDec->hMFCWmvHandle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->ColorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + 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; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output timestamp %lld us (%.2f secs), indexTimestamp: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, indexTimestamp, pDstOutputData->nFlags); + } + } 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 reorder timestamp %lld us (%.2f secs), sCurrentTimestamp.nIndex: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, sCurrentTimestamp.nIndex, pDstOutputData->nFlags); + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pExynosOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if (pWmvDec->hMFCWmvHandle.videoInstInfo.specificInfo.dec.bLastFrameSupport == VIDEO_FALSE) { + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + 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] indexTimestamp(%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 = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + } + } else { + if ((displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + + if ((pExynosComponent->bBehaviorEOS == OMX_TRUE) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME)) { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (displayStatus != VIDEO_FRAME_STATUS_LAST_FRAME) { + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } else { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 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_ErrorNone; + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + 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; + } + + 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_SignalReset(pWmvDec->hSourceStartEvent); + } + + ret = Exynos_WmvDec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pWmvDec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pWmvDec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pWmvDec->hDestinationStartEvent); + } + 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; + } + + 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 (pWmvDec->hMFCWmvHandle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_WmvDec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +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 (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pWmvDec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pWmvDec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pWmvDec->hDestinationStartEvent); + } + if (Exynos_OSAL_GetElemNum(&pWmvDec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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, "OMX_ErrorBadParameter, Line:%d", __LINE__); + goto EXIT; + } + if ((Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_WMV_DEC, componentName) != 0) && + (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_WMV_CUSTOM_DEC, componentName) != 0)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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) + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_BUFFER_SIZE; + + 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 | BUFFER_ANBSHARE; + 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; + +#if 0 /* unused code */ + pVideoDec->exynos_checkInputFrame = &Check_Wmv_Frame; + pVideoDec->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &WmvCodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &WmvCodecCheckResolution; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + Exynos_OSAL_Free(pWmvDec); + pWmvDec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->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]: Exynos_Video_GetInstInfo is failed", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pWmvDec); + pWmvDec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec %d %d %d %d", pExynosComponent, __FUNCTION__, + (pWmvDec->hMFCWmvHandle.videoInstInfo.specificInfo.dec.bDualDPBSupport), + (pWmvDec->hMFCWmvHandle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport), + (pWmvDec->hMFCWmvHandle.videoInstInfo.specificInfo.dec.bLastFrameSupport), + (pWmvDec->hMFCWmvHandle.videoInstInfo.specificInfo.dec.bSkypeSupport)); + + if (pWmvDec->hMFCWmvHandle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport == VIDEO_TRUE) + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bDynamicDPBMode = OMX_TRUE; + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + 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; + + 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) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/dec/vc1/Exynos_OMX_Wmvdec.h b/component/video/dec/vc1/Exynos_OMX_Wmvdec.h new file mode 100644 index 0000000..62480b0 --- /dev/null +++ b/component/video/dec/vc1/Exynos_OMX_Wmvdec.h @@ -0,0 +1,103 @@ +/* + * + * 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; + + 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 hDestinationStartEvent; + + 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/component/video/dec/vc1/NOTICE b/component/video/dec/vc1/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/dec/vc1/library_register.c b/component/video/dec/vc1/library_register.c new file mode 100644 index 0000000..02578d6 --- /dev/null +++ b/component/video/dec/vc1/library_register.c @@ -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.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; +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + /* component 2 - video custom decoder WMV */ + Exynos_OSAL_Strcpy(ppExynosComponent[1]->componentName, EXYNOS_OMX_COMPONENT_WMV_CUSTOM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[1]->roles[0], EXYNOS_OMX_COMPONENT_WMV_DEC_ROLE); + ppExynosComponent[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; +#endif +EXIT: + FunctionOut(); + return MAX_COMPONENT_NUM; +} diff --git a/component/video/dec/vc1/library_register.h b/component/video/dec/vc1/library_register.h new file mode 100644 index 0000000..beefa77 --- /dev/null +++ b/component/video/dec/vc1/library_register.h @@ -0,0 +1,55 @@ +/* + * + * 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 2 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* WMV */ +#define EXYNOS_OMX_COMPONENT_WMV_DEC "OMX.Exynos.WMV.Decoder" +#define EXYNOS_OMX_COMPONENT_WMV_CUSTOM_DEC "OMX.Exynos.vc1.dec" +#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/component/video/dec/vp8/Android.mk b/component/video/dec/vp8/Android.mk new file mode 100644 index 0000000..5c7cea7 --- /dev/null +++ b/component/video/dec/vp8/Android.mk @@ -0,0 +1,63 @@ +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_CFLAGS := +LOCAL_CFLAGS += -DUSE_VP8_SUPPORT + +ifeq ($(BOARD_USE_ANB), true) +LOCAL_CFLAGS += -DUSE_ANB +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 ($(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 + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/dec/vp8/Exynos_OMX_Vp8dec.c b/component/video/dec/vp8/Exynos_OMX_Vp8dec.c new file mode 100644 index 0000000..9ff8d25 --- /dev/null +++ b/component/video/dec/vp8/Exynos_OMX_Vp8dec.c @@ -0,0 +1,3073 @@ +/* + * + * 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" + +/* 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" + +#define VP8_DEC_NUM_OF_EXTRA_BUFFERS 7 + +//#define FULL_FRAME_SEARCH /* Full frame search not support*/ + +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; + + FunctionIn(); + + 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; + } + + while ((pVp8Dec->hMFCVp8Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pVp8Dec->hMFCVp8Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : there is no any profile/level", __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); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s : supported profile(%x), level(%x)", __FUNCTION__, pProfileLevelType->eProfile, pProfileLevelType->eLevel); + +EXIT: + 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, "%s : there is no any profile/level", __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, "%s : profile(%x)/level(%x) is %ssupported", __FUNCTION__, + pProfileLevelType->eProfile, pProfileLevelType->eLevel, + (bProfileSupport && bLevelSupport)? "":"not "); + +EXIT: + return (bProfileSupport && bLevelSupport); +} + +#if 0 /* unused code */ +static OMX_ERRORTYPE GetCodecInputPrivateData(OMX_PTR codecBuffer, OMX_PTR *pVirtAddr, OMX_U32 *dataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +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; +} + +#if 0 /* unused code */ +static int Check_VP8_Frame( + OMX_U8 *pInputStream, + OMX_U32 buffSize, + OMX_U32 flag, + OMX_BOOL bPreviousFrameEOF, + OMX_BOOL *pbEndOfFrame) +{ + /* Uncompressed data Chunk comprises a common + (for key frames and interframes) 3-byte frame tag that + contains four fields + - 1-bit frame type (0 - key frame, 1 - inter frame) + - 3-bit version number (0 - 3 are defined as four different + profiles with different decoding complexity) + - 1-bit show_frame flag ( 0 - current frame not for display, + 1 - current frame is for dispaly) + - 19-bit field - size of the first data partition in bytes + + Key Frames : frame tag followed by 7 bytes of uncompressed + data + 3-bytes : Start code (byte 0: 0x9d,byte 1: 0x01,byte 2: 0x2a) + Next 4-bytes: Width & height, Horizontal and vertical scale information + 16 bits : (2 bits Horizontal Scale << 14) | Width (14 bits) + 16 bits : (2 bits Vertical Scale << 14) | Height (14 bits) + */ + int width, height; + int horizSscale, vertScale; + + FunctionIn(); + + *pbEndOfFrame = OMX_TRUE; + + /*Check for Key frame*/ + if (!(pInputStream[0] & 0x01)){ + /* Key Frame Start code*/ + if (pInputStream[3] != 0x9d || pInputStream[4] != 0x01 || pInputStream[5]!=0x2a) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, " VP8 Key Frame Start Code not Found"); + *pbEndOfFrame = OMX_FALSE; + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, " VP8 Found Key Frame Start Code"); + width = (pInputStream[6] | (pInputStream[7] << 8)) & 0x3fff; + horizSscale = pInputStream[7] >> 6; + height = (pInputStream[8] | (pInputStream[9] << 8)) & 0x3fff; + vertScale = pInputStream[9] >> 6; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "width = %d, height = %d, horizSscale = %d, vertScale = %d", width, height, horizSscale, vertScale); + } + + FunctionOut(); + return (int)buffSize; +} +#endif + +OMX_BOOL Check_VP8_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize) +{ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "streamSize: %d",streamSize); + if (streamSize < 3) { + return OMX_FALSE; + } + + if (!(pInputStream[0] & 0x01)){ + /* Key Frame Start code*/ + if (pInputStream[3] != 0x9d || pInputStream[4] != 0x01 || pInputStream[5]!=0x2a) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, " VP8 Key Frame Start Code not Found"); + return OMX_FALSE; + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, " VP8 Found Key Frame Start Code"); + } + + 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_VP8DEC_HANDLE *pVp8Dec = NULL; + EXYNOS_OMX_BASEPORT *pOutputPort = NULL; + ExynosVideoColorFormatType eVideoFormat = VIDEO_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate decoder ops buffer"); + 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); + + Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps); + + /* 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, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pVp8Dec->hMFCVp8Handle.hMFCHandle = pVp8Dec->hMFCVp8Handle.pDecOps->Init(pVideoInstInfo); + if (pVp8Dec->hMFCVp8Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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; + } + + /* 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + pOutbufOps = pVp8Dec->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; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = 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; + pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + 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) && + (pOutputPort->bDynamicDPBMode == OMX_TRUE)) + 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + 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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + CODEC_DEC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoDecBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]); + pBufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]); + pBufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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) { + /**********************************/ + /* 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); + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = VP8CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to VP8CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType & BUFFER_SHARE) { + /**********************************/ + /* Codec Buffer Unregister */ + /**********************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + } + + Exynos_ResolutionUpdate(pOMXComponent); + } 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + int i, nOutbufs; + + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pVp8Dec->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, "pVideoDec->pMFCDecInputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecInputBuffer[%d]->pVirAddr[0]: 0x%x", i, 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->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pVp8Dec->hMFCVp8Handle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +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); + 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 ((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) || + (codecOutbufConf.bInterlaced != pVp8Dec->hMFCVp8Handle.codecOutbufConf.bInterlaced) || +#endif + (maxDPBNum != pVp8Dec->hMFCVp8Handle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] DRC: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth, + pVp8Dec->hMFCVp8Handle.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__, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType, + pVp8Dec->hMFCVp8Handle.maxDPBNum, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.eColorFormat, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.eFilledDataType); + + 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 (pOutputPort->bufferProcessType & BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = pVp8Dec->hMFCVp8Handle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pVp8Dec->hMFCVp8Handle.maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + /** 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); + } + } + + 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] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nWidth, + pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nHeight); + + 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; + + /** 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; + + 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, "Failed to get geometry for parsed header info"); + ret = OMX_ErrorCorruptedHeader; + 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] VP8CodecSetup maxDPBNum: %d", pExynosComponent, __FUNCTION__, pVp8Dec->hMFCVp8Handle.maxDPBNum); + + pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc = OMX_TRUE; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pCropRectangle = &(pOutputPort->cropRectangle); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + } else { + pCropRectangle = &(pOutputPort->newCropRectangle); + pInputPortDefinition = &(pInputPort->newPortDefinition); + pOutputPortDefinition = &(pOutputPort->newPortDefinition); + } + + 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) { + if ((pVideoDec->bReconfigDPB) || + (pInputPort->portDefinition.format.video.nFrameWidth != pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.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; + + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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) || + (pInputPort->portDefinition.format.video.nFrameWidth != pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.format.video.nFrameHeight != pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPort->portDefinition.nBufferCountActual != 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; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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); + } + } + + if ((pVideoDec->bReconfigDPB != OMX_TRUE) && + ((pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameWidth != pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nWidth) || + (pVp8Dec->hMFCVp8Handle.codecOutbufConf.nFrameHeight != pVp8Dec->hMFCVp8Handle.codecOutbufConf.cropRect.nHeight))) { + /* Check Crop */ + 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); + + /** 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 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 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + int i; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + 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); + Exynos_OSAL_SignalSet(pVp8Dec->hDestinationStartEvent); + + 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); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eCompressionFormat = VIDEO_CODING_VP8; + pInbufOps->Set_Shareable(hMFCHandle); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + bufferConf.nSizeImage = pExynosInputPort->portDefinition.nBufferSize; + } else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + bufferConf.nSizeImage = DEFAULT_MFC_INPUT_BUFFER_SIZE; + } + 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + if ((pVp8Dec->hMFCVp8Handle.videoInstInfo.specificInfo.dec.bDualDPBSupport == VIDEO_TRUE) && + (eOutputFormat != (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled)) { + /* Needs to eanble DualDPB feature */ + if (pDecOps->Enable_DualDPBMode(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorHardware; + goto EXIT; + } + } + 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; + goto EXIT; + } + } + + pVp8Dec->hMFCVp8Handle.MFCOutputColorType = bufferConf.eColorFormat; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + /* set buffer process type */ + if (pDecOps->Set_BufferProcessType(hMFCHandle, pExynosOutputPort->bufferProcessType) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set buffer process type(not supported)"); + } + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enqueue input buffer for header parsing"); +// 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, "Failed to run input buffer for header parsing"); + ret = OMX_ErrorCodecInit; + goto EXIT; + } + + ret = Vp8CodecUpdateResolution(pOMXComponent); + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0]) , *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 1), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 2), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 3), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 4), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 5), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 6), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 7)); + if (ret != OMX_ErrorNone) { + VP8CodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + ret = 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + 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] = {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]; + + if (pExynosOutputPort->bDynamicDPBMode == OMX_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enable Dynamic DPB"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + /* get dpb count */ + nOutbufs = pVp8Dec->hMFCVp8Handle.maxDPBNum; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Register output buffer */ + ret = VP8CodecRegistCodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) + pOutbufOps->Enqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + nDataLen, + nPlaneCnt, + NULL); + } else { + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + 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; + + /* without Register output buffer */ + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (int *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { +#ifdef USE_ANB + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + int plane; + + Exynos_OSAL_Memset((OMX_PTR)planes, 0, sizeof(ExynosVideoPlane) * MAX_BUFFER_PLANE); + + /* get dpb count */ + nOutbufs = pExynosOutputPort->portDefinition.nBufferCountActual; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_TRUE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + for (i = 0; i < pExynosOutputPort->assignedBufferNum; i++) { + for (plane = 0; plane < nPlaneCnt; plane++) { + planes[plane].fd = pExynosOutputPort->extendBufferHeader[i].buf_fd[plane]; + planes[plane].addr = pExynosOutputPort->extendBufferHeader[i].pYUVBuf[plane]; + planes[plane].allocSize = nAllocLen[plane]; + } + + if (pOutbufOps->Register(hMFCHandle, planes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Register output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pOutbufOps->Enqueue(hMFCHandle, + (void **)pExynosOutputPort->extendBufferHeader[i].pYUVBuf, + nDataLen, + nPlaneCnt, + NULL); + } + + if (pOutbufOps->Apply_RegisteredBuffer(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Apply output buffer"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } else { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } else { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_FALSE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } +#else + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; +#endif + } + + pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst = OMX_TRUE; + + 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; + + 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 ((int)nParamIndex) { + case OMX_IndexParamVideoVp8: + { + OMX_VIDEO_PARAM_VP8TYPE *pDstVP8Component = (OMX_VIDEO_PARAM_VP8TYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP8TYPE *pSrcVP8Component = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = 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) { + goto EXIT; + } + + if (pDstVP8Component->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + 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) { + 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; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pDstProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pDstProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = 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; + } + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + + 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 ((int)nIndex) { + case OMX_IndexParamVideoVp8: + { + OMX_VIDEO_PARAM_VP8TYPE *pDstVP8Component = NULL; + OMX_VIDEO_PARAM_VP8TYPE *pSrcVP8Component = (OMX_VIDEO_PARAM_VP8TYPE *)pComponentParameterStructure; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + /* 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; + } + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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) { + 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_ErrorBadParameter; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoProfileLevelCurrent: + { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *pSrcProfileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_VP8TYPE *pDstVP8Component = NULL; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcProfileLevel, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcProfileLevel->nPortIndex >= ALL_PORT_NUM) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + 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; + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + + 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) { + case OMX_IndexConfigCommonOutputCrop: + { + EXYNOS_VP8DEC_HANDLE *pVp8Dec = NULL; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + OMX_CONFIG_RECTTYPE *pDstRectType = NULL; + + pVp8Dec = (EXYNOS_VP8DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + if (pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + break; + } + + pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + + if ((pDstRectType->nPortIndex != INPUT_PORT_INDEX) && + (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[pDstRectType->nPortIndex]; + + pSrcRectType = &(pExynosPort->cropRectangle); + + 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; + + 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_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) { + 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_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; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + 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; + OMX_PTR hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + ExynosVideoInstInfo *pVideoInstInfo = &(pVp8Dec->hMFCVp8Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i, plane; + + FunctionIn(); + + pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + pVideoDec->bDiscardCSDError = 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; + } + + pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {DEFAULT_MFC_INPUT_BUFFER_SIZE, 0, 0}; + 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) { + 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->hDestinationStartEvent); + + 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 = (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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + OMX_PTR hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + + int i, plane; + + FunctionIn(); + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pVp8Dec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pVp8Dec->hDestinationStartEvent); + pVp8Dec->hDestinationStartEvent = NULL; + pVp8Dec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalTerminate(pVp8Dec->hSourceStartEvent); + pVp8Dec->hSourceStartEvent = NULL; + pVp8Dec->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); + } 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); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + 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]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp8Dec->hMFCVp8Handle.pOutbufOps; + 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; + int i; + + FunctionIn(); + + if (pVp8Dec->hMFCVp8Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = VP8CodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst == OMX_FALSE) && + (pVideoDec->bForceHeaderParsing == OMX_FALSE)) { + ret = VP8CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to VP8CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + } + + if (((bInStartCode = Check_VP8_StartCode(pSrcInputData->multiPlaneBuffer.dataBuffer[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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x, oneFrameSize: %d", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pVp8Dec->hMFCVp8Handle.indexTimestamp, pSrcInputData->nFlags, oneFrameSize); + pDecOps->Set_FrameTag(hMFCHandle, pVp8Dec->hMFCVp8Handle.indexTimestamp); + pVp8Dec->hMFCVp8Handle.indexTimestamp++; + pVp8Dec->hMFCVp8Handle.indexTimestamp %= MAX_TIMESTAMP; + + if ((pVideoDec->bQosChanged == OMX_TRUE) && + (pDecOps->Set_QosRatio != NULL)) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + pVideoDec->bQosChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] bufferHeader: 0x%x, dataBuffer: 0x%x", pExynosComponent, __FUNCTION__, pSrcInputData->bufferHeader, pSrcInputData->multiPlaneBuffer.dataBuffer[0]); + + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + if (pExynosInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp8Dec->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + ret = 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pVp8Dec->hMFCVp8Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp8Dec->hMFCVp8Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[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, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#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]; + + ExynosVideoDecOps *pDecOps = pVp8Dec->hMFCVp8Handle.pDecOps; + 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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + 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] : %d => ADDR[%d]: 0x%x", pExynosComponent, __FUNCTION__, __LINE__, i, + pDstInputData->multiPlaneBuffer.dataBuffer[i]); + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + ret = VP8CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to VP8CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + pVideoDec->bReconfigDPB = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + codecReturn = pOutbufOps->Enqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } else { + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &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; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + FunctionIn(); + + if (pVp8Dec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + pVideoBuffer = pOutbufOps->Dequeue(hMFCHandle); + if (pVideoBuffer == (ExynosVideoBuffer *)VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "HW is not available"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + if (pVideoBuffer == NULL) { + ret = OMX_ErrorNone; + goto EXIT; + } + } else { + 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, "HW is not available"); + 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(pExynosOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL)) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pExynosOutputPort->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(pExynosOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->multiPlaneBuffer.fd[plane] = pVideoBuffer->planes[plane].fd; + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->multiPlaneBuffer.dataBuffer[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pVp8Dec->hMFCVp8Handle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->ColorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + 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; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output timestamp %lld us (%.2f secs), indexTimestamp: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, indexTimestamp, pDstOutputData->nFlags); + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pExynosOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if (pVp8Dec->hMFCVp8Handle.videoInstInfo.specificInfo.dec.bLastFrameSupport == VIDEO_FALSE) { + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + 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] indexTimestamp(%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 = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + } + } else { + if ((displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + + if (pExynosComponent->bBehaviorEOS == OMX_TRUE) { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (displayStatus != VIDEO_FRAME_STATUS_LAST_FRAME) { + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } else { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 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_ErrorNone; + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + 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; + } + + 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) { + 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_SignalReset(pVp8Dec->hSourceStartEvent); + } + + ret = Exynos_VP8Dec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pVp8Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pVp8Dec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pVp8Dec->hDestinationStartEvent); + } + 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; + } + + 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 (pVp8Dec->hMFCVp8Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_VP8Dec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +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 (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pVp8Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pVp8Dec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pVp8Dec->hDestinationStartEvent); + } + if (Exynos_OSAL_GetElemNum(&pVp8Dec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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, "OMX_ErrorBadParameter, Line:%d", __LINE__); + goto EXIT; + } + if ((Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP8_DEC, componentName) != 0) && + (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP8_CUSTOM_DEC, componentName) != 0)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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) + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_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/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 | BUFFER_ANBSHARE; + 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; + +#if 0 /* unused code */ + pVideoDec->exynos_checkInputFrame = &Check_VP8_Frame; + pVideoDec->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &Vp8CodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &Vp8CodecCheckResolution; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + Exynos_OSAL_Free(pVp8Dec); + pVp8Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->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]: Exynos_Video_GetInstInfo is failed", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pVp8Dec); + pVp8Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec %d %d %d %d", pExynosComponent, __FUNCTION__, + (pVp8Dec->hMFCVp8Handle.videoInstInfo.specificInfo.dec.bDualDPBSupport), + (pVp8Dec->hMFCVp8Handle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport), + (pVp8Dec->hMFCVp8Handle.videoInstInfo.specificInfo.dec.bLastFrameSupport), + (pVp8Dec->hMFCVp8Handle.videoInstInfo.specificInfo.dec.bSkypeSupport)); + + if (pVp8Dec->hMFCVp8Handle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport == VIDEO_TRUE) + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bDynamicDPBMode = OMX_TRUE; + + Exynos_Output_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + 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; + + 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) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/dec/vp8/Exynos_OMX_Vp8dec.h b/component/video/dec/vp8/Exynos_OMX_Vp8dec.h new file mode 100644 index 0000000..e3c7d81 --- /dev/null +++ b/component/video/dec/vp8/Exynos_OMX_Vp8dec.h @@ -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_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; + + 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 hDestinationStartEvent; + + 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/component/video/dec/vp8/NOTICE b/component/video/dec/vp8/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/dec/vp8/library_register.c b/component/video/dec/vp8/library_register.c new file mode 100644 index 0000000..296e8a3 --- /dev/null +++ b/component/video/dec/vp8/library_register.c @@ -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.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; +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + /* component 2 - video custom decoder VP8 */ + Exynos_OSAL_Strcpy(ppExynosComponent[1]->componentName, EXYNOS_OMX_COMPONENT_VP8_CUSTOM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[1]->roles[0], EXYNOS_OMX_COMPONENT_VP8_DEC_ROLE); + ppExynosComponent[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; +#endif +EXIT: + FunctionOut(); + return MAX_COMPONENT_NUM; +} diff --git a/component/video/dec/vp8/library_register.h b/component/video/dec/vp8/library_register.h new file mode 100644 index 0000000..453759a --- /dev/null +++ b/component/video/dec/vp8/library_register.h @@ -0,0 +1,56 @@ +/* + * + * 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 2 +#define MAX_COMPONENT_ROLE_NUM 1 + +/* VP8 */ +#define EXYNOS_OMX_COMPONENT_VP8_DEC "OMX.Exynos.VP8.Decoder" +#define EXYNOS_OMX_COMPONENT_VP8_CUSTOM_DEC "OMX.Exynos.vp8.dec" +#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/component/video/dec/vp9/Android.mk b/component/video/dec/vp9/Android.mk new file mode 100644 index 0000000..db97bec --- /dev/null +++ b/component/video/dec/vp9/Android.mk @@ -0,0 +1,63 @@ +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_CFLAGS := +LOCAL_CFLAGS += -DUSE_VP9_SUPPORT + +ifeq ($(BOARD_USE_ANB), true) +LOCAL_CFLAGS += -DUSE_ANB +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 ($(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 + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Vdec libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/dec/vp9/Exynos_OMX_Vp9dec.c b/component/video/dec/vp9/Exynos_OMX_Vp9dec.c new file mode 100644 index 0000000..bd55472 --- /dev/null +++ b/component/video/dec/vp9/Exynos_OMX_Vp9dec.c @@ -0,0 +1,2782 @@ +/* + * + * 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" + +/* 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" + +#define VP9_DEC_NUM_OF_EXTRA_BUFFERS 7 + +//#define FULL_FRAME_SEARCH /* Full frame search not support*/ + +#if 0 /* unused code */ +static OMX_ERRORTYPE GetCodecInputPrivateData(OMX_PTR codecBuffer, OMX_PTR *pVirtAddr, OMX_U32 *dataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +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; +} + +#if 0 /* unused code */ +static int Check_VP9_Frame( + OMX_U8 *pInputStream, + OMX_U32 buffSize, + OMX_U32 flag, + OMX_BOOL bPreviousFrameEOF, + OMX_BOOL *pbEndOfFrame) +{ + /* Uncompressed data Chunk comprises a common + (for key frames and interframes) 3-byte frame tag that + contains four fields + - 1-bit frame type (0 - key frame, 1 - inter frame) + - 3-bit version number (0 - 3 are defined as four different + profiles with different decoding complexity) + - 1-bit show_frame flag ( 0 - current frame not for display, + 1 - current frame is for dispaly) + - 19-bit field - size of the first data partition in bytes + + Key Frames : frame tag followed by 7 bytes of uncompressed + data + 3-bytes : Start code (byte 0: 0x9d,byte 1: 0x01,byte 2: 0x2a) + Next 4-bytes: Width & height, Horizontal and vertical scale information + 16 bits : (2 bits Horizontal Scale << 14) | Width (14 bits) + 16 bits : (2 bits Vertical Scale << 14) | Height (14 bits) + */ + int width, height; + int horizSscale, vertScale; + + FunctionIn(); + + *pbEndOfFrame = OMX_TRUE; + + /*Check for Key frame*/ + if (!(pInputStream[0] & 0x01)){ + /* Key Frame Start code*/ + if (pInputStream[3] != 0x9d || pInputStream[4] != 0x01 || pInputStream[5]!=0x2a) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, " VP9 Key Frame Start Code not Found"); + *pbEndOfFrame = OMX_FALSE; + } + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, " VP9 Found Key Frame Start Code"); + width = (pInputStream[6] | (pInputStream[7] << 8)) & 0x3fff; + horizSscale = pInputStream[7] >> 6; + height = (pInputStream[8] | (pInputStream[9] << 8)) & 0x3fff; + vertScale = pInputStream[9] >> 6; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "width = %d, height = %d, horizSscale = %d, vertScale = %d", width, height, horizSscale, vertScale); + } + + FunctionOut(); + return (int)buffSize; +} +#endif + +OMX_BOOL Check_VP9_StartCode( + OMX_U8 *pInputStream, + OMX_U32 streamSize) +{ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "buffer: %p, streamSize: %d", pInputStream, streamSize); + if (streamSize < 3) { + 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_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate decoder ops buffer"); + 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); + + Exynos_Video_Register_Decoder(pDecOps, pInbufOps, pOutbufOps); + + /* 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, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pVp9Dec->hMFCVp9Handle.hMFCHandle = pVp9Dec->hMFCVp9Handle.pDecOps->Init(pVideoInstInfo); + if (pVp9Dec->hMFCVp9Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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; + } + + /* 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + pOutbufOps = pVp9Dec->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; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = 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; + pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + 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) && + (pOutputPort->bDynamicDPBMode == OMX_TRUE)) + 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; + void *hMFCHandle = NULL; + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + 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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + CODEC_DEC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoDecBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoDec->pMFCDecInputBuffer[0]); + pBufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoDec->pMFCDecOutputBuffer[0]); + pBufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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) { + /**********************************/ + /* 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); + + /******************************************************/ + /* V4L2 Destnation Setup for DPB Buffer Number Change */ + /******************************************************/ + ret = VP9CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to VP9CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + + pVideoDec->bReconfigDPB = OMX_FALSE; + } else if (pExynosPort->bufferProcessType & BUFFER_SHARE) { + /**********************************/ + /* Codec Buffer Unregister */ + /**********************************/ + pBufferOps->Clear_RegisteredBuffer(hMFCHandle); + pBufferOps->Cleanup_Buffer(hMFCHandle); + } + + Exynos_ResolutionUpdate(pOMXComponent); + } 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + int i, nOutbufs; + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + FunctionIn(); + + if ((nPortIndex != INPUT_PORT_INDEX) && (nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((nPortIndex == INPUT_PORT_INDEX) && + (pVp9Dec->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, "pVideoDec->pMFCDecInputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecInputBuffer[%d]->pVirAddr[0]: 0x%x", i, 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->bDestinationStart == OMX_TRUE)) { + Exynos_CodecBufferReset(pExynosComponent, OUTPUT_PORT_INDEX); + + for (i = 0; i < pVp9Dec->hMFCVp9Handle.maxDPBNum; i++) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoDec->pMFCDecOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnQueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoDec->pMFCDecOutputBuffer[i]); + } + pOutbufOps->Clear_Queue(hMFCHandle); + } + +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); + 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 ((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) || + (codecOutbufConf.bInterlaced != pVp9Dec->hMFCVp9Handle.codecOutbufConf.bInterlaced) || +#endif + (maxDPBNum != pVp9Dec->hMFCVp9Handle.maxDPBNum)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] DRC: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.nFrameWidth, + codecOutbufConf.nFrameHeight, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth, + pVp9Dec->hMFCVp9Handle.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__, + maxDPBNum, codecOutbufConf.eColorFormat, codecOutbufConf.eFilledDataType, + pVp9Dec->hMFCVp9Handle.maxDPBNum, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.eColorFormat, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.eFilledDataType); + + 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 (pOutputPort->bufferProcessType & BUFFER_SHARE) { + pOutputPortDefinition->nBufferCountActual = pVp9Dec->hMFCVp9Handle.maxDPBNum; + pOutputPortDefinition->nBufferCountMin = pVp9Dec->hMFCVp9Handle.maxDPBNum; + } + + Exynos_UpdateFrameSize(pOMXComponent); + + if (eOutputExcepState == GENERAL_STATE) { + pOutputPort->exceptionFlag = NEED_PORT_DISABLE; + + /** 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); + } + } + + 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] CROP: W(%d), H(%d) -> W(%d), H(%d)", + pExynosComponent, __FUNCTION__, + codecOutbufConf.cropRect.nWidth, + codecOutbufConf.cropRect.nHeight, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nWidth, + pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nHeight); + + 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; + + /** 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; + + 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, "Failed to get geometry for parsed header info"); + ret = OMX_ErrorCorruptedHeader; + 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] Vp9CodecSetup maxDPBNum: %d", pExynosComponent, __FUNCTION__, pVp9Dec->hMFCVp9Handle.maxDPBNum); + + pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc = OMX_TRUE; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pCropRectangle = &(pOutputPort->cropRectangle); + pInputPortDefinition = &(pInputPort->portDefinition); + pOutputPortDefinition = &(pOutputPort->portDefinition); + } else { + pCropRectangle = &(pOutputPort->newCropRectangle); + pInputPortDefinition = &(pInputPort->newPortDefinition); + pOutputPortDefinition = &(pOutputPort->newPortDefinition); + } + + 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) { + if ((pVideoDec->bReconfigDPB) || + (pInputPort->portDefinition.format.video.nFrameWidth != pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.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; + + pOutputPortDefinition->nBufferCountActual = pOutputPort->portDefinition.nBufferCountActual; + pOutputPortDefinition->nBufferCountMin = pOutputPort->portDefinition.nBufferCountMin; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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) || + (pInputPort->portDefinition.format.video.nFrameWidth != pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth) || + (pInputPort->portDefinition.format.video.nFrameHeight != pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight) || + ((OMX_S32)pOutputPort->portDefinition.nBufferCountActual != 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; + + if (pVideoDec->bReconfigDPB != OMX_TRUE) + Exynos_UpdateFrameSize(pOMXComponent); + + /** 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); + } + } + + if ((pVideoDec->bReconfigDPB != OMX_TRUE) && + ((pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameWidth != pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nWidth) || + (pVp9Dec->hMFCVp9Handle.codecOutbufConf.nFrameHeight != pVp9Dec->hMFCVp9Handle.codecOutbufConf.cropRect.nHeight))) { + /* Check Crop */ + 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); + + /** 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 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 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + ExynosVideoGeometry bufferConf; + + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {oneFrameSize, 0, 0}; + OMX_U32 nInBufferCnt = 0; + OMX_BOOL bSupportFormat = OMX_FALSE; + int i; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + 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); + Exynos_OSAL_SignalSet(pVp9Dec->hDestinationStartEvent); + + 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); + + /* input buffer info */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eCompressionFormat = VIDEO_CODING_VP9; + pInbufOps->Set_Shareable(hMFCHandle); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + bufferConf.nSizeImage = pExynosInputPort->portDefinition.nBufferSize; + } else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + bufferConf.nSizeImage = DEFAULT_MFC_INPUT_BUFFER_SIZE; + } + 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* set output geometry */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + + bSupportFormat = CheckFormatHWSupport(pExynosComponent, eOutputFormat); + if (bSupportFormat == OMX_TRUE) { /* supported by H/W */ + if ((pVp9Dec->hMFCVp9Handle.videoInstInfo.specificInfo.dec.bDualDPBSupport == VIDEO_TRUE) && + (eOutputFormat != (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled)) { + /* Needs to eanble DualDPB feature */ + if (pDecOps->Enable_DualDPBMode(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorHardware; + goto EXIT; + } + } + 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; + goto EXIT; + } + } + + pVp9Dec->hMFCVp9Handle.MFCOutputColorType = bufferConf.eColorFormat; + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + if (pOutbufOps->Set_Geometry(hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* input buffer enqueue for header parsing */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Header Size: %d", pExynosComponent, __FUNCTION__, oneFrameSize); + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + /* set buffer process type */ + if (pDecOps->Set_BufferProcessType(hMFCHandle, pExynosOutputPort->bufferProcessType) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set buffer process type(not supported)"); + } + + if (pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pSrcInputData->bufferHeader) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enqueue input buffer for header parsing"); +// 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, "Failed to run input buffer for header parsing"); + ret = OMX_ErrorCodecInit; + goto EXIT; + } + + ret = Vp9CodecUpdateResolution(pOMXComponent); + if (((EXYNOS_OMX_ERRORTYPE)ret == OMX_ErrorCorruptedHeader) && + (pExynosComponent->codecType != HW_VIDEO_DEC_SECURE_CODEC) && + (oneFrameSize >= 8)) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "CorruptedHeader Info : %02x %02x %02x %02x %02x %02x %02x %02x ...", + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0]) , *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 1), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 2), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 3), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 4), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 5), + *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 6), *((OMX_U8 *)pSrcInputData->multiPlaneBuffer.dataBuffer[0] + 7)); + if (ret != OMX_ErrorNone) { + VP9CodecStop(pOMXComponent, INPUT_PORT_INDEX); + pInbufOps->Cleanup_Buffer(hMFCHandle); + goto EXIT; + } + + Exynos_OSAL_SleepMillisec(0); + ret = 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + 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]; + + if (pExynosOutputPort->bDynamicDPBMode == OMX_TRUE) { + if (pDecOps->Enable_DynamicDPB(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to enable Dynamic DPB"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } + + pOutbufOps->Set_Shareable(hMFCHandle); + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + /* get dpb count */ + nOutbufs = pVp9Dec->hMFCVp9Handle.maxDPBNum; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Register output buffer */ + ret = VP9CodecRegistCodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, nOutbufs); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) + pOutbufOps->Enqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + nDataLen, + nPlaneCnt, + NULL); + } else { + if (pOutbufOps->Setup(hMFCHandle, MAX_OUTPUTBUFFER_NUM_DYNAMIC) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + 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; + + /* without Register output buffer */ + + /* Enqueue output buffer */ + for (i = 0; i < nOutbufs; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr, + (int *)pVideoDec->pMFCDecOutputBuffer[i]->fd, + pVideoDec->pMFCDecOutputBuffer[i]->bufferSize, + nDataLen, + nPlaneCnt, + NULL); + } + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { +#ifdef USE_ANB + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + int plane; + + Exynos_OSAL_Memset((OMX_PTR)planes, 0, sizeof(ExynosVideoPlane) * MAX_BUFFER_PLANE); + + /* get dpb count */ + nOutbufs = pExynosOutputPort->portDefinition.nBufferCountActual; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_TRUE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + for (i = 0; i < pExynosOutputPort->assignedBufferNum; i++) { + for (plane = 0; plane < nPlaneCnt; plane++) { + planes[plane].fd = pExynosOutputPort->extendBufferHeader[i].buf_fd[plane]; + planes[plane].addr = pExynosOutputPort->extendBufferHeader[i].pYUVBuf[plane]; + planes[plane].allocSize = nAllocLen[plane]; + } + + if (pOutbufOps->Register(hMFCHandle, planes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Register output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + pOutbufOps->Enqueue(hMFCHandle, + (void **)pExynosOutputPort->extendBufferHeader[i].pYUVBuf, + nDataLen, + nPlaneCnt, + NULL); + } + + if (pOutbufOps->Apply_RegisteredBuffer(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to Apply output buffer"); + ret = OMX_ErrorHardware; + goto EXIT; + } + } else { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } else { + /* get dpb count */ + nOutbufs = MAX_OUTPUTBUFFER_NUM_DYNAMIC; + if (pOutbufOps->Setup(hMFCHandle, nOutbufs) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosOutputPort->bIsANBEnabled == OMX_FALSE) && + (pExynosOutputPort->bStoreMetaData == OMX_FALSE)) { + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + } +#else + /*************/ + /* TBD */ + /*************/ + ret = OMX_ErrorNotImplemented; + goto EXIT; +#endif + } + + pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst = OMX_TRUE; + + 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; + + 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_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; + } + + Exynos_OSAL_Strcpy((char *)pComponentRole->cRole, EXYNOS_OMX_COMPONENT_VP9_DEC_ROLE); + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = 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; + } + + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + + 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_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_VP9_DEC_ROLE)) { + pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat = OMX_VIDEO_CodingVP9; + } else { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + } + break; + case OMX_IndexParamVideoErrorCorrection: + { + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pSrcErrorCorrectionType = (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *pDstErrorCorrectionType = NULL; + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + + ret = Exynos_OMX_Check_SizeVersion(pSrcErrorCorrectionType, sizeof(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcErrorCorrectionType->nPortIndex != INPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + 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; + + 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) { + case OMX_IndexConfigCommonOutputCrop: + { + EXYNOS_VP9DEC_HANDLE *pVp9Dec = NULL; + OMX_CONFIG_RECTTYPE *pSrcRectType = NULL; + OMX_CONFIG_RECTTYPE *pDstRectType = NULL; + + pVp9Dec = (EXYNOS_VP9DEC_HANDLE *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + + if (pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = OMX_ErrorNotReady; + break; + } + + pDstRectType = (OMX_CONFIG_RECTTYPE *)pComponentConfigStructure; + + if ((pDstRectType->nPortIndex != INPUT_PORT_INDEX) && + (pDstRectType->nPortIndex != OUTPUT_PORT_INDEX)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + EXYNOS_OMX_BASEPORT *pExynosPort = &pExynosComponent->pExynosPort[pDstRectType->nPortIndex]; + + pSrcRectType = &(pExynosPort->cropRectangle); + + 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_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; + + 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_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) { + 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_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; + OMX_COMPONENTTYPE *pOMXComponent = NULL; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL; + + 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; + OMX_PTR hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = NULL; + ExynosVideoDecBufferOps *pInbufOps = NULL; + ExynosVideoDecBufferOps *pOutbufOps = NULL; + ExynosVideoInstInfo *pVideoInstInfo = &(pVp9Dec->hMFCVp9Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i, plane; + + FunctionIn(); + + pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + pVideoDec->bDiscardCSDError = 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; + } + + pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {DEFAULT_MFC_INPUT_BUFFER_SIZE, 0, 0}; + 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) { + 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->hDestinationStartEvent); + + 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 + 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 = (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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + OMX_PTR hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + + int i, plane; + + FunctionIn(); + + if (pVideoDec->csc_handle != NULL) { + csc_deinit(pVideoDec->csc_handle); + pVideoDec->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pVp9Dec->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pVp9Dec->hDestinationStartEvent); + pVp9Dec->hDestinationStartEvent = NULL; + pVp9Dec->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalTerminate(pVp9Dec->hSourceStartEvent); + pVp9Dec->hSourceStartEvent = NULL; + pVp9Dec->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); + } 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); + } else if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + 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]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps = pVp9Dec->hMFCVp9Handle.pOutbufOps; + 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; + int i; + + FunctionIn(); + + if (pVp9Dec->hMFCVp9Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = VP9CodecSrcSetup(pOMXComponent, pSrcInputData); + goto EXIT; + } + + if ((pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst == OMX_FALSE) && + (pVideoDec->bForceHeaderParsing == OMX_FALSE)) { + ret = VP9CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to VP9CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + } + + if (((bInStartCode = Check_VP9_StartCode(pSrcInputData->multiPlaneBuffer.dataBuffer[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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x, oneFrameSize: %d", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pVp9Dec->hMFCVp9Handle.indexTimestamp, pSrcInputData->nFlags, oneFrameSize); + pDecOps->Set_FrameTag(hMFCHandle, pVp9Dec->hMFCVp9Handle.indexTimestamp); + pVp9Dec->hMFCVp9Handle.indexTimestamp++; + pVp9Dec->hMFCVp9Handle.indexTimestamp %= MAX_TIMESTAMP; + + if ((pVideoDec->bQosChanged == OMX_TRUE) && + (pDecOps->Set_QosRatio != NULL)) { + pDecOps->Set_QosRatio(hMFCHandle, pVideoDec->nQosRatio); + pVideoDec->bQosChanged = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] bufferHeader: 0x%x, dataBuffer: 0x%x", pExynosComponent, __FUNCTION__, pSrcInputData->bufferHeader, pSrcInputData->multiPlaneBuffer.dataBuffer[0]); + + if (pExynosInputPort->bufferProcessType & BUFFER_SHARE) + nAllocLen[0] = pSrcInputData->bufferHeader->nAllocLen; + else if (pExynosInputPort->bufferProcessType & BUFFER_COPY) + nAllocLen[0] = DEFAULT_MFC_INPUT_BUFFER_SIZE; + + if (pExynosInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosInputPort), + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp9Dec->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } else if (bInStartCode == OMX_FALSE) { + ret = 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 *)((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pVp9Dec->hMFCVp9Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + ExynosVideoDecBufferOps *pInbufOps = pVp9Dec->hMFCVp9Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->allocSize = 0; + pSrcOutputData->pPrivate = NULL; + } else { + pSrcOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pSrcOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[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, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#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]; + + ExynosVideoDecOps *pDecOps = pVp9Dec->hMFCVp9Handle.pDecOps; + 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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + 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] : %d => ADDR[%d]: 0x%x", pExynosComponent, __FUNCTION__, __LINE__, i, + pDstInputData->multiPlaneBuffer.dataBuffer[i]); + } + + if ((pVideoDec->bReconfigDPB == OMX_TRUE) && + (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) && + (pExynosOutputPort->exceptionFlag == GENERAL_STATE)) { + ret = VP9CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed to VP9CodecDstSetup(0x%x)", __func__, __LINE__, ret); + goto EXIT; + } + pVideoDec->bReconfigDPB = OMX_FALSE; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + codecReturn = pOutbufOps->Enqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } else { + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pDstInputData->bufferHeader); + } + + if (codecReturn != VIDEO_ERROR_NONE) { + if (codecReturn != VIDEO_ERROR_WRONGBUFFERSIZE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d", __FUNCTION__, __LINE__); + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &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; + + OMX_S32 indexTimestamp = 0; + int plane, nPlaneCnt; + + FunctionIn(); + + if (pVp9Dec->bDestinationStart == OMX_FALSE) { + ret = OMX_ErrorNone; + goto EXIT; + } + + while (1) { + if (pExynosOutputPort->bDynamicDPBMode == OMX_FALSE) { + pVideoBuffer = pOutbufOps->Dequeue(hMFCHandle); + if (pVideoBuffer == (ExynosVideoBuffer *)VIDEO_ERROR_DQBUF_EIO) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "HW is not available"); + ret = OMX_ErrorHardware; + goto EXIT; + } + + if (pVideoBuffer == NULL) { + ret = OMX_ErrorNone; + goto EXIT; + } + } else { + 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, "HW is not available"); + 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(pExynosOutputPort))) { + ret = OMX_ErrorNone; + break; + } + } + + if ((pVideoDec->bThumbnailMode == OMX_FALSE) && + (displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL)) { + if (pVideoDec->bReconfigDPB != OMX_TRUE) { + pExynosOutputPort->exceptionFlag = NEED_PORT_FLUSH; + pVideoDec->bReconfigDPB = OMX_TRUE; + Vp9CodecUpdateResolution(pOMXComponent); + pVideoDec->csc_set_format = OMX_FALSE; + } + ret = OMX_ErrorNone; + goto EXIT; + } + + pVp9Dec->hMFCVp9Handle.outputIndexTimestamp++; + pVp9Dec->hMFCVp9Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->allocSize = pDstOutputData->dataLen = 0; + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosOutputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pDstOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pDstOutputData->multiPlaneBuffer.fd[plane] = pVideoBuffer->planes[plane].fd; + pDstOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + pDstOutputData->dataLen += pVideoBuffer->planes[plane].dataSize; + } + pDstOutputData->usedDataLen = 0; + pDstOutputData->pPrivate = pVideoBuffer; + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->multiPlaneBuffer.dataBuffer[0] == + pVideoDec->pMFCDecOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoDec->pMFCDecOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecDecode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + pBufferInfo = (DECODE_CODEC_EXTRA_BUFFERINFO *)pDstOutputData->extInfo; + bufferGeometry = &pVp9Dec->hMFCVp9Handle.codecOutbufConf; + pBufferInfo->imageWidth = bufferGeometry->nFrameWidth; + pBufferInfo->imageHeight = bufferGeometry->nFrameHeight; + pBufferInfo->imageStride = bufferGeometry->nStride; + pBufferInfo->ColorFormat = Exynos_OSAL_Video2OMXFormat((int)bufferGeometry->eColorFormat); + Exynos_OSAL_Memcpy(&pBufferInfo->PDSB, &pVideoBuffer->PDSB, sizeof(PrivateDataShareBuffer)); + + 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 { + /* 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; + + if (pVideoBuffer->frameType & VIDEO_FRAME_CORRUPT) + pDstOutputData->nFlags |= OMX_BUFFERFLAG_DATACORRUPT; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] output timestamp %lld us (%.2f secs), indexTimestamp: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, indexTimestamp, pDstOutputData->nFlags); + } + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pExynosOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if (pVp9Dec->hMFCVp9Handle.videoInstInfo.specificInfo.dec.bLastFrameSupport == VIDEO_FALSE) { + if ((!(pVideoBuffer->frameType & VIDEO_FRAME_B)) && + (pExynosComponent->bSaveFlagEOS == OMX_TRUE)) { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + 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] indexTimestamp(%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 = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (!(pVideoBuffer->frameType & VIDEO_FRAME_B)) { + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } else { + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + } + } else { + if ((displayStatus == VIDEO_FRAME_STATUS_DECODING_FINISHED) || + (displayStatus == VIDEO_FRAME_STATUS_LAST_FRAME) || + ((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + + if (pExynosComponent->bBehaviorEOS == OMX_TRUE) { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 2; + + if (displayStatus != VIDEO_FRAME_STATUS_LAST_FRAME) { + pDstOutputData->nFlags &= (~OMX_BUFFERFLAG_EOS); + } else { + pDstOutputData->nFlags |= OMX_BUFFERFLAG_EOS; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + } + } + } else { + pDstOutputData->remainDataLen = bufferGeometry->nFrameWidth * bufferGeometry->nFrameHeight * 3 / 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_ErrorNone; + goto EXIT; + } + if (OMX_FALSE == Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) { + ret = OMX_ErrorNone; + 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; + } + + 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_SignalReset(pVp9Dec->hSourceStartEvent); + } + + ret = Exynos_VP9Dec_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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_ErrorOutputBufferUseYet; + else + ret = OMX_ErrorNone; + goto EXIT; + } + if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pVp9Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pVp9Dec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pVp9Dec->hDestinationStartEvent); + } + 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; + } + + 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 (pVp9Dec->hMFCVp9Handle.bConfiguredMFCDst == OMX_TRUE) { + ret = Exynos_VP9Dec_DstIn(pOMXComponent, pDstInputData); + if (ret != OMX_ErrorNone) { + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, ret, 0, NULL); + } + } + +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 (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pVp9Dec->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pVp9Dec->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoDec->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pVp9Dec->hDestinationStartEvent); + } + if (Exynos_OSAL_GetElemNum(&pVp9Dec->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + 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; + 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, "OMX_ErrorBadParameter, Line:%d", __LINE__); + goto EXIT; + } + if ((Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP9_DEC, componentName) != 0) && + (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP9_CUSTOM_DEC, componentName) != 0)) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoDecodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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) + pExynosPort->portDefinition.nBufferSize = CUSTOM_DEFAULT_VIDEO_INPUT_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/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 | BUFFER_ANBSHARE; + pExynosPort->portWayType = WAY2_PORT; + pExynosPort->ePlaneType = PLANE_MULTIPLE; + + 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; + +#if 0 /* unused code */ + pVideoDec->exynos_checkInputFrame = &Check_VP9_Frame; + pVideoDec->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoDec->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + pVideoDec->exynos_codec_reconfigAllBuffers = &Vp9CodecReconfigAllBuffers; + + pVideoDec->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + pVideoDec->exynos_codec_checkResolutionChange = &Vp9CodecCheckResolution; + + pVideoDec->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoDec->hSharedMemory == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + Exynos_OSAL_Free(pVp9Dec); + pVp9Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->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]: Exynos_Video_GetInstInfo is failed", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pVp9Dec); + pVp9Dec = ((EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + Exynos_OMX_VideoDecodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] GetInstInfo for dec %d %d %d %d", pExynosComponent, __FUNCTION__, + (pVp9Dec->hMFCVp9Handle.videoInstInfo.specificInfo.dec.bDualDPBSupport), + (pVp9Dec->hMFCVp9Handle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport), + (pVp9Dec->hMFCVp9Handle.videoInstInfo.specificInfo.dec.bLastFrameSupport), + (pVp9Dec->hMFCVp9Handle.videoInstInfo.specificInfo.dec.bSkypeSupport)); + + if (pVp9Dec->hMFCVp9Handle.videoInstInfo.specificInfo.dec.bDynamicDPBSupport == VIDEO_TRUE) + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bDynamicDPBMode = OMX_TRUE; + + Exynos_Output_SetSupportFormat(pExynosComponent); + + 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; + + 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) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/dec/vp9/Exynos_OMX_Vp9dec.h b/component/video/dec/vp9/Exynos_OMX_Vp9dec.h new file mode 100644 index 0000000..1f40180 --- /dev/null +++ b/component/video/dec/vp9/Exynos_OMX_Vp9dec.h @@ -0,0 +1,86 @@ +/* + * + * 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; + + ExynosVideoColorFormatType MFCOutputColorType; + ExynosVideoDecOps *pDecOps; + ExynosVideoDecBufferOps *pInbufOps; + ExynosVideoDecBufferOps *pOutbufOps; + ExynosVideoGeometry codecOutbufConf; + ExynosVideoInstInfo videoInstInfo; +} EXYNOS_MFC_VP9DEC_HANDLE; + +typedef struct _EXYNOS_VP9DEC_HANDLE +{ + /* OMX Codec specific */ + 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 hDestinationStartEvent; + + 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/component/video/dec/vp9/NOTICE b/component/video/dec/vp9/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/dec/vp9/library_register.c b/component/video/dec/vp9/library_register.c new file mode 100644 index 0000000..dafcdf9 --- /dev/null +++ b/component/video/dec/vp9/library_register.c @@ -0,0 +1,64 @@ +/* + * + * 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; +#ifdef USE_CUSTOM_COMPONENT_SUPPORT + /* component 2 - video custom decoder VP9 */ + Exynos_OSAL_Strcpy(ppExynosComponent[1]->componentName, EXYNOS_OMX_COMPONENT_VP9_CUSTOM_DEC); + Exynos_OSAL_Strcpy(ppExynosComponent[1]->roles[0], EXYNOS_OMX_COMPONENT_VP9_DEC_ROLE); + ppExynosComponent[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; +#endif +EXIT: + FunctionOut(); + return MAX_COMPONENT_NUM; +} diff --git a/component/video/dec/vp9/library_register.h b/component/video/dec/vp9/library_register.h new file mode 100644 index 0000000..397f886 --- /dev/null +++ b/component/video/dec/vp9/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 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 */ +#define EXYNOS_OMX_COMPONENT_VP9_DEC "OMX.Exynos.VP9.Decoder" +#define EXYNOS_OMX_COMPONENT_VP9_CUSTOM_DEC "OMX.Exynos.vp9.dec" +#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/component/video/enc/Android.mk b/component/video/enc/Android.mk new file mode 100644 index 0000000..6db368f --- /dev/null +++ b/component/video/enc/Android.mk @@ -0,0 +1,75 @@ +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_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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_CFLAGS += -DUSE_ANDROID +LOCAL_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +ifeq ($(EXYNOS_OMX_SUPPORT_TUNNELING), true) +LOCAL_CFLAGS += -DTUNNELING_SUPPORT +endif + +ifeq ($(BOARD_USE_METADATABUFFERTYPE), true) +LOCAL_CFLAGS += -DUSE_METADATABUFFERTYPE + +ifeq ($(BOARD_USE_STOREMETADATA), true) +LOCAL_CFLAGS += -DUSE_STOREMETADATA +endif + +ifeq ($(BOARD_USE_ANDROIDOPAQUE), true) +LOCAL_CFLAGS += -DUSE_ANDROIDOPAQUE +endif +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_QOS_CTRL), true) +LOCAL_CFLAGS += -DUSE_QOS_CTRL +endif + +ifeq ($(BOARD_USE_VIDEO_EXT_FOR_WFD_HDCP), true) +LOCAL_CFLAGS += -DUSE_VIDEO_EXT_FOR_WFD_HDCP +endif + +LOCAL_SHARED_LIBRARIES := libcsc + +include $(BUILD_STATIC_LIBRARY) diff --git a/component/video/enc/Exynos_OMX_Venc.c b/component/video/enc/Exynos_OMX_Venc.c new file mode 100644 index 0000000..78e6448 --- /dev/null +++ b/component/video/enc/Exynos_OMX_Venc.c @@ -0,0 +1,2038 @@ +/* + * + * 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" + +#ifdef USE_METADATABUFFERTYPE +#include "Exynos_OSAL_Android.h" +#endif + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "EXYNOS_VIDEO_ENC" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +inline 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_ANDROIDOPAQUE + 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, "Support Format[%d] : 0x%x", 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_ANDROIDOPAQUE + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) + eColorFormat = pVideoEnc->ANBColorFormat; +#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; +} + +void Exynos_Free_CodecBuffers( + 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; + 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_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, "Failed to Alloc codec buffer"); + 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, "Failed to Alloc plane"); + 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_TRACE, "PORT[%d]: pMFCCodecBuffer[%d]->pVirAddr[%d]: 0x%x", nPortIndex, i, j, ppCodecBuffer[i]->pVirAddr[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->currentState == OMX_StateExecuting) && + (pExynosComponent->pExynosPort[nPortIndex].portState == OMX_StateIdle) && + (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]; + + /* 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)); + + /* 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); + } + + 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->multiPlaneBuffer.dataBuffer[i] = pCodecBuffer->pVirAddr[i]; + pData->multiPlaneBuffer.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_VIDEOENC_COMPONENT *pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_OMX_BASEPORT *exynosOMXInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *exynosOMXOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + 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_SignalWait(pExynosComponent->pExynosPort[nPortIndex].pauseEvent, DEF_MAX_WAIT_TIME); + 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 *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; + CODEC_ENC_BUFFER *codecInputBuffer = (CODEC_ENC_BUFFER *)srcInputData->pPrivate; + OMX_COLOR_FORMATTYPE eColorFormat = exynosInputPort->portDefinition.format.video.eColorFormat; + OMX_COLOR_FORMATTYPE inputColorFormat = OMX_COLOR_FormatUnused; + + FunctionIn(); + + void *pInputBuf = (void *)inputUseBuffer->bufferHeader->pBuffer; + void *pSrcBuf[MAX_BUFFER_PLANE] = {NULL, }; + void *pDstBuf[MAX_BUFFER_PLANE] = {NULL, }; + + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + OMX_PTR ppBuf[MAX_BUFFER_PLANE] = {NULL, NULL, NULL}; + + OMX_U32 nSrcFrameWidth = 0, nSrcFrameHeight = 0; + OMX_U32 nSrcImageWidth = 0, nSrcImageHeight = 0, stride = 0; + + OMX_U32 nDstFrameWidth = 0, nDstFrameHeight = 0; + OMX_U32 nDstImageWidth = 0, nDstImageHeight = 0; + int i, nPlaneCnt; + + CSC_ERRORCODE cscRet = CSC_ErrorNone; + CSC_METHOD csc_method = CSC_METHOD_SW; + CSC_MEMTYPE csc_memType = CSC_MEMORY_USERPTR; + unsigned int srcCacheable = 1, dstCacheable = 1; + unsigned int csc_src_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar, PLANE_SINGLE_USER); + unsigned int csc_dst_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)OMX_COLOR_FormatYUV420SemiPlanar, exynosInputPort->ePlaneType); + + nDstFrameWidth = nSrcFrameWidth = ALIGN(exynosInputPort->portDefinition.format.video.nFrameWidth, 16); + nDstImageWidth = nSrcImageWidth = exynosInputPort->portDefinition.format.video.nFrameWidth; + nDstFrameHeight = nDstImageHeight = nSrcFrameHeight = nSrcImageHeight = exynosInputPort->portDefinition.format.video.nFrameHeight; + + if ((pVideoEnc->eRotationType == ROTATE_90) || + (pVideoEnc->eRotationType == ROTATE_270)) { + nDstFrameWidth = ALIGN(exynosInputPort->portDefinition.format.video.nFrameHeight, 16); + nDstImageWidth = exynosInputPort->portDefinition.format.video.nFrameHeight; + nDstFrameHeight = nDstImageHeight = exynosInputPort->portDefinition.format.video.nFrameWidth; + } + + csc_get_method(pVideoEnc->csc_handle, &csc_method); + + /* blur filtering and rotation are supported by H/W */ + if (((pVideoEnc->bUseBlurFilter == OMX_TRUE) || + (pVideoEnc->eRotationType != ROTATE_0)) && + (csc_method == CSC_METHOD_SW)) { + cscRet = csc_set_method(pVideoEnc->csc_handle, CSC_METHOD_HW); + if (cscRet != CSC_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: csc_set_method(CSC_METHOD_HW) is failed", __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + + csc_method = CSC_METHOD_HW; + } + + /* setup dst buffer */ + pDstBuf[0] = srcInputData->multiPlaneBuffer.dataBuffer[0]; + pDstBuf[1] = srcInputData->multiPlaneBuffer.dataBuffer[1]; + pDstBuf[2] = srcInputData->multiPlaneBuffer.dataBuffer[2]; + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + Exynos_OSAL_GetPlaneSize(inputColorFormat, exynosInputPort->ePlaneType, nDstImageWidth, nDstImageHeight, nDataLen, nAllocLen); + codecInputBuffer->dataSize = 0; + nPlaneCnt = Exynos_GetPlaneFromPort(exynosInputPort); + for (i = 0; i < nPlaneCnt; i++) + codecInputBuffer->dataSize += nDataLen[i]; + + if (exynosInputPort->ePlaneType == PLANE_SINGLE) { /* for H/W. only Y addr is valid */ + /* get a count of color plane */ + int nPlaneCnt = Exynos_OSAL_GetPlaneCount(inputColorFormat, PLANE_MULTIPLE); + + if (nPlaneCnt == 2) { /* Semi-Planar : interleaved */ + pDstBuf[1] = (void *)(((char *)pDstBuf[0]) + GET_UV_OFFSET(nDstImageWidth, nDstImageHeight)); + } else if (nPlaneCnt == 3) { /* Planar */ + pDstBuf[1] = (void *)(((char *)pDstBuf[0]) + GET_CB_OFFSET(nDstImageWidth, nDstImageHeight)); + pDstBuf[2] = (void *)(((char *)pDstBuf[0]) + GET_CR_OFFSET(nDstImageWidth, nDstImageHeight)); + } + } + + /* setup src buffer */ +#ifdef USE_METADATABUFFERTYPE + if (exynosInputPort->bStoreMetaData == OMX_TRUE) { + /* 1. meta data is enabled + * + * 1) gralloc source + * 2) camera source + */ + if (OMX_ErrorNone != Exynos_OSAL_GetInfoFromMetaData((OMX_BYTE)inputUseBuffer->bufferHeader->pBuffer, ppBuf)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: GetInfoFromMetadata() is failed", __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + +#ifdef USE_ANDROIDOPAQUE + /* 1-1) gralloc source + * -> kMetadataBufferTypeGrallocSource + * -> when format is not supported at H/W codec + */ + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) { + OMX_COLOR_FORMATTYPE eDestFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + csc_src_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)pVideoEnc->ANBColorFormat, exynosInputPort->ePlaneType); + csc_dst_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)eDestFormat, exynosInputPort->ePlaneType); + + if (OMX_ErrorNone != Exynos_OSAL_LockANBHandle(ppBuf[0], nSrcImageWidth, nSrcImageHeight, OMX_COLOR_FormatAndroidOpaque, &stride, planes)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OSAL_LockANBHandle() failed", __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + +#ifdef USE_HW_CSC_GRALLOC_SOURCE +#ifdef USE_FIMC_CSC + if ((csc_method != CSC_METHOD_HW) && + (pVideoEnc->ANBColorFormat != (OMX_COLOR_FORMATTYPE)OMX_COLOR_Format32BitRGBA8888)) +#else + if (csc_method != CSC_METHOD_HW) +#endif // USE_FIMC_CSC + { + cscRet = csc_set_method(pVideoEnc->csc_handle, CSC_METHOD_HW); + if (cscRet != CSC_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: csc_set_method(CSC_METHOD_HW) is failed", __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + csc_method = CSC_METHOD_HW; + } +#endif // USE_HW_CSC_GRALLOC_SOURCE + + pSrcBuf[0] = (void *)planes[0].addr; + pSrcBuf[1] = (void *)planes[1].addr; + pSrcBuf[2] = (void *)planes[2].addr; + +#ifdef USE_DMA_BUF + if (csc_method == CSC_METHOD_HW) { + srcCacheable = 0; + csc_memType = CSC_MEMORY_DMABUF; + pSrcBuf[0] = INT_TO_PTR(planes[0].fd); + pSrcBuf[1] = INT_TO_PTR(planes[1].fd); + pSrcBuf[2] = INT_TO_PTR(planes[2].fd); + } +#endif // USE_DMA_BUF + } else +#endif // USE_ANDROIDOPAQUE + { + /* 1-2) camera source + * -> kMetadataBufferTypeCameraSource + * -> when blur filter or rotation mode is enabled + */ + csc_src_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)eColorFormat, exynosInputPort->ePlaneType); + csc_dst_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)eColorFormat, exynosInputPort->ePlaneType); + +#ifdef USE_DMA_BUF + if (csc_method == CSC_METHOD_HW) { + srcCacheable = 0; + csc_memType = CSC_MEMORY_DMABUF; + pSrcBuf[0] = INT_TO_PTR(ppBuf[0]); + pSrcBuf[1] = INT_TO_PTR(ppBuf[1]); + pSrcBuf[2] = INT_TO_PTR(ppBuf[2]); + } else +#endif // USE_DMA_BUF + { /* CSC_METHOD_SW */ + Exynos_OSAL_GetPlaneSize(inputColorFormat, exynosInputPort->ePlaneType, nSrcImageWidth, nSrcImageHeight, nDataLen, nAllocLen); + for (i = 0; i < nPlaneCnt; i++) { + if (PTR_TO_INT(ppBuf[i]) != -1) { + pSrcBuf[i] = Exynos_OSAL_SharedMemory_IONToVirt(pVideoEnc->hSharedMemory, PTR_TO_INT(ppBuf[i])); + if(pSrcBuf[i] == NULL) + pSrcBuf[i] = Exynos_OSAL_SharedMemory_Map(pVideoEnc->hSharedMemory, nAllocLen[i], PTR_TO_INT(ppBuf[i])); + + if (pSrcBuf[i] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] Exynos_OSAL_SharedMemory_Map(%d) is failed", __FUNCTION__, PTR_TO_INT(ppBuf[i])); + ret = OMX_FALSE; + goto EXIT; + } + } + } + } + } + } else +#endif // USE_USE_METADATABUFFERTYPE + { + /* 2. meta data is not enabled + * + * 1) format is supported at HW codec + * uses SW CSC for satisfying HW constraints except for blur, rotation mode and USE_CSC_HW. + * * blur, rotation is supported by HW. + * 2) format is not supported at HW codec + * needs CSC(Color-Space-Conversion). + */ + /* calculate each plane info from the application */ + Exynos_OSAL_GetPlaneSize(eColorFormat, PLANE_SINGLE_USER, nSrcImageWidth, nSrcImageHeight, nDataLen, nAllocLen); + pSrcBuf[0] = (void *)((char *)pInputBuf); + pSrcBuf[1] = (void *)((char *)pInputBuf + nDataLen[0]); + pSrcBuf[2] = (void *)((char *)pInputBuf + nDataLen[0] + nDataLen[1]); + +#ifdef USE_CSC_HW + if ((pVideoEnc->bUseBlurFilter != OMX_TRUE) && + (pVideoEnc->eRotationType == ROTATE_0) && + (csc_method != CSC_METHOD_HW) && + (eColorFormat == inputColorFormat)) { +#else + if ((pVideoEnc->bUseBlurFilter != OMX_TRUE) && + (pVideoEnc->eRotationType == ROTATE_0) && + (eColorFormat == inputColorFormat)) { +#endif + csc_memType = CSC_MEMORY_MFC; /* to remove stride value */ + csc_method = CSC_METHOD_SW; + + cscRet = csc_set_method(pVideoEnc->csc_handle, CSC_METHOD_SW); + if (cscRet != CSC_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: csc_set_method(CSC_METHOD_SW) for CSC_MEMORY_MFC is failed", __FUNCTION__); + ret = OMX_FALSE; + goto EXIT; + } + } + + if (pVideoEnc->csc_set_format == OMX_FALSE) { + csc_src_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)eColorFormat, PLANE_SINGLE_USER); + csc_dst_color_format = Exynos_OSAL_OMX2HALPixelFormat((unsigned int)inputColorFormat, exynosInputPort->ePlaneType); + } + +#ifdef USE_DMA_BUF + if (csc_method == CSC_METHOD_HW) { + srcCacheable = 0; + csc_memType = CSC_MEMORY_DMABUF; + pSrcBuf[0] = INT_TO_PTR(Exynos_OSAL_SharedMemory_VirtToION(pVideoEnc->hSharedMemory, (char *)pInputBuf)); + pSrcBuf[1] = NULL; + pSrcBuf[2] = NULL; + } +#endif + } + + /* re-check a csc_method and setup dst buffer */ +#ifdef USE_DMA_BUF + if (csc_method == CSC_METHOD_HW) { + dstCacheable = 0; + csc_memType = CSC_MEMORY_DMABUF; + pDstBuf[0] = INT_TO_PTR(srcInputData->multiPlaneBuffer.fd[0]); + pDstBuf[1] = INT_TO_PTR(srcInputData->multiPlaneBuffer.fd[1]); + pDstBuf[2] = INT_TO_PTR(srcInputData->multiPlaneBuffer.fd[2]); + } +#endif + + /* set info to libcsc */ + if (pVideoEnc->csc_set_format == OMX_FALSE) { + csc_set_src_format( + pVideoEnc->csc_handle, /* handle */ + nSrcFrameWidth, /* width */ + nSrcFrameHeight , /* height */ + 0, /* crop_left */ + 0, /* crop_right */ + nSrcImageWidth, /* crop_width */ + nSrcImageHeight, /* crop_height */ + csc_src_color_format, /* color_format */ + srcCacheable); /* cacheable */ + + csc_set_dst_format( + pVideoEnc->csc_handle, /* handle */ + nDstFrameWidth, /* width */ + nDstFrameHeight, /* height */ + 0, /* crop_left */ + 0, /* crop_right */ + nDstImageWidth, /* crop_width */ + nDstImageHeight, /* crop_height */ + csc_dst_color_format, /* color_format */ + dstCacheable); /* cacheable */ + + csc_set_eq_property( + pVideoEnc->csc_handle, /* handle */ + CSC_EQ_MODE_USER, /* user select */ + CSC_EQ_RANGE_NARROW, /* narrow */ + CSC_EQ_COLORSPACE_SMPTE170M); /* bt.601 */ + + pVideoEnc->csc_set_format = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] %s CSC(%x) %s/ [SRC] width(%d/%d),height(%d/%d),format(0x%x) -> [DST] width(%d/%d),height(%d/%d),format(0x%x)", + pExynosComponent, __FUNCTION__, + (csc_method == CSC_METHOD_SW)? "SW":"HW", csc_memType, + (pVideoEnc->eRotationType != ROTATE_0)? "with rotation":"", + nSrcFrameWidth, nSrcImageWidth, nSrcFrameHeight, nSrcImageHeight, csc_src_color_format, + nDstFrameWidth, nDstImageWidth, nDstFrameHeight, nDstImageHeight, csc_dst_color_format); + } + + /* blur filter */ + 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_1080: + filterType = CSC_FT_1080; + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] invliad eBlurResol(%d)", __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_set_src_buffer( + pVideoEnc->csc_handle, /* handle */ + pSrcBuf, + csc_memType); /* YUV Addr or FD */ + + csc_set_dst_buffer( + pVideoEnc->csc_handle, /* handle */ + pDstBuf, + csc_memType); /* YUV Addr or FD */ + + if (pVideoEnc->eRotationType != ROTATE_0) + cscRet = csc_convert_with_rotation(pVideoEnc->csc_handle, (int)pVideoEnc->eRotationType, 0, 0); + else + cscRet = csc_convert(pVideoEnc->csc_handle); + + if (cscRet != CSC_ErrorNone) + ret = OMX_FALSE; + else + ret = OMX_TRUE; + +#ifdef USE_METADATABUFFERTYPE + if ((exynosInputPort->bStoreMetaData == OMX_TRUE) && + (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque)) { +#ifdef USE_ANDROIDOPAQUE + Exynos_OSAL_UnlockANBHandle(ppBuf[0]); +#endif + } +#endif + +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; + OMX_BYTE checkInputStream = NULL; + OMX_U32 checkInputStreamLen = 0; + OMX_BOOL flagEOS = OMX_FALSE; + + FunctionIn(); + + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + if ((srcInputData->multiPlaneBuffer.dataBuffer[0] == NULL) || + (srcInputData->pPrivate == NULL)) { + ret = OMX_FALSE; + goto EXIT; + } + } + + if (inputUseBuffer->dataValid == OMX_TRUE) { + if (exynosInputPort->bufferProcessType & BUFFER_SHARE) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Input port is BUFFER_SHARE", pExynosComponent, __FUNCTION__); + + Exynos_Shared_BufferToData(inputUseBuffer, srcInputData, ONE_PLANE); +#ifdef USE_METADATABUFFERTYPE + if (exynosInputPort->bStoreMetaData == OMX_TRUE) { + OMX_COLOR_FORMATTYPE inputColorFormat = OMX_COLOR_FormatUnused; + + OMX_PTR ppBuf[MAX_BUFFER_PLANE] = {NULL, NULL, NULL}; + unsigned int nAllocLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + unsigned int nDataLen[MAX_BUFFER_PLANE] = {0, 0, 0}; + int plane = 0, nPlaneCnt = 0; + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + Exynos_OSAL_GetPlaneSize(inputColorFormat, exynosInputPort->ePlaneType, nFrameWidth, nFrameHeight, nDataLen, nAllocLen); + nPlaneCnt = Exynos_GetPlaneFromPort(exynosInputPort); + if (pVideoEnc->nInbufSpareSize > 0) { + for (plane = 0; plane < nPlaneCnt; plane++) + nAllocLen[plane] += pVideoEnc->nInbufSpareSize; + } + + for (plane = 0; plane < MAX_BUFFER_PLANE; plane++) { + srcInputData->multiPlaneBuffer.fd[plane] = -1; + srcInputData->multiPlaneBuffer.dataBuffer[plane] = NULL; + } + + 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); + Exynos_InputBufferReturn(pOMXComponent, inputUseBuffer); + Exynos_ResetDataBuffer(inputUseBuffer); /* reset dataBuffer */ + } else { + /* with EOS flag + * makes a buffer for EOS handling needed at MFC Processing scheme. + */ + for (plane = 0; plane < nPlaneCnt; plane++) { + srcInputData->multiPlaneBuffer.dataBuffer[plane] = + (void *)Exynos_OSAL_SharedMemory_Alloc(pVideoEnc->hSharedMemory, nAllocLen[plane], NORMAL_MEMORY); + srcInputData->multiPlaneBuffer.fd[plane] = + Exynos_OSAL_SharedMemory_VirtToION(pVideoEnc->hSharedMemory, srcInputData->multiPlaneBuffer.dataBuffer[plane]); + } + } + } else { + if (OMX_ErrorNone != Exynos_OSAL_GetInfoFromMetaData((OMX_BYTE)inputUseBuffer->bufferHeader->pBuffer, ppBuf)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: GetInfoFromMetadata() is failed", __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + ret = OMX_FALSE; + goto EXIT; + } +#ifdef USE_DMA_BUF +#ifdef USE_ANDROIDOPAQUE + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) { + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + OMX_U32 stride = 0; + + Exynos_OSAL_LockANBHandle(ppBuf[0], nFrameWidth, nFrameHeight, OMX_COLOR_FormatAndroidOpaque, &stride, planes); + + if (stride == ALIGN(exynosInputPort->portDefinition.format.video.nFrameWidth, 16)) + exynosInputPort->portDefinition.format.video.nStride = stride; + + for (plane = 0; plane < nPlaneCnt; plane++) { + srcInputData->multiPlaneBuffer.fd[plane] = planes[plane].fd; + srcInputData->multiPlaneBuffer.dataBuffer[plane] = planes[plane].addr; + } + } else +#endif + { + /* kMetadataBufferTypeCameraSource */ + for (plane = 0; plane < nPlaneCnt; plane++) { + srcInputData->multiPlaneBuffer.fd[plane] = PTR_TO_INT(ppBuf[plane]); + } + } + + for (plane = 0; plane < nPlaneCnt; plane++) { + if ((srcInputData->multiPlaneBuffer.fd[plane] != -1) && + (srcInputData->multiPlaneBuffer.dataBuffer[plane] == NULL)) { + srcInputData->multiPlaneBuffer.dataBuffer[plane] = + Exynos_OSAL_SharedMemory_IONToVirt(pVideoEnc->hSharedMemory, srcInputData->multiPlaneBuffer.fd[plane]); + if(srcInputData->multiPlaneBuffer.dataBuffer[plane] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "Initial mapping is now in progress. fd[%d]",srcInputData->multiPlaneBuffer.fd[plane]); + srcInputData->multiPlaneBuffer.dataBuffer[plane] = + Exynos_OSAL_SharedMemory_Map(pVideoEnc->hSharedMemory, nAllocLen[plane], srcInputData->multiPlaneBuffer.fd[plane]); + } + } + } +#else +#ifdef USE_ANDROIDOPAQUE + if (eColorFormat == OMX_COLOR_FormatAndroidOpaque) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_COLOR_FormatAndroidOpaque share don't implemented in UserPtr mode."); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorNotImplemented, 0, NULL); + ret = OMX_FALSE; + goto EXIT; + } else +#endif + { + /* kMetadataBufferTypeCameraSource */ + for (plane = 0; plane < MAX_BUFFER_PLANE; plane++) { + srcInputData->multiPlaneBuffer.dataBuffer[plane] = (int)ppBuf[plane]; + } + } +#endif + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s:%d YAddr: 0x%p CbCrAddr: 0x%p", __FUNCTION__, __LINE__, ppBuf[0], ppBuf[1]); + } + } +#endif + /* reset dataBuffer */ + Exynos_ResetDataBuffer(inputUseBuffer); + } else if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] Input port is BUFFER_COPY", pExynosComponent, __FUNCTION__); + + checkInputStream = inputUseBuffer->bufferHeader->pBuffer + inputUseBuffer->usedDataLen; + checkInputStreamLen = inputUseBuffer->remainDataLen; + + pExynosComponent->bUseFlagEOF = OMX_TRUE; + + if (checkInputStreamLen == 0) { + inputUseBuffer->nFlags |= OMX_BUFFERFLAG_EOS; + flagEOS = OMX_TRUE; + } + + copySize = checkInputStreamLen; + + if (((srcInputData->allocSize) - (srcInputData->dataLen)) >= copySize) { + if ((copySize > 0) || (inputUseBuffer->nFlags & OMX_BUFFERFLAG_EOS)) { + ret = OMX_TRUE; + if (copySize > 0) + ret = Exynos_CSC_InputData(pOMXComponent, srcInputData); + if (ret) { + 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; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Exynos_CSC_InputData() failure"); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + ret = OMX_FALSE; + } + } else { + ret = OMX_FALSE; + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "input codec buffer is smaller than decoded input data size Out Length"); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + ret = OMX_FALSE; + } + + Exynos_InputBufferReturn(pOMXComponent, inputUseBuffer); + + /* reset dataBuffer */ + Exynos_ResetDataBuffer(inputUseBuffer); + } + + if ((srcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "bSaveFlagEOS : OMX_TRUE"); + pExynosComponent->bSaveFlagEOS = OMX_TRUE; + if (srcInputData->dataLen != 0) + pExynosComponent->bBehaviorEOS = OMX_TRUE; + } + + 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_TRACE, "first frame timestamp after seeking %lld us (%.2f secs)", + srcInputData->timeStamp, srcInputData->timeStamp / 1E6); + } + + ret = OMX_TRUE; + } + +EXIT: + + 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(dstOutputData, outputUseBuffer, OMX_FALSE) == 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_TRACE, "garbage frame drop after flush"); + ret = OMX_TRUE; + goto EXIT; + } + } else if (pExynosComponent->checkTimeStamp.needSetStartTimeStamp == OMX_TRUE) { + ret = OMX_TRUE; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "input buffer has not come after flush."); + goto EXIT; + } + + if (exynosOutputPort->bufferProcessType & BUFFER_COPY) { + if (dstOutputData->remainDataLen <= (outputUseBuffer->allocSize - outputUseBuffer->dataLen)) { + copySize = dstOutputData->remainDataLen; + if (copySize > 0) + Exynos_OSAL_Memcpy((outputUseBuffer->bufferHeader->pBuffer + outputUseBuffer->dataLen), + ((char *)dstOutputData->multiPlaneBuffer.dataBuffer[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)) { + Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer); + } + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "output buffer is smaller than encoded data size Out Length"); + 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) == OMX_BUFFERFLAG_EOS) || + (CHECK_PORT_BEING_FLUSHED(exynosOutputPort))) { + if (exynosOutputPort->bStoreMetaData == OMX_TRUE) + Exynos_OSAL_SetDataLengthToMetaData(outputUseBuffer->bufferHeader->pBuffer, outputUseBuffer->remainDataLen); + Exynos_OutputBufferReturn(pOMXComponent, outputUseBuffer); + } else { + Exynos_OMX_FillThisBufferAgain(pOMXComponent, outputUseBuffer->bufferHeader); + Exynos_ResetDataBuffer(outputUseBuffer); + } + } + } else { + ret = OMX_FALSE; + } + +EXIT: + FunctionOut(); + + return ret; +} + +#ifdef USE_METADATABUFFERTYPE +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 *exynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_DATABUFFER *srcInputUseBuffer = &exynosInputPort->way.port2WayDataBuffer.inputDataBuffer; + EXYNOS_OMX_DATA *pSrcInputData = &exynosInputPort->processData; + OMX_COLOR_FORMATTYPE eColorFormat = exynosInputPort->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}; + OMX_PTR ppBuf[MAX_BUFFER_PLANE] = {NULL, NULL, NULL}; + int i = 0; + +#ifdef USE_METADATABUFFERTYPE + if (exynosInputPort->bStoreMetaData == OMX_TRUE) { + 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); +#ifdef USE_ANDROIDOPAQUE + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) { + pVideoEnc->ANBColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + exynosInputPort->bufferProcessType = BUFFER_SHARE; + Exynos_SetPlaneToPort(exynosInputPort, Exynos_OSAL_GetPlaneCount(pVideoEnc->ANBColorFormat, exynosInputPort->ePlaneType)); + } else +#endif + { + Exynos_SetPlaneToPort(exynosInputPort, Exynos_OSAL_GetPlaneCount(eColorFormat, exynosInputPort->ePlaneType)); + } + + goto EXIT; + } else { + ret = Exynos_OSAL_GetInfoFromMetaData((OMX_BYTE)srcInputUseBuffer->bufferHeader->pBuffer, ppBuf); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: GetInfoFromMetadata() is failed", __FUNCTION__); + goto EXIT; + } + +#ifdef USE_ANDROIDOPAQUE + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) { + /* kMetadataBufferTypeGrallocSource */ + pVideoEnc->ANBColorFormat = Exynos_OSAL_GetANBColorFormat(ppBuf[0]); + eActualFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + if (eActualFormat == OMX_COLOR_FormatUnused) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "[%s] unsupported color format : ANB color is 0x%x", __FUNCTION__, pVideoEnc->ANBColorFormat); + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + if (pVideoEnc->ANBColorFormat == eActualFormat) { + exynosInputPort->bufferProcessType = BUFFER_SHARE; + Exynos_SetPlaneToPort(exynosInputPort, Exynos_OSAL_GetPlaneCount(pVideoEnc->ANBColorFormat, exynosInputPort->ePlaneType)); + } else { + exynosInputPort->bufferProcessType = BUFFER_COPY; + } + } else +#endif + { + Exynos_SetPlaneToPort(exynosInputPort, Exynos_OSAL_GetPlaneCount(eColorFormat, exynosInputPort->ePlaneType)); + } + } + + } +#endif + + /* forcefully have to use BUFFER_COPY mode, if blur filter is used or rotation is needed */ + if ((pVideoEnc->bUseBlurFilter == OMX_TRUE) || + (pVideoEnc->eRotationType != ROTATE_0)) { + exynosInputPort->bufferProcessType = BUFFER_COPY; + } + + if ((exynosInputPort->bufferProcessType & BUFFER_COPY) == BUFFER_COPY) { + OMX_U32 nFrameWidth = exynosInputPort->portDefinition.format.video.nFrameWidth; + OMX_U32 nFrameHeight = exynosInputPort->portDefinition.format.video.nFrameHeight; + + if ((pVideoEnc->eRotationType == ROTATE_90) || + (pVideoEnc->eRotationType == ROTATE_270)) { + nFrameWidth = exynosInputPort->portDefinition.format.video.nFrameHeight; + nFrameHeight = exynosInputPort->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, "[%s] unsupported color format : 0x%x", __func__, eActualFormat); + ret = OMX_ErrorNotImplemented; + goto EXIT; + } + + Exynos_SetPlaneToPort(exynosInputPort, Exynos_OSAL_GetPlaneCount(eActualFormat, exynosInputPort->ePlaneType)); + Exynos_OSAL_GetPlaneSize(eActualFormat, exynosInputPort->ePlaneType, nFrameWidth, nFrameHeight, nDataLen, nAllocLen); + + if (pVideoEnc->nInbufSpareSize > 0) { + for (i = 0; i < Exynos_GetPlaneFromPort(exynosInputPort); i++) + nAllocLen[i] += pVideoEnc->nInbufSpareSize; + } + + 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, pVideoEnc->pMFCEncInputBuffer[i]); + } else if (exynosInputPort->bufferProcessType == BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + +EXIT: + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] eActualFormat: 0x%x eColorFormat: 0x%x ANBColorFormat: 0x%x bufferProcessType: 0x%x", pExynosComponent, __FUNCTION__, eActualFormat, eColorFormat, pVideoEnc->ANBColorFormat, exynosInputPort->bufferProcessType); + + return ret; +} +#endif + +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; + OMX_BOOL bValidCodecData = 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_ENABLED(exynosInputPort))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_SemaphoreWait(exynosInputPort->semWaitPortEnable[INPUT_WAY_INDEX]); + continue; + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent, INPUT_PORT_INDEX)) && + (!pVideoEnc->bExitBufferProcessThread)) { + Exynos_OSAL_SleepMillisec(0); + + if (CHECK_PORT_BEING_FLUSHED(exynosInputPort)) + break; + if (exynosInputPort->portState != OMX_StateIdle) + break; + + Exynos_OSAL_MutexLock(srcInputUseBuffer->bufferMutex); + if (pVideoEnc->bFirstInput == OMX_FALSE) { + if (exynosInputPort->bufferProcessType & BUFFER_COPY) { + OMX_PTR codecBuffer; + if ((pSrcInputData->multiPlaneBuffer.dataBuffer[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) { + (*(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_ENABLED(exynosInputPort))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_SemaphoreWait(exynosInputPort->semWaitPortEnable[OUTPUT_WAY_INDEX]); + 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) { + OMX_BOOL bNeedUnlock = OMX_FALSE; + OMX_COLOR_FORMATTYPE eColorFormat = exynosInputPort->portDefinition.format.video.eColorFormat; +#ifdef USE_ANDROIDOPAQUE + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) + bNeedUnlock = OMX_TRUE; +#endif + Exynos_Shared_DataToBuffer(&srcOutputData, srcOutputUseBuffer, bNeedUnlock); + 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_ENABLED(exynosOutputPort))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_SemaphoreWait(exynosOutputPort->semWaitPortEnable[INPUT_WAY_INDEX]); + continue; + } + + while ((Exynos_Check_BufferProcess_State(pExynosComponent, OUTPUT_PORT_INDEX)) && + (!pVideoEnc->bExitBufferProcessThread)) { + Exynos_OSAL_SleepMillisec(0); + + if ((CHECK_PORT_BEING_FLUSHED(exynosOutputPort)) || + (!CHECK_PORT_POPULATED(exynosOutputPort))) + break; + if (exynosOutputPort->portState != OMX_StateIdle) + 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; + } + Exynos_Shared_BufferToData(dstInputUseBuffer, &dstInputData, ONE_PLANE); + if (exynosOutputPort->bStoreMetaData == OMX_TRUE) { + int ionFD = -1; + OMX_PTR dataBuffer = NULL; + OMX_PTR ppBuf[MAX_BUFFER_PLANE] = {NULL, NULL, NULL}; + + ret = Exynos_OSAL_GetBufferFdFromMetaData((OMX_BYTE)dstInputUseBuffer->bufferHeader->pBuffer, ppBuf); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OSAL_GetBufferFdFromMetaData() is failed", __FUNCTION__); + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, OMX_ErrorUndefined, 0, NULL); + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + + /* caution : data loss */ + ionFD = PTR_TO_INT(ppBuf[0]); + + dataBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoEnc->hSharedMemory, ionFD); + if (dataBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Wrong dst-input Metadata buffer", __LINE__); + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + dstInputData.multiPlaneBuffer.fd[0] = ionFD; + dstInputData.multiPlaneBuffer.dataBuffer[0] = dataBuffer; + } else { + if (pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) { + /* caution : data loss */ + int ionFD = PTR_TO_INT(dstInputData.multiPlaneBuffer.dataBuffer[0]); + + OMX_PTR dataBuffer = NULL; + dataBuffer = Exynos_OSAL_SharedMemory_IONToVirt(pVideoEnc->hSharedMemory, ionFD); + if (dataBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Wrong dst-input Secure buffer", __LINE__); + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(dstInputUseBuffer->bufferMutex); + break; + } + dstInputData.multiPlaneBuffer.fd[0] = ionFD; + dstInputData.multiPlaneBuffer.dataBuffer[0] = dataBuffer; + } else { + dstInputData.multiPlaneBuffer.fd[0] = + Exynos_OSAL_SharedMemory_VirtToION(pVideoEnc->hSharedMemory, + dstInputData.multiPlaneBuffer.dataBuffer[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_ENABLED(exynosOutputPort))) { + /* sema will be posted at PortEnable */ + Exynos_OSAL_SemaphoreWait(exynosOutputPort->semWaitPortEnable[OUTPUT_WAY_INDEX]); + 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 (((ret == OMX_ErrorNone) && (dstOutputUseBuffer->dataValid == OMX_TRUE)) || + (exynosOutputPort->bufferProcessType & BUFFER_SHARE)) { + Exynos_Postprocess_OutputData(pOMXComponent, pDstOutputData); + } + + if (exynosOutputPort->bufferProcessType & BUFFER_COPY) { + 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; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = 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; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + 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; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = 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; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + 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; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = 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; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + 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; + EXYNOS_OMX_BASECOMPONENT *pExynosComponent = 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; + } + pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + 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; + unsigned int i = 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_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); + + 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); + + 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); + + 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) { + 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; + + pVideoEnc = Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_VIDEOENC_COMPONENT)); + if (pVideoEnc == NULL) { + Exynos_OMX_Port_Destructor(pOMXComponent); + Exynos_OMX_BaseComponent_Destructor(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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->nInbufSpareSize = 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; + + pExynosComponent->bMultiThreadProcess = OMX_TRUE; + + /* 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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; + +#ifdef USE_METADATABUFFERTYPE + pExynosPort->bStoreMetaData = OMX_FALSE; +#endif + + /* 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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; + + 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) { + 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; + + 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; +} diff --git a/component/video/enc/Exynos_OMX_Venc.h b/component/video/enc/Exynos_OMX_Venc.h new file mode 100644 index 0000000..8b166de --- /dev/null +++ b/component/video/enc/Exynos_OMX_Venc.h @@ -0,0 +1,178 @@ +/* + * + * 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 DEFAULT_FRAME_WIDTH 176 +#define DEFAULT_FRAME_HEIGHT 144 + +#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 3 +#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 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 2 /* 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 */ + int 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 nInbufSpareSize; + 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 bUseBlurFilter; + EXYNOS_OMX_BLUR_MODE eBlurMode; /* Down/Up or Coefficient mothod */ + EXYNOS_OMX_BLUR_RESOL eBlurResol; + + EXYNOS_OMX_ROTATION_TYPE eRotationType; + + OMX_BOOL bFirstInput; + OMX_BOOL bFirstOutput; + OMX_BOOL bEncDRC; + + OMX_COLOR_FORMATTYPE ANBColorFormat; + + /* CSC handle */ + OMX_PTR csc_handle; + OMX_U32 csc_set_format; + + 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); + +#if 0 /* unused code */ + int (*exynos_checkInputFrame) (OMX_U8 *pInputStream, OMX_U32 buffSize, OMX_U32 flag, + OMX_BOOL bPreviousFrameEOF, OMX_BOOL *pbEndOfFrame); + OMX_ERRORTYPE (*exynos_codec_getCodecInputPrivateData) (OMX_PTR codecBuffer, OMX_PTR addr[], OMX_U32 size[]); +#endif + + 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 + +inline 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/component/video/enc/Exynos_OMX_VencControl.c b/component/video/enc/Exynos_OMX_VencControl.c new file mode 100644 index 0000000..b90e9c3 --- /dev/null +++ b/component/video/enc/Exynos_OMX_VencControl.c @@ -0,0 +1,2129 @@ +/* + * + * 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) + * @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_Mutex.h" +#include "Exynos_OSAL_ETC.h" +#include "Exynos_OSAL_SharedMemory.h" + +#ifdef USE_METADATABUFFERTYPE +#include "Exynos_OSAL_Android.h" +#endif + +#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) { + 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) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + + if (pExynosPort->portState != OMX_StateIdle) { + 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) { + 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++; + 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 = pTempBufferHdr; + ret = OMX_ErrorNone; + 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; + int fdTempBuffer = -1; + MEMORY_TYPE eMemType = NORMAL_MEMORY; + 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; + + if (pExynosComponent->hComponentHandle == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + + if (nPortIndex >= pExynosComponent->portParam.nPorts) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; +/* + if (pExynosPort->portState != OMX_StateIdle ) { + 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->bStoreMetaData == OMX_TRUE)) { + OMX_U32 nDataBufferSize = 0; + +#ifdef USE_VIDEO_EXT_FOR_WFD_HDCP + if ((eMemType & SECURE_MEMORY) || // secure component + (eMemType & CONTIG_MEMORY)) // Normal DRM + eMemType |= EXT_MEMORY; +#endif + + nDataBufferSize = ALIGN(pExynosPort->portDefinition.format.video.nFrameWidth * + pExynosPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + pTempBuffer = Exynos_OSAL_AllocMetaDataBuffer(pVideoEnc->hSharedMemory, + pExynosComponent->codecType, + nPortIndex, + nDataBufferSize, + eMemType); + if (pTempBuffer == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else { + pTempBuffer = Exynos_OSAL_SharedMemory_Alloc(pVideoEnc->hSharedMemory, nSizeBytes, eMemType); + if (pTempBuffer == NULL) { + 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_SharedMemory_Free(pVideoEnc->hSharedMemory, pTempBuffer); + 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->bStoreMetaData == OMX_FALSE)) + pTempBufferHdr->pBuffer = INT_TO_PTR(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++; + 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 = pTempBufferHdr; + ret = OMX_ErrorNone; + goto EXIT; + } + } + + Exynos_OSAL_Free(pTempBufferHdr); + Exynos_OSAL_SharedMemory_Free(pVideoEnc->hSharedMemory, pTempBuffer); + + 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) { + 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) { + 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 != OMX_StateLoaded) && + (pExynosPort->portState != OMX_StateInvalid)) && + (pExynosPort->portDefinition.bEnabled != OMX_FALSE)) { + (*(pExynosComponent->pCallbacks->EventHandler)) (pOMXComponent, + pExynosComponent->callbackData, + (OMX_U32)OMX_EventError, + (OMX_U32)OMX_ErrorPortUnpopulated, + nPortIndex, NULL); + ret = OMX_ErrorInvalidState; + 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) { + if (pExynosPort->bufferStateAllocate[i] & BUFFER_STATE_ALLOCATED) { + if ((nPortIndex == OUTPUT_PORT_INDEX) && + (pExynosPort->bStoreMetaData == OMX_TRUE)) { + ret = Exynos_OSAL_FreeMetaDataBuffer(pVideoEnc->hSharedMemory, + pExynosComponent->codecType, + nPortIndex, + pOMXBufferHdr->pBuffer); + if (ret != OMX_ErrorNone) + goto EXIT; + } else { + if ((pExynosComponent->codecType == HW_VIDEO_ENC_SECURE_CODEC) && + (nPortIndex == OUTPUT_PORT_INDEX)) { + /* caution : data loss */ + int ionFD = PTR_TO_INT(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; + pBufferHdr = NULL; + } + + pExynosPort->bufferStateAllocate[i] = BUFFER_STATE_FREE; + ret = OMX_ErrorNone; + goto EXIT; + } + } + } + +EXIT: + if ((ret == OMX_ErrorNone) && + (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; +} + +#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; + + FunctionIn(); + + *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); + } + +EXIT: + FunctionOut(); + + 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) { + 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->messageType != 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 (pExynosComponent->bMultiThreadProcess == OMX_TRUE) { + if (pExynosPort->bufferProcessType & BUFFER_SHARE) { + if (pExynosPort->processData.bufferHeader != NULL) { + if (nPortIndex == INPUT_PORT_INDEX) { +#if defined(USE_METADATABUFFERTYPE) && defined(USE_ANDROIDOPAQUE) + if ((pExynosPort->bStoreMetaData == OMX_TRUE) && + (pExynosPort->portDefinition.format.video.eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque)) { + OMX_PTR ppBuf[MAX_BUFFER_PLANE]; + if (OMX_ErrorNone == + Exynos_OSAL_GetInfoFromMetaData((OMX_BYTE)pExynosPort->processData.bufferHeader->pBuffer, ppBuf)) + Exynos_OSAL_UnlockANBHandle(ppBuf[0]); + } +#endif + 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 defined(USE_METADATABUFFERTYPE) && defined(USE_ANDROIDOPAQUE) + if ((pExynosPort->bStoreMetaData == OMX_TRUE) && + (pExynosPort->portDefinition.format.video.eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque)) { + OMX_PTR ppBuf[MAX_BUFFER_PLANE]; + if (OMX_ErrorNone == + Exynos_OSAL_GetInfoFromMetaData((OMX_BYTE)pExynosPort->extendBufferHeader[i].OMXBufferHeader->pBuffer, ppBuf)) + Exynos_OSAL_UnlockANBHandle(ppBuf[0]); + } +#endif + Exynos_OMX_InputBufferReturn(pOMXComponent, + pExynosPort->extendBufferHeader[i].OMXBufferHeader); + } + } + } + } + } else { + Exynos_ResetCodecData(&pExynosPort->processData); + } + + 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}; + OMX_U32 i = 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; + + 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,"OMX_CommandFlush start, port:%d", nPortIndex); + + pExynosPort->bIsPortFlushed = OMX_TRUE; + + if (pExynosComponent->bMultiThreadProcess == OMX_FALSE) { + Exynos_OSAL_SignalSet(pExynosComponent->pauseEvent); + } else { + 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; + } + + pExynosPort->bIsPortFlushed = OMX_FALSE; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE,"OMX_CommandFlush EventCmdComplete, port:%d", nPortIndex); + if (bEvent == OMX_TRUE) + pExynosComponent->pCallbacks->EventHandler((OMX_HANDLETYPE)pOMXComponent, + pExynosComponent->callbackData, + OMX_EventCmdComplete, + OMX_CommandFlush, nPortIndex, NULL); + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_CountReset(pExynosPort->hBufferCount); +#endif + } + + if (pDataBuffer[1] != NULL) + Exynos_OSAL_MutexUnlock(pDataBuffer[1]->bufferMutex); + + Exynos_OSAL_MutexUnlock(pDataBuffer[0]->bufferMutex); + +EXIT: + if ((ret != OMX_ErrorNone) && (pOMXComponent != NULL) && (pExynosComponent != NULL)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR,"%s : %d", __FUNCTION__, __LINE__); + pExynosComponent->pCallbacks->EventHandler(pOMXComponent, + pExynosComponent->callbackData, + OMX_EventError, + ret, 0, NULL); + } + + 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) { + 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]); + + if (pDataBuffer != NULL) + 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) { + ret = OMX_ErrorUndefined; + goto EXIT; + } else if ((pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (!CHECK_PORT_BEING_FLUSHED(pExynosPort))) { + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + if (pDataBuffer->dataValid != OMX_TRUE) { + pMessage = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (pMessage == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + if (pMessage->messageType == EXYNOS_OMX_CommandFakeBuffer) { + Exynos_OSAL_Free(pMessage); + ret = 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, "Input Buffer Full, Check input buffer size! allocSize:%d, dataLen:%d", 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->bStoreMetaData == OMX_TRUE) && + (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, "event OMX_BUFFERFLAG_EOS!!!"); + 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) { + ret = OMX_ErrorUndefined; + goto EXIT; + } else if ((pExynosComponent->transientState != EXYNOS_OMX_TransStateExecutingToIdle) && + (!CHECK_PORT_BEING_FLUSHED(pExynosPort))) { + Exynos_OSAL_SemaphoreWait(pExynosPort->bufferSemID); + if (pDataBuffer->dataValid != OMX_TRUE) { + pMessage = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (pMessage == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + if (pMessage->messageType == EXYNOS_OMX_CommandFakeBuffer) { + Exynos_OSAL_Free(pMessage); + ret = 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_SemaphoreWait(pExynosPort->bufferSemID); + + pMessage = (EXYNOS_OMX_MESSAGE *)Exynos_OSAL_Dequeue(&pExynosPort->bufferQ); + if (pMessage == NULL) { + pBufferHdr = NULL; + goto EXIT; + } + if (pMessage->messageType == 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_SemaphoreWait(pExynosPort->codecSemID); + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + 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) + 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) + 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; + /* 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) + goto EXIT; + + pExynosPort = &pExynosComponent->pExynosPort[nPortIndex]; + Exynos_OSAL_Memcpy(((char *)pPortDef) + nOffset, + ((char *)&pExynosPort->portDefinition) + nOffset, + pPortDef->nSize - nOffset); + +#ifdef USE_STOREMETADATA + if (pExynosPort->bStoreMetaData == OMX_TRUE) + pPortDef->nBufferSize = MAX_METADATA_BUFFER_SIZE; +#endif + } + 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) + 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) + 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) + 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_GetAndroidParameter(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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + 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) + 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, "%s[%x] xFramerate is invalid(%d)", + __FUNCTION__, OMX_IndexParamVideoPortFormat, 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) + 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, "pExynosOutputPort->portDefinition.nBufferSize: %d", + pExynosPort->portDefinition.nBufferSize); + } + ret = OMX_ErrorNone; + } + break; +#ifdef USE_STOREMETADATA + case OMX_IndexParamStoreMetaDataBuffer: + { + ret = Exynos_OSAL_SetAndroidParameter(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) + 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) + 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) + 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) + 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; + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + 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) + goto EXIT; + + pBufferInfo->fd = Exynos_OSAL_SharedMemory_VirtToION(pVideoEnc->hSharedMemory, pBufferInfo->pVirAddr); + } + break; + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + if (pVideoEnc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + 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, "Rate control(eControlRate) is disable. can not change a bitrate"); + 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, "%s[%x] xFramerate is invalid(%d)", + __FUNCTION__, OMX_IndexConfigVideoFramerate, 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) + goto EXIT; + + xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + if (xFramerate == 0) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s : xFramerate is zero. can't calculate QosRatio", __FUNCTION__); + pVideoEnc->nQosRatio = 100; + } else { + pVideoEnc->nQosRatio = (OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + } + + pVideoEnc->bQosChanged = OMX_TRUE; + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] operating rate(%.1lf) / frame rate(%.1lf) / ratio(%d)", pExynosComponent, __FUNCTION__, + pConfigRate->nU32 / (double)65536, xFramerate / (double)65536, pVideoEnc->nQosRatio); + + ret = OMX_ErrorNone; + } + break; +#ifdef USE_QOS_CTRL + case OMX_IndexVendorSetQosRatio: /* MSRND */ + { + EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *pQosInfo = (EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion(pQosInfo, sizeof(EXYNOS_OMX_VIDEO_CONFIG_QOSINFO)); + if (ret != OMX_ErrorNone) + goto EXIT; + + pVideoEnc->nQosRatio = pQosInfo->nQosRatio; + pVideoEnc->bQosChanged = OMX_TRUE; + + ret = OMX_ErrorNone; + } + break; +#endif + 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) + 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, "[%s] Resolution(%d x %d) is smaller than target resolution", + __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, "[%s] Blur Filter is not enabled, it will be discard", __FUNCTION__); + } + + ret = (OMX_ERRORTYPE)OMX_ErrorNoneExpiration; + } + break; + 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) { + 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 ((szParamName == NULL) || (pIndexType == NULL)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_CONFIG_VIDEO_INTRAPERIOD) == 0) { + *pIndexType = 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_CONFIG_OPERATING_RATE) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexConfigOperatingRate; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_QOS_CTRL + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_CONFIG_SET_QOS_RATIO) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexVendorSetQosRatio; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + +#ifdef USE_STOREMETADATA + if (Exynos_OSAL_Strcmp(szParamName, EXYNOS_INDEX_PARAM_STORE_METADATA_BUFFER) == 0) { + *pIndexType = (OMX_INDEXTYPE)OMX_IndexParamStoreMetaDataBuffer; + ret = OMX_ErrorNone; + goto EXIT; + } +#endif + + 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; + } + + ret = Exynos_OMX_GetExtensionIndex(hComponent, szParamName, pIndexType); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_Shared_DataToBuffer(EXYNOS_OMX_DATA *pData, EXYNOS_OMX_DATABUFFER *pUseBuffer, OMX_BOOL bNeedUnlock) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + 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 defined(USE_METADATABUFFERTYPE) && defined(USE_ANDROIDOPAQUE) + if ((bNeedUnlock == OMX_TRUE) && (pUseBuffer->bufferHeader != NULL)) { + OMX_PTR ppBuf[MAX_BUFFER_PLANE]; + if (OMX_ErrorNone == + Exynos_OSAL_GetInfoFromMetaData((OMX_BYTE)pUseBuffer->bufferHeader->pBuffer, ppBuf)) + Exynos_OSAL_UnlockANBHandle(ppBuf[0]); + } +#endif + + return ret; +} diff --git a/component/video/enc/Exynos_OMX_VencControl.h b/component/video/enc/Exynos_OMX_VencControl.h new file mode 100644 index 0000000..b1e0a99 --- /dev/null +++ b/component/video/enc/Exynos_OMX_VencControl.h @@ -0,0 +1,110 @@ +/* + * + * 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) + * @version 2.0.0 + * @history + * 2012.02.20 : Create + */ + +#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_ERRORTYPE Exynos_Shared_DataToBuffer(EXYNOS_OMX_DATA *pData, EXYNOS_OMX_DATABUFFER *pUseBuffer, OMX_BOOL bNeedUnlock); +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); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/video/enc/NOTICE b/component/video/enc/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/enc/h264/Android.mk b/component/video/enc/h264/Android.mk new file mode 100644 index 0000000..59ab1be --- /dev/null +++ b/component/video/enc/h264/Android.mk @@ -0,0 +1,78 @@ +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_CFLAGS := + +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_CFLAGS += -DUSE_ANDROID +endif + +ifeq ($(BOARD_USE_METADATABUFFERTYPE), true) +LOCAL_CFLAGS += -DUSE_METADATABUFFERTYPE + +ifeq ($(BOARD_USE_ANDROIDOPAQUE), true) +LOCAL_CFLAGS += -DUSE_ANDROIDOPAQUE +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 ($(BOARD_USE_QOS_CTRL), true) +LOCAL_CFLAGS += -DUSE_QOS_CTRL +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Venc libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi + +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/include + +ifeq ($(BOARD_USE_SKYPE_HD), true) +LOCAL_CFLAGS += -DUSE_SKYPE_HD +LOCAL_CFLAGS += -DBUILD_ENC +LOCAL_C_INCLUDES += $(EXYNOS_OMX_INC)/skype +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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/enc/h264/Exynos_OMX_H264enc.c b/component/video/enc/h264/Exynos_OMX_H264enc.c new file mode 100644 index 0000000..9ff1e9d --- /dev/null +++ b/component/video/enc/h264/Exynos_OMX_H264enc.c @@ -0,0 +1,3508 @@ +/* + * + * 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 "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" + +#ifdef USE_ANDROID +#include "Exynos_OSAL_Android.h" +#endif + +#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; + + FunctionIn(); + + 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_100: + case MFC_101: + pH264Enc->hMFCH264Handle.maxLevel = OMX_VIDEO_AVCLevel52; + break; + case MFC_80: + case MFC_90: + case MFC_1010: + 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: + 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; + } + + while ((pH264Enc->hMFCH264Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pH264Enc->hMFCH264Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : there is no any profile/level", __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); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s : supported profile(%x), level(%x)", __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, "%s : there is no any profile/level", __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, "%s : profile(%x)/level(%x) is %ssupported", __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 ((EXYNOS_OMX_VIDEO_AVCPROFILETYPE)profile == OMX_VIDEO_AVCProfileConstrainedBaseline) + ret = 1; + else if (profile == OMX_VIDEO_AVCProfileMain) + ret = 2; + else if (profile == OMX_VIDEO_AVCProfileHigh) + ret = 4; + else if ((EXYNOS_OMX_VIDEO_AVCPROFILETYPE)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; + + 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_ESSENTIAL, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "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_ESSENTIAL, "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_ESSENTIAL, "LoopFilterDisable : %d", pH264Param->LoopFilterDisable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LoopFilterAlphaC0Offset : %d", pH264Param->LoopFilterAlphaC0Offset); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LoopFilterBetaOffset : %d", pH264Param->LoopFilterBetaOffset); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SymbolMode : %d", pH264Param->SymbolMode); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "PictureInterlace : %d", pH264Param->PictureInterlace); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Transform8x8Mode : %d", pH264Param->Transform8x8Mode); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DarkDisable : %d", pH264Param->DarkDisable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SmoothDisable : %d", pH264Param->SmoothDisable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "StaticDisable : %d", pH264Param->StaticDisable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "ActivityDisable : %d", pH264Param->ActivityDisable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "HierarType: : %d", pH264Param->HierarType); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "VuiRestrictionEnable: : %d", pH264Param->VuiRestrictionEnable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "HeaderWithIFrame: : %d", pH264Param->HeaderWithIFrame); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SarEnable: : %d", pH264Param->SarEnable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SarIndex: : %d", pH264Param->SarIndex); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SarWidth: : %d", pH264Param->SarWidth); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SarHeight: : %d", pH264Param->SarHeight); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LTREnable: : %d", pH264Param->LTREnable); + + /* 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 *pExynosInputPort = NULL; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = 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; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH264Param *pH264Param = NULL; + + int i; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pEncParam = &pMFCH264Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pH264Param = &pEncParam->codecParam.h264; + + pEncParam->eCompressionFormat = VIDEO_CODING_AVC; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "eCompressionFormat: %d", pEncParam->eCompressionFormat); + + /* common parameters */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + pCommonParam->SourceWidth = pExynosOutputPort->portDefinition.format.video.nFrameWidth; + pCommonParam->SourceHeight = pExynosOutputPort->portDefinition.format.video.nFrameHeight; + } else { + pCommonParam->SourceWidth = pExynosOutputPort->portDefinition.format.video.nFrameHeight; + pCommonParam->SourceHeight = pExynosOutputPort->portDefinition.format.video.nFrameWidth; + } + pCommonParam->IDRPeriod = pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].nPFrames + 1; + pCommonParam->SliceMode = pH264Enc->AVCSliceFmo.eSliceMode; + pCommonParam->Bitrate = pExynosOutputPort->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; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "RandomIntraMBRefresh: %d", pCommonParam->RandomIntraMBRefresh); + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pExynosInputPort->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 = (pExynosInputPort->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 */ + pH264Param->TemporalSVC.nTemporalLayerCount = (unsigned int)pH264Enc->TemporalSVC.nTemporalLayerCount; + for (i = 0; i < OMX_VIDEO_ANDROID_MAXAVCTEMPORALLAYERS; i++) + pH264Param->TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pH264Enc->TemporalSVC.nTemporalLayerBitrateRatio[i]; + + /* Hierarchal P & B */ + pH264Param->HierarType = pH264Enc->eHierarchicalType; + + /* SPS VUI */ + if (pH264Enc->stSarParam.SarEnable == OMX_TRUE) { + pH264Param->SarEnable = 1; + /* TBD */ + /*need value check*/ + pH264Param->SarIndex = pH264Enc->stSarParam.SarIndex; + pH264Param->SarWidth = pH264Enc->stSarParam.SarWidth; + pH264Param->SarHeight = pH264Enc->stSarParam.SarHeight; + + } else { + pH264Param->SarEnable = 0; + pH264Param->SarIndex = 0; + pH264Param->SarWidth = 0; + pH264Param->SarHeight = 0; + } + + 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; + } + + if (pMFCH264Handle->bLTREnable == OMX_TRUE) + pH264Param->LTREnable = 1; + else + pH264Param->LTREnable = 0; + + if (pMFCH264Handle->bRoiInfo == OMX_TRUE) + pH264Param->ROIEnable = 1; + else + pH264Param->ROIEnable = 0; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]: 0x%x", 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; + 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 void Change_H264Enc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + 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; + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_S32 nPFrames = (*((OMX_S32 *)pConfigData)) - 1; + nValue = nPFrames + 1; + pEncOps->Set_IDRPeriod(pH264Enc->hMFCH264Handle.hMFCHandle, nValue); + } + break; + case OMX_IndexConfigVideoAVCIntraPeriod: + { + OMX_VIDEO_CONFIG_AVCINTRAPERIOD *pAVCIntraPeriod = (OMX_VIDEO_CONFIG_AVCINTRAPERIOD *)pConfigData; + nValue = pAVCIntraPeriod->nIDRPeriod; + pEncOps->Set_IDRPeriod(pMFCH264Handle->hMFCHandle, 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); + } + } + 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); + } + } + 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); + } + break; + case OMX_IndexConfigOperatingRate: + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pConfigData; + OMX_U32 xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + + if (xFramerate == 0) + nValue = 100; + else + nValue = (OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + + pEncOps->Set_QosRatio(pMFCH264Handle->hMFCHandle, nValue); + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; +#ifdef USE_QOS_CTRL + case OMX_IndexVendorSetQosRatio: /* MSRND */ + { + EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *pQosInfo = (EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *)pConfigData; + nValue = pQosInfo->nQosRatio; + pEncOps->Set_QosRatio(pMFCH264Handle->hMFCHandle, nValue); + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; +#endif + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pConfigData; + ExynosVideoQPRange qpRange; + + 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); + + /* Temporal SVC */ + TemporalLayerShareBuffer TemporalSVC; + Exynos_OSAL_Memset(&TemporalSVC, 0, sizeof(TemporalLayerShareBuffer)); + TemporalSVC.nTemporalLayerCount = (unsigned int)pTemporalSVC->nTemporalLayerCount; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "nTemporalLayerCount : %d", TemporalSVC.nTemporalLayerCount); + for (i = 0; i < OMX_VIDEO_ANDROID_MAXAVCTEMPORALLAYERS; i++) { + TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pTemporalSVC->nTemporalLayerBitrateRatio[i]; + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "nTempBitrateRatio[%d] : %d", i, TemporalSVC.nTemporalLayerBitrateRatio[i]); + } + pEncOps->Set_LayerChange(pMFCH264Handle->hMFCHandle, TemporalSVC); + } + 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; + if (pEncOps->Set_RoiInfo != NULL) + pEncOps->Set_RoiInfo(pMFCH264Handle->hMFCHandle, &RoiInfo); + else + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: Not supported control: Set_RoiInfo", __func__); + } + break; + default: +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bSkypeSupport == VIDEO_TRUE) + Change_H264Enc_SkypeHDParam(pExynosComponent, pDynamicConfigCMD); +#endif + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nCmdIndex %x nValue %d ", pExynosComponent, __FUNCTION__, (int)nCmdIndex, nValue); + Exynos_OSAL_Free(pDynamicConfigCMD); + + Set_H264Enc_Param(pExynosComponent); + +EXIT: + return; +} + +#if 0 /* unused code */ +OMX_ERRORTYPE GetCodecInputPrivateData(OMX_PTR codecBuffer, OMX_PTR addr[], OMX_U32 size[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +OMX_ERRORTYPE GetCodecOutputPrivateData(OMX_PTR codecBuffer, OMX_PTR *pVirtAddr, OMX_U32 *dataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pCodecBuffer; + + if (codecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pCodecBuffer = (ExynosVideoBuffer *)codecBuffer; + + if (pVirtAddr != NULL) + *pVirtAddr = pCodecBuffer->planes[0].addr; + + if (dataSize != NULL) + *dataSize = pCodecBuffer->planes[0].allocSize; + + pCodecBuffer = (ExynosVideoBuffer *)codecBuffer; + +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_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate encoder ops buffer"); + 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); + + Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps); + + /* 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, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pH264Enc->hMFCH264Handle.hMFCHandle = pH264Enc->hMFCH264Handle.pEncOps->Init(pVideoInstInfo); + if (pH264Enc->hMFCH264Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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; + } + + /* 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; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + 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; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + 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; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + + 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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE H264CodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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; + CODEC_ENC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoEncBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoEnc->pMFCEncInputBuffer[0]); + pBufOps = pH264Enc->hMFCH264Handle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoEnc->pMFCEncOutputBuffer[0]); + pBufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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 *)((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + int i, nOutbufs; + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + + 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, "pVideoEnc->pMFCEncInputBuffer[%d]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncInputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncInputBuffer[%d]->pVirAddr[1]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[1]); + + 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, "pVideoEnc->pMFCEncOutputBuffer[%d]: 0x%x", i, pVideoEnc->pMFCEncOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoEnc->pMFCEncOutputBuffer[i]); + } + + pOutbufOps->Clear_Queue(hMFCHandle); + } + +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 *)((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = &pH264Enc->hMFCH264Handle; + void *hMFCHandle = pMFCH264Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + ExynosVideoEncParam *pEncParam = NULL; + + ExynosVideoGeometry bufferConf; + OMX_U32 inputBufferNumber = 0; + int i, nOutbufs; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] FBD with EOS will be processed through bypassBufferInfoQ", + 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); + Exynos_OSAL_SignalSet(pH264Enc->hDestinationStartEvent); /* awake dstInput thread */ + + 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, "Failed to set geometry for input buffer"); + 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, "%s: Not supported control: Enable_PrependSpsPpsToIdr", __func__); + } + + /* input buffer info: only 3 config values needed */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eColorFormat = pEncParam->commonParam.FrameMap; + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = pExynosInputPort->portDefinition.format.video.nFrameWidth; + bufferConf.nFrameHeight = pExynosInputPort->portDefinition.format.video.nFrameHeight; + bufferConf.nStride = ALIGN(pExynosInputPort->portDefinition.format.video.nFrameWidth, 16); + } else { + bufferConf.nFrameWidth = pExynosInputPort->portDefinition.format.video.nFrameHeight; + bufferConf.nFrameHeight = pExynosInputPort->portDefinition.format.video.nFrameWidth; + bufferConf.nStride = ALIGN(pExynosInputPort->portDefinition.format.video.nFrameHeight, 16); + } + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + pInbufOps->Set_Shareable(hMFCHandle); + inputBufferNumber = MAX_INPUTBUFFER_NUM_DYNAMIC; + + if (pExynosInputPort->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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, inputBufferNumber) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosInputPort->bufferProcessType & BUFFER_SHARE) +#ifdef USE_METADATABUFFERTYPE + && (pExynosInputPort->bStoreMetaData != OMX_TRUE) +#endif + ) { + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + 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, nOutbufs; + + FunctionIn(); + + int nOutBufSize = pExynosOutputPort->portDefinition.nBufferSize; + if (pExynosOutputPort->bStoreMetaData == OMX_TRUE) { + nOutBufSize = ALIGN(pExynosOutputPort->portDefinition.format.video.nFrameWidth * + pExynosOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + } + + /* 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(pExynosOutputPort); + + if (pOutbufOps->Set_Geometry(pH264Enc->hMFCH264Handle.hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for output buffer"); + 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); + int SetupBufferNumber = 0; + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) + SetupBufferNumber = MFC_OUTPUT_BUFFER_NUM_MAX; + else + SetupBufferNumber = pExynosOutputPort->portDefinition.nBufferCountActual; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SetupBufferNumber:%d", SetupBufferNumber); + + if (pOutbufOps->Setup(pH264Enc->hMFCH264Handle.hMFCHandle, SetupBufferNumber) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + nAllocLen[0] = nOutBufSize; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, MFC_OUTPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr, + (int *)pVideoEnc->pMFCEncOutputBuffer[i]->fd, + pVideoEnc->pMFCEncOutputBuffer[i]->bufferSize, + nDataLen, + Exynos_GetPlaneFromPort(pExynosOutputPort), + NULL); + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + /* Register output buffer */ + /*************/ + /* TBD */ + /*************/ + } + pH264Enc->hMFCH264Handle.bConfiguredMFCDst = OMX_TRUE; + + 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; + + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) { + 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) { + 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) { + goto EXIT; + } + + 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) { + 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) { + 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) { + 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) + 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) { + 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) { + goto EXIT; + } + + if (pDstEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstEnableRoiInfo->bEnableRoiInfo = pH264Enc->hMFCH264Handle.bRoiInfo; + } + break; + + default: +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bSkypeSupport == VIDEO_TRUE) + ret = Exynos_H264Enc_GetParameter_SkypeHD(hComponent, nParamIndex, pComponentParameterStructure); + else + ret = OMX_ErrorUnsupportedIndex; + + if (OMX_ErrorNone != ret) +#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; + + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) { + 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) { + 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) { + 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)) { + 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) + 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) { + 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) + 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; + case OMX_IndexParamPrependSPSPPSToIDR: + { +#ifdef USE_ANDROID + ret = Exynos_OSAL_SetPrependSPSPPSToIDR(pComponentParameterStructure, &(pH264Enc->hMFCH264Handle.bPrependSpsPpsToIdr)); +#else + ret = OMX_ErrorNotImplemented; +#endif + } + break; + 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) { + goto EXIT; + } + + if (pSrcEnableTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) && + (pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: MFC D/D doesn't support Temporal SVC", __func__); + 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_ANDROID_MAXAVCTEMPORALLAYERS; 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; + int i; + + ret = Exynos_OMX_Check_SizeVersion(pSrcEnableRoiInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bRoiInfoSupport == VIDEO_FALSE) && + (pSrcEnableRoiInfo->bEnableRoiInfo == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: MFC D/D doesn't support Roi Info", __func__); + 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) { + 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, "%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); + + if (pVideoEnc->bFirstInput == OMX_FALSE) + pVideoEnc->bEncDRC = OMX_TRUE; + + pVideoEnc->bFirstInput = OMX_TRUE; + pH264Enc->hMFCH264Handle.bConfiguredMFCSrc = OMX_FALSE; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pExynosOutputPort->portDefinition.nBufferSize: %d", pExynosPort->portDefinition.nBufferSize); + } else if (nPortIndex == OUTPUT_PORT_INDEX) { + pH264Enc->hMFCH264Handle.bConfiguredMFCDst = OMX_FALSE; + } + + ret = OMX_ErrorNone; + } + break; + + default: +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bSkypeSupport == VIDEO_TRUE) + ret = Exynos_H264Enc_SetParameter_SkypeHD(hComponent, nIndex, pComponentParameterStructure); + else + ret = OMX_ErrorUnsupportedIndex; + + if (OMX_ErrorNone != ret) +#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; + + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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) + 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; + default: +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bSkypeSupport == VIDEO_TRUE) + ret = Exynos_H264Enc_GetConfig_SkypeHD(hComponent, nIndex, pComponentConfigStructure); + else + ret = OMX_ErrorUnsupportedIndex; + + if (OMX_ErrorNone != ret) +#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; + + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoIntraPeriod: + { + EXYNOS_OMX_VIDEOENC_COMPONENT *pVEncBase = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle); + 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) + 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; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pDstTemporalSVC = &pH264Enc->TemporalSVC; + 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) + goto EXIT; + + if (pSrcTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.bTemporalSVC == OMX_FALSE) || + (pSrcTemporalSVC->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXAVCTEMPORALLAYERS)) { + 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); + } + 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) || + ((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; + } + } + break; + default: +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bSkypeSupport == VIDEO_TRUE) + ret = Exynos_H264Enc_SetConfig_SkypeHD(hComponent, nIndex, pComponentConfigStructure); + else + ret = OMX_ErrorUnsupportedIndex; + + if (OMX_ErrorNone != ret) +#endif + ret = Exynos_OMX_VideoEncodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + OMX_PTR pDynamicConfigCMD = NULL; + pDynamicConfigCMD = Exynos_OMX_MakeDynamicConfigCMD(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) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + if (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_PREPEND_SPSPPS_TO_IDR) == 0) { + *pIndexType = OMX_IndexParamPrependSPSPPSToIDR; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_TEMPORALSVC) == 0) { + *pIndexType = OMX_IndexConfigVideoTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_AVC_ENABLE_TEMPORALSVC) == 0) { + *pIndexType = OMX_IndexParamVideoAVCEnableTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_ROIINFO) == 0) { + *pIndexType = OMX_IndexConfigVideoRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_ENABLE_ROIINFO) == 0) { + *pIndexType = OMX_IndexParamVideoEnableRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + +#ifdef USE_SKYPE_HD + if (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bSkypeSupport == VIDEO_TRUE) + ret = Exynos_H264Enc_GetExtensionIndex_SkypeHD(hComponent, cParameterName, pIndexType); + else + ret = OMX_ErrorUnsupportedIndex; + + if (ret != OMX_ErrorNone) +#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)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (nIndex == (MAX_COMPONENT_ROLE_NUM-1)) { + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle;; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = &pH264Enc->hMFCH264Handle; + OMX_PTR hMFCHandle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + ExynosVideoInstInfo *pVideoInstInfo = &(pH264Enc->hMFCH264Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i = 0; + + FunctionIn(); + + pH264Enc->hMFCH264Handle.bConfiguredMFCSrc = OMX_FALSE; + pH264Enc->hMFCH264Handle.bConfiguredMFCDst = OMX_FALSE; + pVideoEnc->bFirstInput = OMX_TRUE; + pVideoEnc->bFirstOutput = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + eColorFormat = pExynosInputPort->portDefinition.format.video.eColorFormat; +#ifdef USE_METADATABUFFERTYPE + if (pExynosInputPort->bStoreMetaData == OMX_TRUE) { +#ifdef USE_ANDROIDOPAQUE + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) { + pExynosInputPort->bufferProcessType = BUFFER_COPY; + } else { + pExynosInputPort->bufferProcessType = BUFFER_SHARE; + } +#else + pExynosInputPort->bufferProcessType = BUFFER_SHARE; +#endif + } else { + pExynosInputPort->bufferProcessType = BUFFER_COPY; + } +#else + pExynosInputPort->bufferProcessType = BUFFER_COPY; +#endif + + 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(pH264Enc, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + Exynos_SetPlaneToPort(pExynosOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + + Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + 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. */ + } + + pH264Enc->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pH264Enc->hSourceStartEvent); + pH264Enc->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pH264Enc->hDestinationStartEvent); + + 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 = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle); + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + OMX_PTR hMFCHandle = pH264Enc->hMFCH264Handle.hMFCHandle; + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + + int i = 0, plane = 0; + + FunctionIn(); + + if (pVideoEnc->csc_handle != NULL) { + csc_deinit(pVideoEnc->csc_handle); + pVideoEnc->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pH264Enc->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pH264Enc->hDestinationStartEvent); + pH264Enc->hDestinationStartEvent = 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); + } 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); + + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + OMX_COLOR_FORMATTYPE inputColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pH264Enc->hMFCH264Handle.pOutbufOps; + 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; + + FunctionIn(); + + if (pH264Enc->hMFCH264Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = H264CodecSrcSetup(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + goto EXIT; + } + } + + if (pH264Enc->hMFCH264Handle.bConfiguredMFCDst == OMX_FALSE) { + ret = H264CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + } + + while (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + Change_H264Enc_Param(pExynosComponent); + } + + 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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pH264Enc->hMFCH264Handle.indexTimestamp, pSrcInputData->nFlags); + pEncOps->Set_FrameTag(hMFCHandle, pH264Enc->hMFCH264Handle.indexTimestamp); + pH264Enc->hMFCH264Handle.indexTimestamp++; + pH264Enc->hMFCH264Handle.indexTimestamp %= MAX_TIMESTAMP; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] oneFrameSize: %ld, bufferHeader: 0x%p", pExynosComponent, __FUNCTION__, oneFrameSize, pSrcInputData->bufferHeader); + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pExynosInputPort->ePlaneType, + pExynosInputPort->portDefinition.format.video.nFrameWidth, + pExynosInputPort->portDefinition.format.video.nFrameHeight, + nDataLen, + nAllocLen); + } else { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pExynosInputPort->ePlaneType, + pExynosInputPort->portDefinition.format.video.nFrameHeight, + pExynosInputPort->portDefinition.format.video.nFrameWidth, + nDataLen, + nAllocLen); + } + + if (pExynosInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + if (pVideoEnc->nInbufSpareSize > 0) { + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = nAllocLen[i] + pVideoEnc->nInbufSpareSize; + } + + if (pSrcInputData->dataLen == 0) { + for (i = 0; i < nPlaneCnt; i++) + nDataLen[i] = 0; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - pInbufOps->Enqueue", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pH264Enc->hDestinationStartEvent); + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pH264Enc->hMFCH264Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + else + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->pPrivate = NULL; + } else { + int plane = 0, nPlaneCnt; + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pSrcOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pSrcOutputData->multiPlaneBuffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pSrcOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->multiPlaneBuffer.dataBuffer[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, "%s: %d: Failed - Lost buffer", __FUNCTION__, __LINE__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pExynosInputPort->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 *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pH264Enc->hMFCH264Handle.pEncOps; + 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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + nAllocLen[0] = pExynosOutputPort->portDefinition.nBufferSize; + if (pExynosOutputPort->bStoreMetaData == OMX_TRUE) + nAllocLen[0] = ALIGN(pExynosOutputPort->portDefinition.format.video.nFrameWidth * pExynosOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosOutputPort), + pDstInputData->bufferHeader); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - pOutbufOps->Enqueue", __FUNCTION__, __LINE__); + 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 *pExynosOutputPort = &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; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + 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, "HW is not available"); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + pH264Enc->hMFCH264Handle.outputIndexTimestamp++; + pH264Enc->hMFCH264Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pDstOutputData->multiPlaneBuffer.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 (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->multiPlaneBuffer.dataBuffer[0] == + pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoEnc->pMFCEncOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + 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->multiPlaneBuffer.dataBuffer[0] + 4), + pDstOutputData->dataLen - 4); + + iSpsSize = PTR_TO_INT((p - (OMX_U8 *)pDstOutputData->multiPlaneBuffer.dataBuffer[0])); + pH264Enc->hMFCH264Handle.headerData.pHeaderSPS = + (OMX_PTR)pDstOutputData->multiPlaneBuffer.dataBuffer[0]; + pH264Enc->hMFCH264Handle.headerData.SPSLen = iSpsSize; + + iPpsSize = pDstOutputData->dataLen - iSpsSize; + pH264Enc->hMFCH264Handle.headerData.pHeaderPPS = + (OMX_U8 *)pDstOutputData->multiPlaneBuffer.dataBuffer[0] + iSpsSize; + pH264Enc->hMFCH264Handle.headerData.PPSLen = iPpsSize; + } + + 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); + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Tag(%d) is invalid. changes to use outputIndexTimestamp(%d)", + pExynosComponent, __FUNCTION__, + indexTimestamp, pH264Enc->hMFCH264Handle.outputIndexTimestamp); + indexTimestamp = pH264Enc->hMFCH264Handle.outputIndexTimestamp; + } + + 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; + } + } + } + + 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 timestamp %lld us (%.2f secs), Tag: %d, frameType: %d dataLen: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, indexTimestamp, + pVideoBuffer->frameType, pDstOutputData->dataLen); + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pExynosOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) && + (pExynosComponent->bBehaviorEOS == OMX_FALSE))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + } + + if (((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) && + (pExynosComponent->bBehaviorEOS == OMX_TRUE)) + 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_H264ENC_HANDLE *pH264Enc = (EXYNOS_H264ENC_HANDLE *)((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->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 (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_ERROR, "%s: %d: Failed - SrcIn -> event is thrown to client", __FUNCTION__, __LINE__); + 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 *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 ((pH264Enc->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosInputPort))) { + Exynos_OSAL_SignalWait(pH264Enc->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pH264Enc->hSourceStartEvent); + } + + ret = Exynos_H264Enc_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - SrcOut -> event is thrown to client", __FUNCTION__, __LINE__); + 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 *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 (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pH264Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pH264Enc->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pH264Enc->hDestinationStartEvent); + } + + if (Exynos_OSAL_GetElemNum(&pH264Enc->bypassBufferInfoQ) > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] buffer with EOS will be returned by bypassBufferInfoQ", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pH264Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + 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_ERROR, "%s: %d: Failed - DstIn -> event is thrown to client", __FUNCTION__, __LINE__); + 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 *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 (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pH264Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pH264Enc->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pH264Enc->hDestinationStartEvent); + } + + if (Exynos_OSAL_GetElemNum(&pH264Enc->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - DstOut -> event is thrown to client", __FUNCTION__, __LINE__); + 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, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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; + + 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; + } + + 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->hMFCH264Handle.bTemporalSVC = OMX_FALSE; + for (i = 0; i < OMX_VIDEO_ANDROID_MAXAVCTEMPORALLAYERS; 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; + + 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; + +#if 0 /* unused code */ + pVideoEnc->exynos_checkInputFrame = NULL; + pVideoEnc->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoEnc->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pVideoEnc->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoEnc->hSharedMemory == NULL) { + Exynos_OSAL_Free(pH264Enc); + pH264Enc = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->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]: Exynos_Video_GetInstInfo is failed", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pH264Enc); + pH264Enc = ((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 %d %d %d %d %d %d", pExynosComponent, __FUNCTION__, + (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bRGBSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.nSpareSize), + (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bTemporalSvcSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bSkypeSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bRoiInfoSupport), + (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.bQpRangePBSupport)); + + if (pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.nSpareSize > 0) + pVideoEnc->nInbufSpareSize = pH264Enc->hMFCH264Handle.videoInstInfo.specificInfo.enc.nSpareSize; + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + 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; + + 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; + } + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/enc/h264/Exynos_OMX_H264enc.h b/component/video/enc/h264/Exynos_OMX_H264enc.h new file mode 100644 index 0000000..4d207ff --- /dev/null +++ b/component/video/enc/h264/Exynos_OMX_H264enc.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_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" + +#ifdef USE_SKYPE_HD +#include "OMX_Video_Extensions.h" +#endif + +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 bLTREnable; + 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; + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC TemporalSVC; /* Temporal SVC */ + + /* SEC MFC Codec specific */ + EXYNOS_MFC_H264ENC_HANDLE hMFCH264Handle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationStartEvent; + + EXYNOS_QUEUE bypassBufferInfoQ; + + OMX_BOOL bLowLatency; + EXYNOS_OMX_HIERARCHICAL_CODING_TYPE eHierarchicalType; +#ifdef USE_SKYPE_HD + OMX_VIDEO_ENCODERPARAMS stEncParam; +#endif + H264_VUI_SAR stSarParam; + OMX_S32 nBaseLayerPid; +} 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/component/video/enc/h264/NOTICE b/component/video/enc/h264/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/enc/h264/library_register.c b/component/video/enc/h264/library_register.c new file mode 100644 index 0000000..ad65ae0 --- /dev/null +++ b/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_ENC_ROLE); + exynosComponents[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} + diff --git a/component/video/enc/h264/library_register.h b/component/video/enc/h264/library_register.h new file mode 100644 index 0000000..0e8d723 --- /dev/null +++ b/component/video/enc/h264/library_register.h @@ -0,0 +1,56 @@ +/* + * + * 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" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/component/video/enc/hevc/Android.mk b/component/video/enc/hevc/Android.mk new file mode 100644 index 0000000..a3b8c9f --- /dev/null +++ b/component/video/enc/hevc/Android.mk @@ -0,0 +1,72 @@ +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_CFLAGS := +LOCAL_CFLAGS += -DUSE_HEVC_SUPPORT + +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_CFLAGS += -DUSE_ANDROID +endif + +ifeq ($(BOARD_USE_METADATABUFFERTYPE), true) +LOCAL_CFLAGS += -DUSE_METADATABUFFERTYPE + +ifeq ($(BOARD_USE_ANDROIDOPAQUE), true) +LOCAL_CFLAGS += -DUSE_ANDROIDOPAQUE +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 ($(BOARD_USE_QOS_CTRL), true) +LOCAL_CFLAGS += -DUSE_QOS_CTRL +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Venc libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi + +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/enc/hevc/Exynos_OMX_HEVCenc.c b/component/video/enc/hevc/Exynos_OMX_HEVCenc.c new file mode 100644 index 0000000..da01fdc --- /dev/null +++ b/component/video/enc/hevc/Exynos_OMX_HEVCenc.c @@ -0,0 +1,3257 @@ +/* + * + * 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 "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" + +#ifdef USE_ANDROID +#include "Exynos_OSAL_Android.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_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; + + FunctionIn(); + + 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_100: + case MFC_101: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel51; + break; + case MFC_90: + case MFC_1010: + pHevcEnc->hMFCHevcHandle.maxLevel = OMX_VIDEO_HEVCHighTierLevel5; + break; + case MFC_1011: + case MFC_1020: + 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; + } + + while ((pHevcEnc->hMFCHevcHandle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pHevcEnc->hMFCHevcHandle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : there is no any profile/level", __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); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s : supported profile(%x), level(%x)", __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, "%s : there is no any profile/level", __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, "%s : profile(%x)/level(%x) is %ssupported", __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; + 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: + 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: + 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; + 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_ESSENTIAL, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "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_ESSENTIAL, "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_ESSENTIAL, "LoopFilterDisable : %d", pHEVCParam->LoopFilterDisable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LoopFilterSliceFlag : %d", pHEVCParam->LoopFilterSliceFlag); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LoopFilterTcOffset : %d", pHEVCParam->LoopFilterTcOffset); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LoopFilterBetaOffset : %d", pHEVCParam->LoopFilterBetaOffset); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LongtermRefEnable : %d", pHEVCParam->LongtermRefEnable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LongtermUserRef : %d", pHEVCParam->LongtermUserRef); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LongtermStoreRef : %d", pHEVCParam->LongtermStoreRef); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "DarkDisable : %d", pHEVCParam->DarkDisable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SmoothDisable : %d", pHEVCParam->SmoothDisable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "StaticDisable : %d", pHEVCParam->StaticDisable); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "ActivityDisable : %d", pHEVCParam->ActivityDisable); + + /* 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; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncHevcParam *pHEVCParam = NULL; + + 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; + pCommonParam = &pEncParam->commonParam; + pHEVCParam = &pEncParam->codecParam.hevc; + + pEncParam->eCompressionFormat = VIDEO_CODING_HEVC; + 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 = pHevcEnc->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 = 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; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "RandomIntraMBRefresh: %d", pCommonParam->RandomIntraMBRefresh); + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + + 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 */ + pHEVCParam->TemporalSVC.nTemporalLayerCount = (unsigned int)pHevcEnc->TemporalSVC.nTemporalLayerCount; + for (i = 0; i < OMX_VIDEO_ANDROID_MAXHEVCTEMPORALLAYERS; i++) + pHEVCParam->TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pHevcEnc->TemporalSVC.nTemporalLayerBitrateRatio[i]; + + if (pMFCHevcHandle->bRoiInfo == OMX_TRUE) + pHEVCParam->ROIEnable = 1; + else + pHEVCParam->ROIEnable = 0; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]: 0x%x", 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_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; + + 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; + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_S32 nPFrames = (*((OMX_U32 *)pConfigData)) - 1; + nValue = nPFrames + 1; + pEncOps->Set_IDRPeriod(pMFCHevcHandle->hMFCHandle, 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); + } + } + 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); + } + } + 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); + } + break; + case OMX_IndexConfigOperatingRate: + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pConfigData; + OMX_U32 xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + + if (xFramerate == 0) + nValue = 100; + else + nValue = (OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + + pEncOps->Set_QosRatio(pMFCHevcHandle->hMFCHandle, nValue); + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; +#ifdef USE_QOS_CTRL + case OMX_IndexVendorSetQosRatio: /* MSRND */ + { + EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *pQosInfo = (EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *)pConfigData; + nValue = pQosInfo->nQosRatio; + pEncOps->Set_QosRatio(pMFCHevcHandle->hMFCHandle, nValue); + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; +#endif + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pTemporalSVC = (EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *)pConfigData; + ExynosVideoQPRange qpRange; + int i; + + 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); + + /* Temporal SVC */ + TemporalLayerShareBuffer TemporalSVC; + Exynos_OSAL_Memset(&TemporalSVC, 0, sizeof(TemporalLayerShareBuffer)); + TemporalSVC.nTemporalLayerCount = (unsigned int)pTemporalSVC->nTemporalLayerCount; + for (i = 0; i < OMX_VIDEO_ANDROID_MAXHEVCTEMPORALLAYERS; i++) + TemporalSVC.nTemporalLayerBitrateRatio[i] = (unsigned int)pTemporalSVC->nTemporalLayerBitrateRatio[i]; + + if (pEncOps->Set_LayerChange(pMFCHevcHandle->hMFCHandle, TemporalSVC) != VIDEO_ERROR_NONE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: Not supported control: Set_LayerChange", __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; + if (pEncOps->Set_RoiInfo != NULL) + pEncOps->Set_RoiInfo(pMFCHevcHandle->hMFCHandle, &RoiInfo); + else + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: Not supported control: Set_RoiInfo", __func__); + } + break; + default: + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nCmdIndex %x nValue %d ", pExynosComponent, __FUNCTION__, (int)nCmdIndex, nValue); + Exynos_OSAL_Free(pDynamicConfigCMD); + + Set_HEVCEnc_Param(pExynosComponent); + +EXIT: + return; +} + +#if 0 /* unused code */ +OMX_ERRORTYPE GetCodecInputPrivateData( + OMX_PTR pCodecBuffer, + OMX_PTR pVirtAddr[], + OMX_U32 nSize[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +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_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate encoder ops buffer"); + 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); + + Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps); + + /* 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, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pHevcEnc->hMFCHevcHandle.hMFCHandle = pHevcEnc->hMFCHevcHandle.pEncOps->Init(pVideoInstInfo); + if (pHevcEnc->hMFCHevcHandle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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; + } + + /* 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; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + void *hMFCHandle = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_HEVCENC_HANDLE *pHevcEnc = NULL; + + FunctionIn(); + + if (pOMXComponent == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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) { + 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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE HEVCCodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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; + CODEC_ENC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoEncBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoEnc->pMFCEncInputBuffer[0]); + pBufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoEnc->pMFCEncOutputBuffer[0]); + pBufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + int i, nOutbufs; + + ExynosVideoEncOps *pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + + 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, "pVideoEnc->pMFCEncInputBuffer[%d]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncInputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncInputBuffer[%d]->pVirAddr[1]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[1]); + + 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, "pVideoEnc->pMFCEncOutputBuffer[%d]: 0x%x", i, pVideoEnc->pMFCEncOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoEnc->pMFCEncOutputBuffer[i]); + } + + pOutbufOps->Clear_Queue(hMFCHandle); + } + +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]; + + ExynosVideoEncOps *pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + ExynosVideoEncParam *pEncParam = NULL; + + ExynosVideoGeometry bufferConf; + OMX_U32 nInputBufferCnt = 0; + int i, nOutbufs; + + FunctionIn(); + + if ((pSrcInputData->dataLen <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] FBD with EOS will be processed through bypassBufferInfoQ", + 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); + Exynos_OSAL_SignalSet(pHevcEnc->hDestinationStartEvent); /* awake dstInput thread */ + + 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + Print_HEVCEnc_Param(pEncParam); + + if ((pMFCHevcHandle->bPrependSpsPpsToIdr == OMX_TRUE) && + (pEncOps->Enable_PrependSpsPpsToIdr)) { + if (pEncOps->Enable_PrependSpsPpsToIdr(pHevcEnc->hMFCHevcHandle.hMFCHandle) != VIDEO_ERROR_NONE) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: Not supported control: Enable_PrependSpsPpsToIdr", __func__); + } + + /* input buffer info: only 3 config values needed */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eColorFormat = pEncParam->commonParam.FrameMap; + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = pInputPort->portDefinition.format.video.nFrameWidth; + bufferConf.nFrameHeight = pInputPort->portDefinition.format.video.nFrameHeight; + bufferConf.nStride = ALIGN(pInputPort->portDefinition.format.video.nFrameWidth, 16); + } else { + bufferConf.nFrameWidth = pInputPort->portDefinition.format.video.nFrameHeight; + bufferConf.nFrameHeight = pInputPort->portDefinition.format.video.nFrameWidth; + bufferConf.nStride = ALIGN(pInputPort->portDefinition.format.video.nFrameHeight, 16); + } + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + pInbufOps->Set_Shareable(hMFCHandle); + nInputBufferCnt = 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInputBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pInputPort->bufferProcessType & BUFFER_SHARE) +#ifdef USE_METADATABUFFERTYPE + && (pInputPort->bStoreMetaData != OMX_TRUE) +#endif + ) { + 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 *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + 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->bStoreMetaData == OMX_TRUE) { + nOutBufSize = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * + pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + } + + /* set geometry for output (dst) */ + if (pOutbufOps->Set_Geometry) { + /* 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, "Failed to set geometry for output buffer"); + 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, "Failed to setup output buffer"); + 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) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr, + (int *)pVideoEnc->pMFCEncOutputBuffer[i]->fd, + pVideoEnc->pMFCEncOutputBuffer[i]->bufferSize, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + NULL); + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /* Register output buffer */ + /*************/ + /* TBD */ + /*************/ + } + + pHevcEnc->hMFCHevcHandle.bConfiguredMFCDst = OMX_TRUE; + + 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; + + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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) + goto EXIT; + + 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) + 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) + 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) + 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) + 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) + 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) { + goto EXIT; + } + + if (pDstEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDstEnableRoiInfo->bEnableRoiInfo = pHevcEnc->hMFCHevcHandle.bRoiInfo; + } + break; + 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; + + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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) + 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)) { + 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) + 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) + 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) + 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; + case OMX_IndexParamPrependSPSPPSToIDR: + { +#ifdef USE_ANDROID + ret = Exynos_OSAL_SetPrependSPSPPSToIDR(pComponentParameterStructure, &(pHevcEnc->hMFCHevcHandle.bPrependSpsPpsToIdr)); +#else + ret = OMX_ErrorNotImplemented; +#endif + } + break; + 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) + goto EXIT; + + if (pSrcEnableTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.videoInstInfo.specificInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) && + (pSrcEnableTemporalSVC->bEnableTemporalSVC == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: MFC D/D doesn't support Temporal SVC", __func__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.bTemporalSVC = pSrcEnableTemporalSVC->bEnableTemporalSVC; + if ((pHevcEnc->hMFCHevcHandle.bTemporalSVC == OMX_TRUE) && + (pHevcEnc->TemporalSVC.nTemporalLayerCount == 0)) { /* not initialized yet */ + pHevcEnc->TemporalSVC.nTemporalLayerCount = 1; + pHevcEnc->TemporalSVC.nTemporalLayerBitrateRatio[0] = pPortDef->format.video.nBitrate; + } else if (pHevcEnc->hMFCHevcHandle.bTemporalSVC == OMX_FALSE) { /* set default value */ + pHevcEnc->TemporalSVC.nTemporalLayerCount = 0; + for (i = 0; i < OMX_VIDEO_ANDROID_MAXHEVCTEMPORALLAYERS; i++) + pHevcEnc->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; + OMX_PARAM_PORTDEFINITIONTYPE *pPortDef = &(pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition); + int i; + + ret = Exynos_OMX_Check_SizeVersion(pSrcEnableRoiInfo, sizeof(EXYNOS_OMX_VIDEO_PARAM_ENABLE_ROIINFO)); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + if (pSrcEnableRoiInfo->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.videoInstInfo.specificInfo.enc.bRoiInfoSupport == VIDEO_FALSE) && + (pSrcEnableRoiInfo->bEnableRoiInfo == OMX_TRUE)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: MFC D/D doesn't support Roi Info", __func__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + pHevcEnc->hMFCHevcHandle.bRoiInfo = pSrcEnableRoiInfo->bEnableRoiInfo; + } + 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; + + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + 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) + 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; + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pSrcTemporalSVC = &pHevcEnc->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) + goto EXIT; + + if (pDstTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pSrcTemporalSVC->nKeyFrameInterval = pHevcEnc->nPFrames + 1; + + pSrcTemporalSVC->nMinQuantizer = pHevcEnc->qpRangeI.nMinQP; + pSrcTemporalSVC->nMaxQuantizer = pHevcEnc->qpRangeI.nMaxQP; + + Exynos_OSAL_Memcpy(((char *)pDstTemporalSVC) + nOffset, + ((char *)pSrcTemporalSVC) + nOffset, + sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC) - nOffset); + } + break; + 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; + + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pHevcEnc = (EXYNOS_HEVCENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] nIndex %x", pExynosComponent, __FUNCTION__, (int)nIndex); + switch ((int)nIndex) { + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_U32 nPFrames = (*((OMX_U32 *)pComponentConfigStructure)) - 1; + + pHevcEnc->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) + 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; + case OMX_IndexConfigVideoTemporalSVC: + { + EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC *pDstTemporalSVC = &pHevcEnc->TemporalSVC; + 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) + goto EXIT; + + if (pSrcTemporalSVC->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pHevcEnc->hMFCHevcHandle.bTemporalSVC == OMX_FALSE) || + (pSrcTemporalSVC->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXHEVCTEMPORALLAYERS)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pHevcEnc->nPFrames = pSrcTemporalSVC->nKeyFrameInterval - 1; + + pHevcEnc->qpRangeI.nMinQP = pSrcTemporalSVC->nMinQuantizer; + pHevcEnc->qpRangeI.nMaxQP = pSrcTemporalSVC->nMaxQuantizer; + + Exynos_OSAL_Memcpy(((char *)pDstTemporalSVC) + nOffset, + ((char *)pSrcTemporalSVC) + nOffset, + sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC) - nOffset); + } + 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) || + ((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; + } + } + break; + default: + ret = Exynos_OMX_VideoEncodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + OMX_PTR pDynamicConfigCMD = NULL; + pDynamicConfigCMD = Exynos_OMX_MakeDynamicConfigCMD(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; + + 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; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_PREPEND_SPSPPS_TO_IDR) == 0) { + *pIndexType = OMX_IndexParamPrependSPSPPSToIDR; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_TEMPORALSVC) == 0) { + *pIndexType = OMX_IndexConfigVideoTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_HEVC_ENABLE_TEMPORALSVC) == 0) { + *pIndexType = OMX_IndexParamVideoHevcEnableTemporalSVC; + ret = OMX_ErrorNone; + goto EXIT; + } + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_CONFIG_VIDEO_ROIINFO) == 0) { + *pIndexType = OMX_IndexConfigVideoRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + if (Exynos_OSAL_Strcmp(cParameterName, EXYNOS_INDEX_PARAM_VIDEO_ENABLE_ROIINFO) == 0) { + *pIndexType = OMX_IndexParamVideoEnableRoiInfo; + ret = OMX_ErrorNone; + goto EXIT; + } + + 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; + + 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_ENC_ROLE); + ret = OMX_ErrorNone; + } else { + ret = OMX_ErrorNoMore; + } + +EXIT: + FunctionOut(); + + return ret; +} + +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_PTR hMFCHandle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + ExynosVideoInstInfo *pVideoInstInfo = &(pHevcEnc->hMFCHevcHandle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + + int i = 0, nPlaneCnt; + + FunctionIn(); + + pHevcEnc->hMFCHevcHandle.bConfiguredMFCSrc = OMX_FALSE; + pHevcEnc->hMFCHevcHandle.bConfiguredMFCDst = OMX_FALSE; + pVideoEnc->bFirstInput = OMX_TRUE; + pVideoEnc->bFirstOutput = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; +#ifdef USE_METADATABUFFERTYPE + if (pInputPort->bStoreMetaData == OMX_TRUE) { +#ifdef USE_ANDROIDOPAQUE + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) + pInputPort->bufferProcessType = BUFFER_COPY; + else + pInputPort->bufferProcessType = BUFFER_SHARE; +#else + pInputPort->bufferProcessType = BUFFER_COPY; +#endif + } else { + pInputPort->bufferProcessType = BUFFER_COPY; + } +#else + pInputPort->bufferProcessType = BUFFER_COPY; +#endif + + 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; + + pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + pInbufOps = pHevcEnc->hMFCHevcHandle.pInbufOps; + pOutbufOps = pHevcEnc->hMFCHevcHandle.pOutbufOps; + hMFCHandle = pHevcEnc->hMFCHevcHandle.hMFCHandle; + + 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->hDestinationStartEvent); + + 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 = (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; + + int i = 0, plane = 0; + + FunctionIn(); + + if (pVideoEnc->csc_handle != NULL) { + csc_deinit(pVideoEnc->csc_handle); + pVideoEnc->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pHevcEnc->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pHevcEnc->hDestinationStartEvent); + pHevcEnc->hDestinationStartEvent = NULL; + pHevcEnc->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalTerminate(pHevcEnc->hSourceStartEvent); + pHevcEnc->hSourceStartEvent = NULL; + pHevcEnc->bSourceStart = OMX_FALSE; + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pOutputPort->codecSemID); + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + } else if (pInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_OSAL_QueueTerminate(&pInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pInputPort->codecSemID); + + 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]; + 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; + + FunctionIn(); + + if (pHevcEnc->hMFCHevcHandle.bConfiguredMFCSrc == OMX_FALSE) { + ret = HEVCCodecSrcSetup(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + goto EXIT; + } + } + + if (pHevcEnc->hMFCHevcHandle.bConfiguredMFCDst == OMX_FALSE) { + ret = HEVCCodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + } + + while (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + Change_HEVCEnc_Param(pExynosComponent); + } + + 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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pHevcEnc->hMFCHevcHandle.indexTimestamp, pSrcInputData->nFlags); + + pEncOps->Set_FrameTag(hMFCHandle, pHevcEnc->hMFCHevcHandle.indexTimestamp); + pHevcEnc->hMFCHevcHandle.indexTimestamp++; + pHevcEnc->hMFCHevcHandle.indexTimestamp %= MAX_TIMESTAMP; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] oneFrameSize: %ld, bufferHeader: 0x%p", pExynosComponent, __FUNCTION__, pSrcInputData->dataLen, pSrcInputData->bufferHeader); + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + pInputPort->portDefinition.format.video.nFrameWidth, + pInputPort->portDefinition.format.video.nFrameHeight, + nDataLen, + nAllocLen); + } else { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + pInputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.format.video.nFrameWidth, + 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 (pVideoEnc->nInbufSpareSize> 0) { + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = nAllocLen[i] + pVideoEnc->nInbufSpareSize; + } + + if (pSrcInputData->dataLen == 0) { + for (i = 0; i < nPlaneCnt; i++) + nDataLen[i] = 0; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - pInbufOps->Enqueue", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pHevcEnc->hDestinationStartEvent); + 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 + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->pPrivate = NULL; + } else { + int plane = 0, nPlaneCnt; + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pSrcOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pSrcOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[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, "%s: %d: Failed - Lost buffer", __FUNCTION__, __LINE__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#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]; + + ExynosVideoEncOps *pEncOps = pHevcEnc->hMFCHevcHandle.pEncOps; + 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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + 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->bStoreMetaData == OMX_TRUE) + nAllocLen[0] = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + pDstInputData->bufferHeader); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - pOutbufOps->Enqueue", __FUNCTION__, __LINE__); + 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; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + 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, "HW is not available"); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + pHevcEnc->hMFCHevcHandle.outputIndexTimestamp++; + pHevcEnc->hMFCHevcHandle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pDstOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[0] == + pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoEnc->pMFCEncOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + if (pVideoEnc->bFirstOutput == OMX_FALSE) { + 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); + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Tag(%d) is invalid. changes to use outputIndexTimestamp(%d)", + pExynosComponent, __FUNCTION__, + indexTimestamp, pHevcEnc->hMFCHevcHandle.outputIndexTimestamp); + indexTimestamp = pHevcEnc->hMFCHevcHandle.outputIndexTimestamp; + } + + 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 timestamp %lld us (%.2f secs), Tag: %d, frameType: %d dataLen: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, + indexTimestamp, pVideoBuffer->frameType, pDstOutputData->dataLen); + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) && + (pExynosComponent->bBehaviorEOS == OMX_FALSE))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + } + + if (((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) && + (pExynosComponent->bBehaviorEOS == OMX_TRUE)) + 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_ERROR, "%s: %d: Failed - SrcIn -> event is thrown to client", __FUNCTION__, __LINE__); + 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_SignalReset(pHevcEnc->hSourceStartEvent); + } + + ret = Exynos_HEVCEnc_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - SrcOut -> event is thrown to client", __FUNCTION__, __LINE__); + 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 (pOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pHevcEnc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pHevcEnc->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pHevcEnc->hDestinationStartEvent); + } + + if (Exynos_OSAL_GetElemNum(&pHevcEnc->bypassBufferInfoQ) > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] buffer with EOS will be returned by bypassBufferInfoQ", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pHevcEnc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + 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_ERROR, "%s: %d: Failed - DstIn -> event is thrown to client", __FUNCTION__, __LINE__); + 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 (pOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pHevcEnc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pHevcEnc->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pHevcEnc->hDestinationStartEvent); + } + + if (Exynos_OSAL_GetElemNum(&pHevcEnc->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - DstOut -> event is thrown to client", __FUNCTION__, __LINE__); + 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, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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; + + 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; + 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; + 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->nPFrames = 29; + + Exynos_OSAL_Memset(&pHevcEnc->TemporalSVC, 0, sizeof(EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC)); + INIT_SET_SIZE_VERSION(&pHevcEnc->TemporalSVC, EXYNOS_OMX_VIDEO_CONFIG_TEMPORALSVC); + pHevcEnc->TemporalSVC.nKeyFrameInterval = pHevcEnc->nPFrames + 1; + pHevcEnc->TemporalSVC.nTemporalLayerCount = 0; + pHevcEnc->hMFCHevcHandle.bTemporalSVC = OMX_FALSE; + for (i = 0; i < OMX_VIDEO_ANDROID_MAXHEVCTEMPORALLAYERS; i++) { + pHevcEnc->TemporalSVC.nTemporalLayerBitrateRatio[i] = + pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].portDefinition.format.video.nBitrate; + } + pHevcEnc->TemporalSVC.nMinQuantizer = pHevcEnc->qpRangeI.nMinQP; + pHevcEnc->TemporalSVC.nMaxQuantizer = pHevcEnc->qpRangeI.nMaxQP; + + 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; + +#if 0 /* unused code */ + pVideoEnc->exynos_checkInputFrame = NULL; + pVideoEnc->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoEnc->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pVideoEnc->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoEnc->hSharedMemory == NULL) { + Exynos_OSAL_Free(pHevcEnc); + pHevcEnc = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->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; + + if (Exynos_Video_GetInstInfo(&(pHevcEnc->hMFCHevcHandle.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(pHevcEnc); + pHevcEnc = ((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 %d %d %d %d %d %d", pExynosComponent, __FUNCTION__, + (pHevcEnc->hMFCHevcHandle.videoInstInfo.specificInfo.enc.bRGBSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.specificInfo.enc.nSpareSize), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.specificInfo.enc.bTemporalSvcSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.specificInfo.enc.bSkypeSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.specificInfo.enc.bRoiInfoSupport), + (pHevcEnc->hMFCHevcHandle.videoInstInfo.specificInfo.enc.bQpRangePBSupport)); + + if (pHevcEnc->hMFCHevcHandle.videoInstInfo.specificInfo.enc.nSpareSize > 0) + pVideoEnc->nInbufSpareSize = pHevcEnc->hMFCHevcHandle.videoInstInfo.specificInfo.enc.nSpareSize; + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + 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; + + 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; + } + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/enc/hevc/Exynos_OMX_HEVCenc.h b/component/video/enc/hevc/Exynos_OMX_HEVCenc.h new file mode 100644 index 0000000..e0bd210 --- /dev/null +++ b/component/video/enc/hevc/Exynos_OMX_HEVCenc.h @@ -0,0 +1,94 @@ +/* + * + * 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; + + ExynosVideoEncOps *pEncOps; + ExynosVideoEncBufferOps *pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps; + ExynosVideoEncParam encParam; + ExynosVideoInstInfo videoInstInfo; + + #define MAX_PROFILE_NUM 1 + 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_U32 nPFrames; /* IDR period control */ + 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_HEVCENC_HANDLE hMFCHevcHandle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationStartEvent; + + 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/component/video/enc/hevc/NOTICE b/component/video/enc/hevc/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/enc/hevc/library_register.c b/component/video/enc/hevc/library_register.c new file mode 100644 index 0000000..d4e366b --- /dev/null +++ b/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_ENC_ROLE); + exynosComponents[1]->totalRoleNum = MAX_COMPONENT_ROLE_NUM; + +EXIT: + FunctionOut(); + + return MAX_COMPONENT_NUM; +} + diff --git a/component/video/enc/hevc/library_register.h b/component/video/enc/hevc/library_register.h new file mode 100644 index 0000000..7cc9814 --- /dev/null +++ b/component/video/enc/hevc/library_register.h @@ -0,0 +1,57 @@ +/* + * + * 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" + + +#ifdef __cplusplus +extern "C" { +#endif + +OSCL_EXPORT_REF int Exynos_OMX_COMPONENT_Library_Register(ExynosRegisterComponentType **exynosComponents); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/component/video/enc/mpeg4/Android.mk b/component/video/enc/mpeg4/Android.mk new file mode 100644 index 0000000..95a8622 --- /dev/null +++ b/component/video/enc/mpeg4/Android.mk @@ -0,0 +1,66 @@ +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_CFLAGS := + +ifeq ($(BOARD_USE_METADATABUFFERTYPE), true) +LOCAL_CFLAGS += -DUSE_METADATABUFFERTYPE + +ifeq ($(BOARD_USE_ANDROIDOPAQUE), true) +LOCAL_CFLAGS += -DUSE_ANDROIDOPAQUE +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 ($(BOARD_USE_QOS_CTRL), true) +LOCAL_CFLAGS += -DUSE_QOS_CTRL +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Venc libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.c b/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.c new file mode 100644 index 0000000..f62c38d --- /dev/null +++ b/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.c @@ -0,0 +1,3145 @@ +/* + * + * 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" + +/* 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; + + FunctionIn(); + + 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; + } + + while ((pMpeg4Enc->hMFCMpeg4Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pMpeg4Enc->hMFCMpeg4Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : there is no any profile/level", __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); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s : supported profile(%x), level(%x)", __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, "%s : there is no any profile/level", __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, "%s : profile(%x)/level(%x) is %ssupported", __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_ESSENTIAL, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + + /* 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_ESSENTIAL, "TimeIncreamentRes : %d", pMpeg4Param->TimeIncreamentRes); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "VopTimeIncreament : %d", pMpeg4Param->VopTimeIncreament); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "SliceArgument : %d", pMpeg4Param->SliceArgument); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "NumberBFrames : %d", pMpeg4Param->NumberBFrames); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "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_ESSENTIAL, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + + /* 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 *pExynosInputPort = NULL; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = 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; + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + pMFCMpeg4Handle = &pMpeg4Enc->hMFCMpeg4Handle; + pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + pEncParam = &pMFCMpeg4Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pMpeg4Param = &pEncParam->codecParam.mpeg4; + pEncParam->eCompressionFormat = VIDEO_CODING_MPEG4; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "eCompressionFormat: %d", pEncParam->eCompressionFormat); + + /* common parameters */ + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + pCommonParam->SourceWidth = pExynosOutputPort->portDefinition.format.video.nFrameWidth; + pCommonParam->SourceHeight = pExynosOutputPort->portDefinition.format.video.nFrameHeight; + } else { + pCommonParam->SourceWidth = pExynosOutputPort->portDefinition.format.video.nFrameHeight; + pCommonParam->SourceHeight = pExynosOutputPort->portDefinition.format.video.nFrameWidth; + } + pCommonParam->IDRPeriod = pMpeg4Enc->mpeg4Component[OUTPUT_PORT_INDEX].nPFrames + 1; + pCommonParam->SliceMode = 0; + pCommonParam->Bitrate = pExynosOutputPort->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; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "RandomIntraMBRefresh: %d", pCommonParam->RandomIntraMBRefresh); + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pExynosInputPort->ePlaneType); + + /* 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 = (pExynosInputPort->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_TRACE, "pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]: 0x%x", 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_Mpeg4Enc_Param(pEncParam); +} + +static void Set_H263Enc_Param(EXYNOS_OMX_BASECOMPONENT *pExynosComponent) +{ + EXYNOS_OMX_BASEPORT *pExynosInputPort = NULL; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = 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; + pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + pExynosOutputPort = &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 = pExynosOutputPort->portDefinition.format.video.nFrameWidth; + pCommonParam->SourceHeight = pExynosOutputPort->portDefinition.format.video.nFrameHeight; + } else { + pCommonParam->SourceWidth = pExynosOutputPort->portDefinition.format.video.nFrameHeight; + pCommonParam->SourceHeight = pExynosOutputPort->portDefinition.format.video.nFrameWidth; + } + pCommonParam->IDRPeriod = pMpeg4Enc->h263Component[OUTPUT_PORT_INDEX].nPFrames + 1; + pCommonParam->SliceMode = 0; + pCommonParam->Bitrate = pExynosOutputPort->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; + } + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pExynosInputPort->ePlaneType); + + /* H263 specific parameters */ + pH263Param->FrameRate = (pExynosInputPort->portDefinition.format.video.xFramerate) >> 16; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]: 0x%x", 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 (nCmdIndex) { + case OMX_IndexConfigVideoIntraVOPRefresh: + { + nValue = VIDEO_FRAME_I; + pEncOps->Set_FrameType(pMFCMpeg4Handle->hMFCHandle, nValue); + pVideoEnc->IntraRefreshVOP = OMX_FALSE; + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_S32 nPFrames = (*((OMX_U32 *)pConfigData)) - 1; + nValue = nPFrames + 1; + pEncOps->Set_IDRPeriod(pMFCMpeg4Handle->hMFCHandle, 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); + } + } + 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); + } + } + 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); + } + break; + case OMX_IndexConfigOperatingRate: + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pConfigData; + OMX_U32 xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + + if (xFramerate == 0) + nValue = 100; + else + nValue = (OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + + pEncOps->Set_QosRatio(pMFCMpeg4Handle->hMFCHandle, nValue); + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; +#ifdef USE_QOS_CTRL + case OMX_IndexVendorSetQosRatio: /* MSRND */ + { + EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *pQosInfo = (EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *)pConfigData; + nValue = pQosInfo->nQosRatio; + pEncOps->Set_QosRatio(pMFCMpeg4Handle->hMFCHandle, nValue); + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; +#endif + default: + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nCmdIndex %x nValue %d ", pExynosComponent, __FUNCTION__, (int)nCmdIndex, nValue); + Exynos_OSAL_Free(pDynamicConfigCMD); + + if (pMpeg4Enc->hMFCMpeg4Handle.codecType == CODEC_TYPE_MPEG4) + Set_Mpeg4Enc_Param(pExynosComponent); + else + Set_H263Enc_Param(pExynosComponent); + +EXIT: + return; +} + +#if 0 /* unused code */ +OMX_ERRORTYPE GetCodecInputPrivateData(OMX_PTR codecBuffer, OMX_PTR addr[], OMX_U32 size[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +OMX_ERRORTYPE GetCodecOutputPrivateData(OMX_PTR codecBuffer, OMX_PTR *pVirtAddr, OMX_U32 *dataSize) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + ExynosVideoBuffer *pCodecBuffer; + + if (codecBuffer == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pCodecBuffer = (ExynosVideoBuffer *)codecBuffer; + + if (pVirtAddr != NULL) + *pVirtAddr = pCodecBuffer->planes[0].addr; + + if (dataSize != NULL) + *dataSize = pCodecBuffer->planes[0].allocSize; + + pCodecBuffer = (ExynosVideoBuffer *)codecBuffer; + +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_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate encoder ops buffer"); + 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); + + Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps); + + /* 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, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.pEncOps->Init(pVideoInstInfo); + if (pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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; + } + + /* 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; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + 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; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + 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; + void *hMFCHandle = NULL; + ExynosVideoEncOps *pEncOps = 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + + 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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Mpeg4CodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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; + CODEC_ENC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoEncBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoEnc->pMFCEncInputBuffer[0]); + pBufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoEnc->pMFCEncOutputBuffer[0]); + pBufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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 *)((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + void *hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + int i, nOutbufs; + + ExynosVideoEncOps *pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + + 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, "pVideoEnc->pMFCEncInputBuffer[%d]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncInputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncInputBuffer[%d]->pVirAddr[1]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[1]); + + 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, "pVideoEnc->pMFCEncOutputBuffer[%d]: 0x%x", i, pVideoEnc->pMFCEncOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoEnc->pMFCEncOutputBuffer[i]); + } + + pOutbufOps->Clear_Queue(hMFCHandle); + } + +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 *)((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + EXYNOS_MFC_MPEG4ENC_HANDLE *pMFCMpeg4Handle = &pMpeg4Enc->hMFCMpeg4Handle; + void *hMFCHandle = pMFCMpeg4Handle->hMFCHandle; + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + OMX_U32 oneFrameSize = pSrcInputData->dataLen; + + ExynosVideoEncOps *pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + ExynosVideoEncParam *pEncParam = NULL; + + ExynosVideoGeometry bufferConf; + OMX_U32 inputBufferNumber = 0; + int i, nOutbufs; + + FunctionIn(); + + if ((oneFrameSize <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] FBD with EOS will be processed through bypassBufferInfoQ", + 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); + Exynos_OSAL_SignalSet(pMpeg4Enc->hDestinationStartEvent); /* awake dstInput thread */ + + 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + Print_Mpeg4Enc_Param(pEncParam); + + /* input buffer info: only 3 config values needed */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eColorFormat = pEncParam->commonParam.FrameMap; + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = pExynosInputPort->portDefinition.format.video.nFrameWidth; + bufferConf.nFrameHeight = pExynosInputPort->portDefinition.format.video.nFrameHeight; + bufferConf.nStride = ALIGN(pExynosInputPort->portDefinition.format.video.nFrameWidth, 16); + } else { + bufferConf.nFrameWidth = pExynosInputPort->portDefinition.format.video.nFrameHeight; + bufferConf.nFrameHeight = pExynosInputPort->portDefinition.format.video.nFrameWidth; + bufferConf.nStride = ALIGN(pExynosInputPort->portDefinition.format.video.nFrameHeight, 16); + } + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + pInbufOps->Set_Shareable(hMFCHandle); + inputBufferNumber = MAX_INPUTBUFFER_NUM_DYNAMIC; + + if (pExynosInputPort->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(pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle, inputBufferNumber) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pExynosInputPort->bufferProcessType & BUFFER_SHARE) +#ifdef USE_METADATABUFFERTYPE + && (pExynosInputPort->bStoreMetaData != OMX_TRUE) +#endif + ) { + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + 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, nOutbufs; + + FunctionIn(); + + int nOutBufSize = pExynosOutputPort->portDefinition.nBufferSize; + if (pExynosOutputPort->bStoreMetaData == OMX_TRUE) { + nOutBufSize = ALIGN(pExynosOutputPort->portDefinition.format.video.nFrameWidth * + pExynosOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + } + + /* 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(pExynosOutputPort); + + if (pOutbufOps->Set_Geometry(pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle, &bufferConf) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to set geometry for output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* should be done before prepare output buffer */ + if (pOutbufOps->Enable_Cacheable) { + if (pOutbufOps->Enable_Cacheable(hMFCHandle) != VIDEO_ERROR_NONE) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + if (pOutbufOps->Set_Shareable) { + pOutbufOps->Set_Shareable(hMFCHandle); + } + int SetupBufferNumber = 0; + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) + SetupBufferNumber = MFC_OUTPUT_BUFFER_NUM_MAX; + else + SetupBufferNumber = pExynosOutputPort->portDefinition.nBufferCountActual; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SetupBufferNumber:%d", SetupBufferNumber); + + if (pOutbufOps->Setup(pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle, SetupBufferNumber) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + nAllocLen[0] = nOutBufSize; + ret = Exynos_Allocate_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX, MFC_OUTPUT_BUFFER_NUM_MAX, nAllocLen); + if (ret != OMX_ErrorNone) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr, + (int *)pVideoEnc->pMFCEncOutputBuffer[i]->fd, + pVideoEnc->pMFCEncOutputBuffer[i]->bufferSize, + nDataLen, + Exynos_GetPlaneFromPort(pExynosOutputPort), + NULL); + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + /* Register output buffer */ + /*************/ + /* TBD */ + /*************/ + } + pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_TRUE; + + 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) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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) + 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) { + 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) { + 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) { + 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) { + 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) + 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) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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) + 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) + 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_ErrorBadParameter; + 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) + 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) { + 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) + 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) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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; + 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_MakeDynamicConfigCMD(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) { + 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_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; +} + +/* MFC Init */ +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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)pVideoEnc->hCodecHandle;; + EXYNOS_MFC_MPEG4ENC_HANDLE *pMFCMpeg4Handle = &pMpeg4Enc->hMFCMpeg4Handle; + OMX_PTR hMFCHandle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + ExynosVideoInstInfo *pVideoInstInfo = &(pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + int i = 0, nPlaneCnt; + + FunctionIn(); + + pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCSrc = OMX_FALSE; + pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCDst = OMX_FALSE; + pVideoEnc->bFirstInput = OMX_TRUE; + pVideoEnc->bFirstOutput = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + eColorFormat = pExynosInputPort->portDefinition.format.video.eColorFormat; +#ifdef USE_METADATABUFFERTYPE + if (pExynosInputPort->bStoreMetaData == OMX_TRUE) { +#ifdef USE_ANDROIDOPAQUE + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) { + pExynosInputPort->bufferProcessType = BUFFER_COPY; + } else { + pExynosInputPort->bufferProcessType = BUFFER_SHARE; + } +#else + pExynosInputPort->bufferProcessType = BUFFER_SHARE; +#endif + } else { + pExynosInputPort->bufferProcessType = BUFFER_COPY; + } +#else + pExynosInputPort->bufferProcessType = BUFFER_COPY; +#endif + + 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/H.263 Codec Open */ + ret = Mpeg4CodecOpen(pMpeg4Enc, pVideoInstInfo); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle; + + Exynos_SetPlaneToPort(pExynosInputPort, MFC_DEFAULT_INPUT_BUFFER_PLANE); + Exynos_SetPlaneToPort(pExynosOutputPort, MFC_DEFAULT_OUTPUT_BUFFER_PLANE); + + Exynos_OSAL_SemaphoreCreate(&pExynosInputPort->codecSemID); + Exynos_OSAL_QueueCreate(&pExynosInputPort->codecBufferQ, MAX_QUEUE_ELEMENTS); + + if (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + 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. */ + } + + pMpeg4Enc->bSourceStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pMpeg4Enc->hSourceStartEvent); + pMpeg4Enc->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalCreate(&pMpeg4Enc->hDestinationStartEvent); + + 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 = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; + EXYNOS_OMX_VIDEOENC_COMPONENT *pVideoEnc = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle); + EXYNOS_OMX_BASEPORT *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + EXYNOS_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + OMX_PTR hMFCHandle = pMpeg4Enc->hMFCMpeg4Handle.hMFCHandle; + + ExynosVideoEncOps *pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + + int i = 0, plane = 0; + + FunctionIn(); + + if (pVideoEnc->csc_handle != NULL) { + csc_deinit(pVideoEnc->csc_handle); + pVideoEnc->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pMpeg4Enc->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pMpeg4Enc->hDestinationStartEvent); + pMpeg4Enc->hDestinationStartEvent = 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); + } 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); + + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pExynosOutputPort = &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; + ExynosVideoEncBufferOps *pOutbufOps = pMpeg4Enc->hMFCMpeg4Handle.pOutbufOps; + 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; + + FunctionIn(); + + if (pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = Mpeg4CodecSrcSetup(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + goto EXIT; + } + } + + if (pMpeg4Enc->hMFCMpeg4Handle.bConfiguredMFCDst == OMX_FALSE) { + ret = Mpeg4CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + } + + while (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + Change_Mpeg4Enc_Param(pExynosComponent); + } + + 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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp, pSrcInputData->nFlags); + pEncOps->Set_FrameTag(hMFCHandle, pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp); + pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp++; + pMpeg4Enc->hMFCMpeg4Handle.indexTimestamp %= MAX_TIMESTAMP; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosInputPort->hBufferCount, pSrcInputData->bufferHeader, INPUT_PORT_INDEX); +#endif + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] oneFrameSize: %ld, bufferHeader: 0x%p", pExynosComponent, __FUNCTION__, oneFrameSize, pSrcInputData->bufferHeader); + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pExynosInputPort->ePlaneType, + pExynosInputPort->portDefinition.format.video.nFrameWidth, + pExynosInputPort->portDefinition.format.video.nFrameHeight, + nDataLen, + nAllocLen); + } else { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pExynosInputPort->ePlaneType, + pExynosInputPort->portDefinition.format.video.nFrameHeight, + pExynosInputPort->portDefinition.format.video.nFrameWidth, + nDataLen, + nAllocLen); + } + + if (pExynosInputPort->bufferProcessType == BUFFER_COPY) { + tempBufferHeader.nFlags = pSrcInputData->nFlags; + tempBufferHeader.nTimeStamp = pSrcInputData->timeStamp; + pPrivate = (void *)&tempBufferHeader; + } else { + pPrivate = (void *)pSrcInputData->bufferHeader; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + if (pVideoEnc->nInbufSpareSize> 0) { + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = nAllocLen[i] + pVideoEnc->nInbufSpareSize; + } + + if (pSrcInputData->dataLen == 0) { + for (i = 0; i < nPlaneCnt; i++) + nDataLen[i] = 0; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - pInbufOps->Enqueue", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pMpeg4Enc->hDestinationStartEvent); + 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 *pExynosInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pMpeg4Enc->hMFCMpeg4Handle.pInbufOps; + ExynosVideoBuffer *pVideoBuffer = NULL; + ExynosVideoBuffer videoBuffer; + + FunctionIn(); + + if (pInbufOps->ExtensionDequeue(hMFCHandle, &videoBuffer) == VIDEO_ERROR_NONE) + pVideoBuffer = &videoBuffer; + else + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->pPrivate = NULL; + } else { + int plane = 0, nPlaneCnt; + nPlaneCnt = Exynos_GetPlaneFromPort(pExynosInputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pSrcOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pSrcOutputData->multiPlaneBuffer.fd[plane] = pVideoBuffer->planes[plane].fd; + + pSrcOutputData->allocSize += pVideoBuffer->planes[plane].allocSize; + } + + if (pExynosInputPort->bufferProcessType & BUFFER_COPY) { + int i; + for (i = 0; i < MFC_INPUT_BUFFER_NUM_MAX; i++) { + if (pSrcOutputData->multiPlaneBuffer.dataBuffer[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, "%s: %d: Failed - Lost buffer", __FUNCTION__, __LINE__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pExynosInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountDecrease(pExynosInputPort->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 *pExynosOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pMpeg4Enc->hMFCMpeg4Handle.pEncOps; + 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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + +#ifdef PERFORMANCE_DEBUG + Exynos_OSAL_V4L2CountIncrease(pExynosOutputPort->hBufferCount, pDstInputData->bufferHeader, OUTPUT_PORT_INDEX); +#endif + + nAllocLen[0] = pExynosOutputPort->portDefinition.nBufferSize; + if (pExynosOutputPort->bStoreMetaData == OMX_TRUE) + nAllocLen[0] = ALIGN(pExynosOutputPort->portDefinition.format.video.nFrameWidth * pExynosOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pExynosOutputPort), + pDstInputData->bufferHeader); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - pOutbufOps->Enqueue", __FUNCTION__, __LINE__); + 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 *pExynosOutputPort = &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; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + ExynosVideoErrorType codecReturn = VIDEO_ERROR_NONE; + + OMX_S32 indexTimestamp = 0; + + 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, "HW is not available"); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + pMpeg4Enc->hMFCMpeg4Handle.outputIndexTimestamp++; + pMpeg4Enc->hMFCMpeg4Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pDstOutputData->multiPlaneBuffer.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 (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + int i = 0; + pDstOutputData->pPrivate = NULL; + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + if (pDstOutputData->multiPlaneBuffer.dataBuffer[0] == + pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoEnc->pMFCEncOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + if (pVideoEnc->bFirstOutput == OMX_FALSE) { + OMX_U8 *p = NULL; + + /* start header return */ + 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); + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Tag(%d) is invalid. changes to use outputIndexTimestamp(%d)", + pExynosComponent, __FUNCTION__, + indexTimestamp, pMpeg4Enc->hMFCMpeg4Handle.outputIndexTimestamp); + indexTimestamp = pMpeg4Enc->hMFCMpeg4Handle.outputIndexTimestamp; + } + + /* 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; + } + } + } + + 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 timestamp %lld us (%.2f secs), Tag: %d, frameType: %d dataLen: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, indexTimestamp, + pVideoBuffer->frameType, pDstOutputData->dataLen); + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pExynosOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) && + (pExynosComponent->bBehaviorEOS == OMX_FALSE))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + } + + if (((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) && + (pExynosComponent->bBehaviorEOS == OMX_TRUE)) + 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_MPEG4ENC_HANDLE *pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->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 (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_ERROR, "%s: %d: Failed - SrcIn -> event is thrown to client", __FUNCTION__, __LINE__); + 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 *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 ((pMpeg4Enc->bSourceStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosInputPort))) { + Exynos_OSAL_SignalWait(pMpeg4Enc->hSourceStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pMpeg4Enc->hSourceStartEvent); + } + + ret = Exynos_Mpeg4Enc_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - SrcOut -> event is thrown to client", __FUNCTION__, __LINE__); + 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 *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 (pExynosOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pMpeg4Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg4Enc->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pMpeg4Enc->hDestinationStartEvent); + } + + if (Exynos_OSAL_GetElemNum(&pMpeg4Enc->bypassBufferInfoQ) > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] buffer with EOS will be returned by bypassBufferInfoQ", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pMpeg4Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + 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_ERROR, "%s: %d: Failed - DstIn -> event is thrown to client", __FUNCTION__, __LINE__); + 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 *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 (pExynosOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pMpeg4Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pExynosOutputPort))) { + Exynos_OSAL_SignalWait(pMpeg4Enc->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pMpeg4Enc->hDestinationStartEvent); + } + + if (Exynos_OSAL_GetElemNum(&pMpeg4Enc->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pExynosOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - DstOut -> event is thrown to client", __FUNCTION__, __LINE__); + 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: parameters are null, ret: %X", __FUNCTION__, ret); + 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: componentName(%s) error, ret: %X", __FUNCTION__, componentName, ret); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_VideoDecodeComponentInit error, ret: %X", __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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: componentName alloc error, ret: %X", __FUNCTION__, ret); + 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: EXYNOS_MPEG4ENC_HANDLE alloc error, ret: %X", __FUNCTION__, ret); + 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; + +#if 0 /* unused code */ + pVideoEnc->exynos_checkInputFrame = NULL; + pVideoEnc->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoEnc->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pVideoEnc->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoEnc->hSharedMemory == NULL) { + Exynos_OSAL_Free(pMpeg4Enc); + pMpeg4Enc = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->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]: Exynos_Video_GetInstInfo is failed", pExynosComponent, __FUNCTION__); + Exynos_OSAL_Free(pMpeg4Enc); + pMpeg4Enc = ((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 %d %d %d %d %d %d", pExynosComponent, __FUNCTION__, + (pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.specificInfo.enc.bRGBSupport), + (pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.specificInfo.enc.nSpareSize), + (pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.specificInfo.enc.bTemporalSvcSupport), + (pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.specificInfo.enc.bSkypeSupport), + (pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.specificInfo.enc.bRoiInfoSupport), + (pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.specificInfo.enc.bQpRangePBSupport)); + + if (pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.specificInfo.enc.nSpareSize > 0) + pVideoEnc->nInbufSpareSize = pMpeg4Enc->hMFCMpeg4Handle.videoInstInfo.specificInfo.enc.nSpareSize; + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + 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; + + Exynos_OSAL_SharedMemory_Close(pVideoEnc->hSharedMemory); + + Exynos_OSAL_Free(pExynosComponent->componentName); + pExynosComponent->componentName = NULL; + + pMpeg4Enc = (EXYNOS_MPEG4ENC_HANDLE *)((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle; + if (pMpeg4Enc != NULL) { + Exynos_OSAL_Free(pMpeg4Enc); + pMpeg4Enc = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->hCodecHandle = NULL; + } + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) { + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.h b/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.h new file mode 100644 index 0000000..9dbaa8c --- /dev/null +++ b/component/video/enc/mpeg4/Exynos_OMX_Mpeg4enc.h @@ -0,0 +1,98 @@ +/* + * + * 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 hDestinationStartEvent; + + 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/component/video/enc/mpeg4/NOTICE b/component/video/enc/mpeg4/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/enc/mpeg4/library_register.c b/component/video/enc/mpeg4/library_register.c new file mode 100644 index 0000000..6b9f5ea --- /dev/null +++ b/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/component/video/enc/mpeg4/library_register.h b/component/video/enc/mpeg4/library_register.h new file mode 100644 index 0000000..60f6037 --- /dev/null +++ b/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/component/video/enc/vp8/Android.mk b/component/video/enc/vp8/Android.mk new file mode 100644 index 0000000..710bc97 --- /dev/null +++ b/component/video/enc/vp8/Android.mk @@ -0,0 +1,67 @@ +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_CFLAGS := +LOCAL_CFLAGS += -DUSE_VP8_SUPPORT + +ifeq ($(BOARD_USE_METADATABUFFERTYPE), true) +LOCAL_CFLAGS += -DUSE_METADATABUFFERTYPE + +ifeq ($(BOARD_USE_ANDROIDOPAQUE), true) +LOCAL_CFLAGS += -DUSE_ANDROIDOPAQUE +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 ($(BOARD_USE_QOS_CTRL), true) +LOCAL_CFLAGS += -DUSE_QOS_CTRL +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Venc libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/enc/vp8/Exynos_OMX_Vp8enc.c b/component/video/enc/vp8/Exynos_OMX_Vp8enc.c new file mode 100644 index 0000000..0f41215 --- /dev/null +++ b/component/video/enc/vp8/Exynos_OMX_Vp8enc.c @@ -0,0 +1,3053 @@ +/* + * + * 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" + +/* 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; + + FunctionIn(); + + 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; + } + + while ((pVp8Enc->hMFCVp8Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pVp8Enc->hMFCVp8Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : there is no any profile/level", __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); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s : supported profile(%x), level(%x)", __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, "%s : there is no any profile/level", __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, "%s : profile(%x)/level(%x) is %ssupported", __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_ESSENTIAL, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + + /* 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_ESSENTIAL, "Vp8NumberOfPartitions : %d", pVp8Param->Vp8NumberOfPartitions); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Vp8FilterLevel : %d", pVp8Param->Vp8FilterLevel); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Vp8FilterSharpness : %d", pVp8Param->Vp8FilterSharpness); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Vp8GoldenFrameSel : %d", pVp8Param->Vp8GoldenFrameSel); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Vp8GFRefreshPeriod : %d", pVp8Param->Vp8GFRefreshPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RefNumberForPFrame : %d", pVp8Param->RefNumberForPFrame); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "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; + + 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; + 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 = 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; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "RandomIntraMBRefresh: %d", pCommonParam->RandomIntraMBRefresh); + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + /* 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 */ + + /* there is no interface at OMX IL component */ + pVp8Param->RefNumberForPFrame = 1; /* 1 ~ 2 */ + + 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_TRACE, "pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]: 0x%x", 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; + + 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 (nCmdIndex) { + case OMX_IndexConfigVideoIntraVOPRefresh: + { + nValue = VIDEO_FRAME_I; + pEncOps->Set_FrameType(pMFCVp8Handle->hMFCHandle, nValue); + pVideoEnc->IntraRefreshVOP = OMX_FALSE; + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_S32 nPFrames = (*((OMX_U32 *)pConfigData)) - 1; + nValue = nPFrames + 1; + pEncOps->Set_IDRPeriod(pMFCVp8Handle->hMFCHandle, nValue); + } + break; + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pConfigData; + int i; + + if (pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] != OMX_Video_ControlRateDisable) { + /* bitrate : main */ + nValue = pConfigBitrate->nEncodeBitrate; + pEncOps->Set_BitRate(pMFCVp8Handle->hMFCHandle, 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); + } + } + 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; + + pEncOps->Set_QpRange(pMFCVp8Handle->hMFCHandle, qpRange); + } + break; + case OMX_IndexConfigOperatingRate: + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pConfigData; + OMX_U32 xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + + if (xFramerate == 0) + nValue = 100; + else + nValue = (OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + + pEncOps->Set_QosRatio(pMFCVp8Handle->hMFCHandle, nValue); + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; +#ifdef USE_QOS_CTRL + case OMX_IndexVendorSetQosRatio: /* MSRND */ + { + EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *pQosInfo = (EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *)pConfigData; + nValue = pQosInfo->nQosRatio; + pEncOps->Set_QosRatio(pMFCVp8Handle->hMFCHandle, nValue); + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; +#endif + default: + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nCmdIndex %x nValue %d ", pExynosComponent, __FUNCTION__, (int)nCmdIndex, nValue); + Exynos_OSAL_Free(pDynamicConfigCMD); + + Set_VP8Enc_Param(pExynosComponent); + +EXIT: + return; +} + +#if 0 /* unused code */ +OMX_ERRORTYPE GetCodecInputPrivateData( + OMX_PTR pCodecBuffer, + OMX_PTR pVirtAddr[], + OMX_U32 nSize[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +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_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate encoder ops buffer"); + 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); + + Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps); + + /* 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, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pVp8Enc->hMFCVp8Handle.hMFCHandle = pVp8Enc->hMFCVp8Handle.pEncOps->Init(pVideoInstInfo); + if (pVp8Enc->hMFCVp8Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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; + } + + /* 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; + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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) { + 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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP8CodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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; + CODEC_ENC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoEncBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoEnc->pMFCEncInputBuffer[0]); + pBufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoEnc->pMFCEncOutputBuffer[0]); + pBufOps = pVp8Enc->hMFCVp8Handle.pOutbufOps; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + int i, nOutbufs; + + ExynosVideoEncOps *pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps; + 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, "pVideoEnc->pMFCEncInputBuffer[%d]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncInputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncInputBuffer[%d]->pVirAddr[1]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[1]); + + 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, "pVideoEnc->pMFCEncOutputBuffer[%d]: 0x%x", i, pVideoEnc->pMFCEncOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoEnc->pMFCEncOutputBuffer[i]); + } + + pOutbufOps->Clear_Queue(hMFCHandle); + } + +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]; + + ExynosVideoEncOps *pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pVp8Enc->hMFCVp8Handle.pOutbufOps; + ExynosVideoEncParam *pEncParam = NULL; + + ExynosVideoGeometry bufferConf; + OMX_U32 nInputBufferCnt = 0; + int i, nOutbufs; + + FunctionIn(); + + if ((pSrcInputData->dataLen <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] FBD with EOS will be processed through bypassBufferInfoQ", + 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); + Exynos_OSAL_SignalSet(pVp8Enc->hDestinationStartEvent); /* awake dstInput thread */ + + 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); + + /* input buffer info: only 3 config values needed */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eColorFormat = pEncParam->commonParam.FrameMap; + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = pInputPort->portDefinition.format.video.nFrameWidth; + bufferConf.nFrameHeight = pInputPort->portDefinition.format.video.nFrameHeight; + bufferConf.nStride = ALIGN(pInputPort->portDefinition.format.video.nFrameWidth, 16); + } else { + bufferConf.nFrameWidth = pInputPort->portDefinition.format.video.nFrameHeight; + bufferConf.nFrameHeight = pInputPort->portDefinition.format.video.nFrameWidth; + bufferConf.nStride = ALIGN(pInputPort->portDefinition.format.video.nFrameHeight, 16); + } + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + pInbufOps->Set_Shareable(hMFCHandle); + nInputBufferCnt = 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInputBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pInputPort->bufferProcessType & BUFFER_SHARE) +#ifdef USE_METADATABUFFERTYPE + && (pInputPort->bStoreMetaData != OMX_TRUE) +#endif + ) { + 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 *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + 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->bStoreMetaData == OMX_TRUE) { + nOutBufSize = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * + pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + } + + /* 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, "Failed to set geometry for output buffer"); + 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, "Failed to setup output buffer"); + 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) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr, + (int *)pVideoEnc->pMFCEncOutputBuffer[i]->fd, + pVideoEnc->pMFCEncOutputBuffer[i]->bufferSize, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + NULL); + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /* Register output buffer */ + /*************/ + /* TBD */ + /*************/ + } + + pVp8Enc->hMFCVp8Handle.bConfiguredMFCDst = OMX_TRUE; + + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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) + 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) + 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) + 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) + 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) + 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; + 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) + 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; + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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_ErrorBadParameter; + 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) + 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) + 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) { + 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, "%s[%x] xFramerate is changed to invalid value(%d)", + __FUNCTION__, OMX_IndexParamVideoPortFormat, 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) { + 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_WARNING, "%s[%x] xFramerate is changed to invalid value(%d)", + __FUNCTION__, OMX_IndexParamPortDefinition, pPortDef->format.video.xFramerate >> 16); + } + + 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, "pExynosOutputPort->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; + 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.specificInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) && + (pSrcVp8EncoderType->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: MFC D/D doesn't support Temporal SVC", __FUNCTION__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + if ((pSrcVp8EncoderType->nMinQuantizer > pSrcVp8EncoderType->nMaxQuantizer) || + (pSrcVp8EncoderType->nMaxQuantizer >= VP8_QP_INDEX_RANGE)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: QP value is invalid(min:%d, max:%d)", __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; + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp8Enc = (EXYNOS_VP8ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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; + default: + ret = Exynos_OMX_VideoEncodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + OMX_PTR pDynamicConfigCMD = NULL; + pDynamicConfigCMD = Exynos_OMX_MakeDynamicConfigCMD(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) { + 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_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_PTR hMFCHandle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + ExynosVideoInstInfo *pVideoInstInfo = &(pVp8Enc->hMFCVp8Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + + int i = 0, nPlaneCnt; + + FunctionIn(); + + pVp8Enc->hMFCVp8Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp8Enc->hMFCVp8Handle.bConfiguredMFCDst = OMX_FALSE; + pVideoEnc->bFirstInput = OMX_TRUE; + pVideoEnc->bFirstOutput = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; +#ifdef USE_METADATABUFFERTYPE + if (pInputPort->bStoreMetaData == OMX_TRUE) { +#ifdef USE_ANDROIDOPAQUE + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) + pInputPort->bufferProcessType = BUFFER_COPY; + else + pInputPort->bufferProcessType = BUFFER_SHARE; +#else + pInputPort->bufferProcessType = BUFFER_COPY; +#endif + } else { + pInputPort->bufferProcessType = BUFFER_COPY; + } +#else + pInputPort->bufferProcessType = BUFFER_COPY; +#endif + + 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; + + pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps; + pInbufOps = pVp8Enc->hMFCVp8Handle.pInbufOps; + pOutbufOps = pVp8Enc->hMFCVp8Handle.pOutbufOps; + hMFCHandle = pVp8Enc->hMFCVp8Handle.hMFCHandle; + + 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->hDestinationStartEvent); + + 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 = (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; + + int i = 0, plane = 0; + + FunctionIn(); + + if (pVideoEnc->csc_handle != NULL) { + csc_deinit(pVideoEnc->csc_handle); + pVideoEnc->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pVp8Enc->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pVp8Enc->hDestinationStartEvent); + pVp8Enc->hDestinationStartEvent = NULL; + pVp8Enc->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalTerminate(pVp8Enc->hSourceStartEvent); + pVp8Enc->hSourceStartEvent = NULL; + pVp8Enc->bSourceStart = OMX_FALSE; + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pOutputPort->codecSemID); + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + } else if (pInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_OSAL_QueueTerminate(&pInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pInputPort->codecSemID); + + 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]; + 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; + + FunctionIn(); + + if (pVp8Enc->hMFCVp8Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = VP8CodecSrcSetup(pOMXComponent, pSrcInputData); + if ((ret != OMX_ErrorNone) || + ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS)) { + goto EXIT; + } + } + + if (pVp8Enc->hMFCVp8Handle.bConfiguredMFCDst == OMX_FALSE) { + ret = VP8CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + } + + while (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + Change_VP8Enc_Param(pExynosComponent); + } + + 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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pVp8Enc->hMFCVp8Handle.indexTimestamp, pSrcInputData->nFlags); + + 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 + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] oneFrameSize: %ld, bufferHeader: 0x%p", pExynosComponent, __FUNCTION__, pSrcInputData->dataLen, pSrcInputData->bufferHeader); + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + pInputPort->portDefinition.format.video.nFrameWidth, + pInputPort->portDefinition.format.video.nFrameHeight, + nDataLen, + nAllocLen); + } else { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + pInputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.format.video.nFrameWidth, + 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 (pVideoEnc->nInbufSpareSize> 0) { + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = nAllocLen[i] + pVideoEnc->nInbufSpareSize; + } + + if (pSrcInputData->dataLen == 0) { + for (i = 0; i < nPlaneCnt; i++) + nDataLen[i] = 0; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - pInbufOps->Enqueue", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp8Enc->hDestinationStartEvent); + 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 + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->pPrivate = NULL; + } else { + int plane = 0, nPlaneCnt; + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pSrcOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pSrcOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[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, "%s: %d: Failed - Lost buffer", __FUNCTION__, __LINE__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#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]; + + ExynosVideoEncOps *pEncOps = pVp8Enc->hMFCVp8Handle.pEncOps; + 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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + 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->bStoreMetaData == OMX_TRUE) + nAllocLen[0] = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)&pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + pDstInputData->bufferHeader); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - pOutbufOps->Enqueue", __FUNCTION__, __LINE__); + 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; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + 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, "HW is not available"); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + pVp8Enc->hMFCVp8Handle.outputIndexTimestamp++; + pVp8Enc->hMFCVp8Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pDstOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[0] == + pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoEnc->pMFCEncOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + if (pVideoEnc->bFirstOutput == OMX_FALSE) { + pDstOutputData->timeStamp = 0; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + pVideoEnc->bFirstOutput = OMX_TRUE; + } else { + indexTimestamp = pEncOps->Get_FrameTag(pVp8Enc->hMFCVp8Handle.hMFCHandle); + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Tag(%d) is invalid. changes to use outputIndexTimestamp(%d)", + pExynosComponent, __FUNCTION__, + indexTimestamp, pVp8Enc->hMFCVp8Handle.outputIndexTimestamp); + indexTimestamp = pVp8Enc->hMFCVp8Handle.outputIndexTimestamp; + } + + 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 timestamp %lld us (%.2f secs), Tag: %d, frameType: %d dataLen: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, indexTimestamp, + pVideoBuffer->frameType, pDstOutputData->dataLen); + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) && + (pExynosComponent->bBehaviorEOS == OMX_FALSE))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + } + + if (((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) && + (pExynosComponent->bBehaviorEOS == OMX_TRUE)) + 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_ERROR, "%s: %d: Failed - SrcIn -> event is thrown to client", __FUNCTION__, __LINE__); + 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_SignalReset(pVp8Enc->hSourceStartEvent); + } + + ret = Exynos_VP8Enc_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - SrcOut -> event is thrown to client", __FUNCTION__, __LINE__); + 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 (pOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pVp8Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pVp8Enc->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pVp8Enc->hDestinationStartEvent); + } + + if (Exynos_OSAL_GetElemNum(&pVp8Enc->bypassBufferInfoQ) > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] buffer with EOS will be returned by bypassBufferInfoQ", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pVp8Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + 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_ERROR, "%s: %d: Failed - DstIn -> event is thrown to client", __FUNCTION__, __LINE__); + 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 (pOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pVp8Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pVp8Enc->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pVp8Enc->hDestinationStartEvent); + } + + if (Exynos_OSAL_GetElemNum(&pVp8Enc->bypassBufferInfoQ) > 0) { + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - DstOut -> event is thrown to client", __FUNCTION__, __LINE__); + 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, "OMX_ErrorBadParameter, Line:%d", __LINE__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP8_ENC, componentName) != 0) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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; + +#if 0 /* unused code */ + pVideoEnc->exynos_checkInputFrame = NULL; + pVideoEnc->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoEnc->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pVideoEnc->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoEnc->hSharedMemory == NULL) { + Exynos_OSAL_Free(pVp8Enc); + pVp8Enc = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->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; + + if (Exynos_Video_GetInstInfo(&(pVp8Enc->hMFCVp8Handle.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(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 %d %d %d %d %d %d", pExynosComponent, __FUNCTION__, + (pVp8Enc->hMFCVp8Handle.videoInstInfo.specificInfo.enc.bRGBSupport), + (pVp8Enc->hMFCVp8Handle.videoInstInfo.specificInfo.enc.nSpareSize), + (pVp8Enc->hMFCVp8Handle.videoInstInfo.specificInfo.enc.bTemporalSvcSupport), + (pVp8Enc->hMFCVp8Handle.videoInstInfo.specificInfo.enc.bSkypeSupport), + (pVp8Enc->hMFCVp8Handle.videoInstInfo.specificInfo.enc.bRoiInfoSupport), + (pVp8Enc->hMFCVp8Handle.videoInstInfo.specificInfo.enc.bQpRangePBSupport)); + + if (pVp8Enc->hMFCVp8Handle.videoInstInfo.specificInfo.enc.nSpareSize > 0) + pVideoEnc->nInbufSpareSize = pVp8Enc->hMFCVp8Handle.videoInstInfo.specificInfo.enc.nSpareSize; + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + 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; + + 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; + } + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/enc/vp8/Exynos_OMX_Vp8enc.h b/component/video/enc/vp8/Exynos_OMX_Vp8enc.h new file mode 100644 index 0000000..0882f28 --- /dev/null +++ b/component/video/enc/vp8/Exynos_OMX_Vp8enc.h @@ -0,0 +1,91 @@ +/* + * + * 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; + + #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 hDestinationStartEvent; + + 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/component/video/enc/vp8/NOTICE b/component/video/enc/vp8/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/enc/vp8/library_register.c b/component/video/enc/vp8/library_register.c new file mode 100644 index 0000000..ccd44f7 --- /dev/null +++ b/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/component/video/enc/vp8/library_register.h b/component/video/enc/vp8/library_register.h new file mode 100644 index 0000000..d0a3090 --- /dev/null +++ b/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/component/video/enc/vp9/Android.mk b/component/video/enc/vp9/Android.mk new file mode 100644 index 0000000..3f77379 --- /dev/null +++ b/component/video/enc/vp9/Android.mk @@ -0,0 +1,66 @@ +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_CFLAGS := -DUSE_VP9_SUPPORT + +ifeq ($(BOARD_USE_METADATABUFFERTYPE), true) +LOCAL_CFLAGS += -DUSE_METADATABUFFERTYPE + +ifeq ($(BOARD_USE_ANDROIDOPAQUE), true) +LOCAL_CFLAGS += -DUSE_ANDROIDOPAQUE +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 ($(BOARD_USE_QOS_CTRL), true) +LOCAL_CFLAGS += -DUSE_QOS_CTRL +endif + +ifeq ($(BOARD_USE_SINGLE_PLANE_IN_DRM), true) +LOCAL_CFLAGS += -DUSE_SINGLE_PLANE_IN_DRM +endif + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_Venc libExynosOMX_OSAL libExynosOMX_Basecomponent \ + libExynosVideoApi +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils libui \ + libExynosOMX_Resourcemanager libcsc libexynosv4l2 libion libhardware + +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 \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/component/video/enc/vp9/Exynos_OMX_Vp9enc.c b/component/video/enc/vp9/Exynos_OMX_Vp9enc.c new file mode 100644 index 0000000..49de498 --- /dev/null +++ b/component/video/enc/vp9/Exynos_OMX_Vp9enc.c @@ -0,0 +1,2936 @@ +/* + * + * 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" + +/* 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; + + FunctionIn(); + + 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_VP9ProfileMain; + pVp9Enc->hMFCVp9Handle.nProfileCnt = nProfileCnt; + pVp9Enc->hMFCVp9Handle.maxLevel = OMX_VIDEO_VP9Level_Version0; + +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; + + 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; + } + + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + if (pVp9Enc == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + while ((pVp9Enc->hMFCVp9Handle.maxLevel >> nLevelCnt) > 0) { + nLevelCnt++; + } + + if ((pVp9Enc->hMFCVp9Handle.nProfileCnt == 0) || + (nLevelCnt == 0)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : there is no any profile/level", __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); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s : supported profile(%x), level(%x)", __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, "%s : there is no any profile/level", __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, "%s : profile(%x)/level(%x) is %ssupported", __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_VP9ProfileMain: + ret = 0; + break; + default: + ret = 0; + break; + } + + return ret; +} + +static OMX_U32 OMXVP9LevelToMFCVersion(OMX_VIDEO_VP9LEVELTYPE eLevel) +{ + OMX_U32 ret; + + switch (eLevel) { + case OMX_VIDEO_VP9Level_Version0: + ret = 0; + 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_ESSENTIAL, "PadControlOn : %d", pCommonParam->PadControlOn); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "LumaPadVal : %d", pCommonParam->LumaPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CbPadVal : %d", pCommonParam->CbPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "CrPadVal : %d", pCommonParam->CrPadVal); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameMap : %d", pCommonParam->FrameMap); + + /* Vp9 specific parameters */ + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "FrameRate : %d", pVp9Param->FrameRate); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Vp9Version : %d", pVp9Param->Vp9Version); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Vp9GoldenFrameSel : %d", pVp9Param->Vp9GoldenFrameSel); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "Vp9GFRefreshPeriod : %d", pVp9Param->Vp9GFRefreshPeriod); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "RefNumberForPFrame : %d", pVp9Param->RefNumberForPFrame); + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "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; + + 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; + 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 = pVp9Enc->nPFrames + 1; + pCommonParam->SliceMode = 0; /* invalid */ + 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; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "RandomIntraMBRefresh: %d", pCommonParam->RandomIntraMBRefresh); + } else { + /* Don't support "Adaptive" and "Cyclic + Adaptive" */ + pCommonParam->RandomIntraMBRefresh = 0; + } + + eColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + pCommonParam->FrameMap = Exynos_OSAL_OMX2VideoFormat(eColorFormat, pInputPort->ePlaneType); + + /* Vp9 specific parameters */ + pVp9Param->FrameRate = (pInputPort->portDefinition.format.video.xFramerate) >> 16; + pVp9Param->Vp9Version = OMXVP9LevelToMFCVersion(pVp9Enc->VP9Component[OUTPUT_PORT_INDEX].eLevel); + /* there is no interface at OMX IL component */ + pVp9Param->RefNumberForPFrame = 2; + + 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_MAXVP9TEMPORALLAYERS; 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_TRACE, "pVideoEnc->eControlRate[OUTPUT_PORT_INDEX]: 0x%x", 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; + + 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 (nCmdIndex) { + case OMX_IndexConfigVideoIntraVOPRefresh: + { + nValue = VIDEO_FRAME_I; + pEncOps->Set_FrameType(pMFCVp9Handle->hMFCHandle, nValue); + pVideoEnc->IntraRefreshVOP = OMX_FALSE; + } + break; + case OMX_IndexConfigVideoIntraPeriod: + { + OMX_S32 nPFrames = (*((OMX_U32 *)pConfigData)) - 1; + nValue = nPFrames + 1; + pEncOps->Set_IDRPeriod(pMFCVp9Handle->hMFCHandle, nValue); + } + break; + case OMX_IndexConfigVideoBitrate: + { + OMX_VIDEO_CONFIG_BITRATETYPE *pConfigBitrate = (OMX_VIDEO_CONFIG_BITRATETYPE *)pConfigData; + int i; + + if (pVideoEnc->eControlRate[OUTPUT_PORT_INDEX] != OMX_Video_ControlRateDisable) { + /* bitrate : main */ + nValue = pConfigBitrate->nEncodeBitrate; + pEncOps->Set_BitRate(pMFCVp9Handle->hMFCHandle, 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_MAXVP9TEMPORALLAYERS; 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); + } + } + 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; + + pEncOps->Set_QpRange(pMFCVp9Handle->hMFCHandle, qpRange); + } + break; + case OMX_IndexConfigOperatingRate: + { + OMX_PARAM_U32TYPE *pConfigRate = (OMX_PARAM_U32TYPE *)pConfigData; + OMX_U32 xFramerate = pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.xFramerate; + + if (xFramerate == 0) + nValue = 100; + else + nValue = (OMX_U32)((pConfigRate->nU32 / (double)xFramerate) * 100); + + pEncOps->Set_QosRatio(pMFCVp9Handle->hMFCHandle, nValue); + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; +#ifdef USE_QOS_CTRL + case OMX_IndexVendorSetQosRatio: /* MSRND */ + { + EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *pQosInfo = (EXYNOS_OMX_VIDEO_CONFIG_QOSINFO *)pConfigData; + nValue = pQosInfo->nQosRatio; + pEncOps->Set_QosRatio(pMFCVp9Handle->hMFCHandle, nValue); + pVideoEnc->bQosChanged = OMX_FALSE; + } + break; +#endif + default: + break; + } + + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] nCmdIndex %x nValue %d ", pExynosComponent, __FUNCTION__, (int)nCmdIndex, nValue); + Exynos_OSAL_Free(pDynamicConfigCMD); + + Set_VP9Enc_Param(pExynosComponent); + +EXIT: + return; +} + +#if 0 /* unused code */ +OMX_ERRORTYPE GetCodecInputPrivateData( + OMX_PTR pCodecBuffer, + OMX_PTR pVirtAddr[], + OMX_U32 nSize[]) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + +EXIT: + return ret; +} +#endif + +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_CODING_UNKNOWN; + int i; + + FunctionIn(); + + 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) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, Line:%d", __LINE__); + 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, "Failed to allocate encoder ops buffer"); + 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); + + Exynos_Video_Register_Encoder(pEncOps, pInbufOps, pOutbufOps); + + /* 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, "Mandatory functions must be supplied"); + 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, "Mandatory functions must be supplied"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* alloc context, open, querycap */ +#ifdef USE_DMA_BUF + pVideoInstInfo->nMemoryType = V4L2_MEMORY_DMABUF; +#else + pVideoInstInfo->nMemoryType = V4L2_MEMORY_USERPTR; +#endif + pVp9Enc->hMFCVp9Handle.hMFCHandle = pVp9Enc->hMFCVp9Handle.pEncOps->Init(pVideoInstInfo); + if (pVp9Enc->hMFCVp9Handle.hMFCHandle == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to allocate context buffer"); + 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; + } + + /* 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; + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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; + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)((EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate)->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) { + 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->hDestinationStartEvent); + Exynos_OSAL_SleepMillisec(0); + } + } + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE VP9CodecRegistCodecBuffers( + OMX_COMPONENTTYPE *pOMXComponent, + OMX_U32 nPortIndex, + int nBufferCnt) +{ + 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; + CODEC_ENC_BUFFER **ppCodecBuffer = NULL; + ExynosVideoEncBufferOps *pBufOps = NULL; + ExynosVideoPlane *pPlanes = NULL; + + int nPlaneCnt = 0; + int i, j; + + FunctionIn(); + + if (nPortIndex == INPUT_PORT_INDEX) { + ppCodecBuffer = &(pVideoEnc->pMFCEncInputBuffer[0]); + pBufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + } else { + ppCodecBuffer = &(pVideoEnc->pMFCEncOutputBuffer[0]); + pBufOps = pVp9Enc->hMFCVp9Handle.pOutbufOps; + } + + nPlaneCnt = Exynos_GetPlaneFromPort(&pExynosComponent->pExynosPort[nPortIndex]); + pPlanes = (ExynosVideoPlane *)Exynos_OSAL_Malloc(sizeof(ExynosVideoPlane) * nPlaneCnt); + if (pPlanes == NULL) { + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + /* Register buffer */ + for (i = 0; i < nBufferCnt; i++) { + for (j = 0; j < nPlaneCnt; j++) { + pPlanes[j].addr = ppCodecBuffer[i]->pVirAddr[j]; + pPlanes[j].fd = ppCodecBuffer[i]->fd[j]; + pPlanes[j].allocSize = ppCodecBuffer[i]->bufferSize[j]; + } + + if (pBufOps->Register(hMFCHandle, pPlanes, nPlaneCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "PORT[%d]: Failed to Register buffer", nPortIndex); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Free(pPlanes); + goto EXIT; + } + } + + Exynos_OSAL_Free(pPlanes); + + 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; + EXYNOS_OMX_BASEPORT *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + int i, nOutbufs; + + ExynosVideoEncOps *pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps; + 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, "pVideoEnc->pMFCEncInputBuffer[%d]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncInputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[0]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncInputBuffer[%d]->pVirAddr[1]: 0x%x", i, pVideoEnc->pMFCEncInputBuffer[i]->pVirAddr[1]); + + 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, "pVideoEnc->pMFCEncOutputBuffer[%d]: 0x%x", i, pVideoEnc->pMFCEncOutputBuffer[i]); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pVideoEnc->pMFCEncOutputBuffer[%d]->pVirAddr[0]: 0x%x", i, pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]); + + Exynos_CodecBufferEnqueue(pExynosComponent, OUTPUT_PORT_INDEX, pVideoEnc->pMFCEncOutputBuffer[i]); + } + + pOutbufOps->Clear_Queue(hMFCHandle); + } + +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]; + + ExynosVideoEncOps *pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + ExynosVideoEncBufferOps *pOutbufOps = pVp9Enc->hMFCVp9Handle.pOutbufOps; + ExynosVideoEncParam *pEncParam = NULL; + + ExynosVideoGeometry bufferConf; + OMX_U32 nInputBufferCnt = 0; + int i, nOutbufs; + + FunctionIn(); + + if ((pSrcInputData->dataLen <= 0) && (pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS)) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] FBD with EOS will be processed through bypassBufferInfoQ", + 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); + Exynos_OSAL_SignalSet(pVp9Enc->hDestinationStartEvent); /* awake dstInput thread */ + + 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); + + /* input buffer info: only 3 config values needed */ + Exynos_OSAL_Memset(&bufferConf, 0, sizeof(bufferConf)); + bufferConf.eColorFormat = pEncParam->commonParam.FrameMap; + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + bufferConf.nFrameWidth = pInputPort->portDefinition.format.video.nFrameWidth; + bufferConf.nFrameHeight = pInputPort->portDefinition.format.video.nFrameHeight; + bufferConf.nStride = ALIGN(pInputPort->portDefinition.format.video.nFrameWidth, 16); + } else { + bufferConf.nFrameWidth = pInputPort->portDefinition.format.video.nFrameHeight; + bufferConf.nFrameHeight = pInputPort->portDefinition.format.video.nFrameWidth; + bufferConf.nStride = ALIGN(pInputPort->portDefinition.format.video.nFrameHeight, 16); + } + bufferConf.nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + pInbufOps->Set_Shareable(hMFCHandle); + nInputBufferCnt = 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, "Failed to set geometry for input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } + + /* setup input buffer */ + if (pInbufOps->Setup(hMFCHandle, nInputBufferCnt) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to setup input buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + + if ((pInputPort->bufferProcessType & BUFFER_SHARE) +#ifdef USE_METADATABUFFERTYPE + && (pInputPort->bStoreMetaData != OMX_TRUE) +#endif + ) { + 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 *pInputPort = &pExynosComponent->pExynosPort[INPUT_PORT_INDEX]; + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + + ExynosVideoEncOps *pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps; + ExynosVideoEncBufferOps *pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + 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->bStoreMetaData == OMX_TRUE) { + nOutBufSize = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * + pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + } + + /* 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, "Failed to set geometry for output buffer"); + 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, "Failed to setup output buffer"); + 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) + goto EXIT; + + /* Enqueue output buffer */ + for (i = 0; i < MFC_OUTPUT_BUFFER_NUM_MAX; i++) { + pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr, + (int *)pVideoEnc->pMFCEncOutputBuffer[i]->fd, + pVideoEnc->pMFCEncOutputBuffer[i]->bufferSize, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + NULL); + } + + if (pOutbufOps->Run(hMFCHandle) != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to run output buffer"); + ret = OMX_ErrorInsufficientResources; + goto EXIT; + } + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /* Register output buffer */ + /*************/ + /* TBD */ + /*************/ + } + + pVp9Enc->hMFCVp9Handle.bConfiguredMFCDst = OMX_TRUE; + + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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) + 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) + 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) + 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) + 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) + 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; + case OMX_IndexParamVideoAndroidVp9Encoder: + { + OMX_VIDEO_PARAM_ANDROID_VP9ENCODERTYPE *pDstVp9EncoderType = (OMX_VIDEO_PARAM_ANDROID_VP9ENCODERTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ANDROID_VP9ENCODERTYPE *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_VP9ENCODERTYPE)); + if (ret != OMX_ErrorNone) + 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_VP9ENCODERTYPE) - nOffset); + } + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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_ErrorBadParameter; + 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) + 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) + 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; + case OMX_IndexParamVideoAndroidVp9Encoder: + { + OMX_VIDEO_PARAM_ANDROID_VP9ENCODERTYPE *pSrcVp9EncoderType = (OMX_VIDEO_PARAM_ANDROID_VP9ENCODERTYPE *)pComponentParameterStructure; + OMX_VIDEO_PARAM_ANDROID_VP9ENCODERTYPE *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_VP9ENCODERTYPE)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pSrcVp9EncoderType->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pVp9Enc->hMFCVp9Handle.videoInstInfo.specificInfo.enc.bTemporalSvcSupport == VIDEO_FALSE) && + (pSrcVp9EncoderType->eTemporalPattern != OMX_VIDEO_VPXTemporalLayerPatternNone)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "%s: MFC D/D doesn't support Temporal SVC", __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_VP9ENCODERTYPE) - nOffset); + } + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pVp9Enc = (EXYNOS_VP9ENC_HANDLE *)pVideoEnc->hCodecHandle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%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) + 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; + default: + ret = Exynos_OMX_VideoEncodeSetConfig(hComponent, nIndex, pComponentConfigStructure); + break; + } + +EXIT: + if (ret == OMX_ErrorNone) { + OMX_PTR pDynamicConfigCMD = NULL; + pDynamicConfigCMD = Exynos_OMX_MakeDynamicConfigCMD(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) { + 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_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_PTR hMFCHandle = NULL; + OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused; + + ExynosVideoEncOps *pEncOps = NULL; + ExynosVideoEncBufferOps *pInbufOps = NULL; + ExynosVideoEncBufferOps *pOutbufOps = NULL; + ExynosVideoInstInfo *pVideoInstInfo = &(pVp9Enc->hMFCVp9Handle.videoInstInfo); + + CSC_METHOD csc_method = CSC_METHOD_SW; + + int i = 0, nPlaneCnt; + + FunctionIn(); + + pVp9Enc->hMFCVp9Handle.bConfiguredMFCSrc = OMX_FALSE; + pVp9Enc->hMFCVp9Handle.bConfiguredMFCDst = OMX_FALSE; + pVideoEnc->bFirstInput = OMX_TRUE; + pVideoEnc->bFirstOutput = OMX_FALSE; + pExynosComponent->bUseFlagEOF = OMX_TRUE; + pExynosComponent->bSaveFlagEOS = OMX_FALSE; + pExynosComponent->bBehaviorEOS = OMX_FALSE; + + eColorFormat = pInputPort->portDefinition.format.video.eColorFormat; +#ifdef USE_METADATABUFFERTYPE + if (pInputPort->bStoreMetaData == OMX_TRUE) { +#ifdef USE_ANDROIDOPAQUE + if (eColorFormat == (OMX_COLOR_FORMATTYPE)OMX_COLOR_FormatAndroidOpaque) + pInputPort->bufferProcessType = BUFFER_COPY; + else + pInputPort->bufferProcessType = BUFFER_SHARE; +#else + pInputPort->bufferProcessType = BUFFER_COPY; +#endif + } else { + pInputPort->bufferProcessType = BUFFER_COPY; + } +#else + pInputPort->bufferProcessType = BUFFER_COPY; +#endif + + 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; + + pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps; + pInbufOps = pVp9Enc->hMFCVp9Handle.pInbufOps; + pOutbufOps = pVp9Enc->hMFCVp9Handle.pOutbufOps; + hMFCHandle = pVp9Enc->hMFCVp9Handle.hMFCHandle; + + 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->hDestinationStartEvent); + + 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 = (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; + + int i = 0, plane = 0; + + FunctionIn(); + + if (pVideoEnc->csc_handle != NULL) { + csc_deinit(pVideoEnc->csc_handle); + pVideoEnc->csc_handle = NULL; + } + + Exynos_OSAL_QueueTerminate(&pVp9Enc->bypassBufferInfoQ); + + Exynos_OSAL_SignalTerminate(pVp9Enc->hDestinationStartEvent); + pVp9Enc->hDestinationStartEvent = NULL; + pVp9Enc->bDestinationStart = OMX_FALSE; + Exynos_OSAL_SignalTerminate(pVp9Enc->hSourceStartEvent); + pVp9Enc->hSourceStartEvent = NULL; + pVp9Enc->bSourceStart = OMX_FALSE; + + if (pOutputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, OUTPUT_PORT_INDEX); + Exynos_OSAL_QueueTerminate(&pOutputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pOutputPort->codecSemID); + } else if (pOutputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + if (pInputPort->bufferProcessType & BUFFER_COPY) { + Exynos_Free_CodecBuffers(pOMXComponent, INPUT_PORT_INDEX); + } else if (pInputPort->bufferProcessType & BUFFER_SHARE) { + /*************/ + /* TBD */ + /*************/ + /* Does not require any actions. */ + } + + Exynos_OSAL_QueueTerminate(&pInputPort->codecBufferQ); + Exynos_OSAL_SemaphoreTerminate(pInputPort->codecSemID); + + 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]; + 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; + + FunctionIn(); + + if (pVp9Enc->hMFCVp9Handle.bConfiguredMFCSrc == OMX_FALSE) { + ret = VP9CodecSrcSetup(pOMXComponent, pSrcInputData); + if ((pSrcInputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) + goto EXIT; + } + + if (pVp9Enc->hMFCVp9Handle.bConfiguredMFCDst == OMX_FALSE) { + ret = VP9CodecDstSetup(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + } + + while (Exynos_OSAL_GetElemNum(&pExynosComponent->dynamicConfigQ) > 0) { + Change_VP9Enc_Param(pExynosComponent); + } + + 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 timestamp %lld us (%.2f secs), Tag: %d, nFlags: 0x%x", pExynosComponent, __FUNCTION__, + pSrcInputData->timeStamp, pSrcInputData->timeStamp / 1E6, pVp9Enc->hMFCVp9Handle.indexTimestamp, pSrcInputData->nFlags); + + 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 + + /* queue work for input buffer */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "[%p][%s] oneFrameSize: %ld, bufferHeader: 0x%p", pExynosComponent, __FUNCTION__, pSrcInputData->dataLen, pSrcInputData->bufferHeader); + + inputColorFormat = Exynos_Input_GetActualColorFormat(pExynosComponent); + if ((pVideoEnc->eRotationType == ROTATE_0) || + (pVideoEnc->eRotationType == ROTATE_180)) { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + pInputPort->portDefinition.format.video.nFrameWidth, + pInputPort->portDefinition.format.video.nFrameHeight, + nDataLen, + nAllocLen); + } else { + Exynos_OSAL_GetPlaneSize(inputColorFormat, + pInputPort->ePlaneType, + pInputPort->portDefinition.format.video.nFrameHeight, + pInputPort->portDefinition.format.video.nFrameWidth, + 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 (pVideoEnc->nInbufSpareSize> 0) { + for (i = 0; i < nPlaneCnt; i++) + nAllocLen[i] = nAllocLen[i] + pVideoEnc->nInbufSpareSize; + } + + if (pSrcInputData->dataLen == 0) { + for (i = 0; i < nPlaneCnt; i++) + nDataLen[i] = 0; + } + + codecReturn = pInbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pSrcInputData->multiPlaneBuffer.dataBuffer, + (int *)pSrcInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + nPlaneCnt, + pPrivate); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - pInbufOps->Enqueue", __FUNCTION__, __LINE__); + 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->bDestinationStart = OMX_TRUE; + Exynos_OSAL_SignalSet(pVp9Enc->hDestinationStartEvent); + 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 + 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->multiPlaneBuffer.dataBuffer[0] = NULL; + pSrcOutputData->pPrivate = NULL; + } else { + int plane = 0, nPlaneCnt; + nPlaneCnt = Exynos_GetPlaneFromPort(pInputPort); + for (plane = 0; plane < nPlaneCnt; plane++) { + pSrcOutputData->multiPlaneBuffer.dataBuffer[plane] = pVideoBuffer->planes[plane].addr; + pSrcOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[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, "%s: %d: Failed - Lost buffer", __FUNCTION__, __LINE__); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + if (pInputPort->bufferProcessType == BUFFER_SHARE) + pSrcOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE*)pVideoBuffer->pPrivate; + +#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]; + + ExynosVideoEncOps *pEncOps = pVp9Enc->hMFCVp9Handle.pEncOps; + 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->multiPlaneBuffer.dataBuffer[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Failed to find input buffer"); + 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->bStoreMetaData == OMX_TRUE) + nAllocLen[0] = ALIGN(pOutputPort->portDefinition.format.video.nFrameWidth * pOutputPort->portDefinition.format.video.nFrameHeight * 3 / 2, 512); + + codecReturn = pOutbufOps->ExtensionEnqueue(hMFCHandle, + (void **)pDstInputData->multiPlaneBuffer.dataBuffer, + (int *)&pDstInputData->multiPlaneBuffer.fd, + nAllocLen, + nDataLen, + Exynos_GetPlaneFromPort(pOutputPort), + pDstInputData->bufferHeader); + if (codecReturn != VIDEO_ERROR_NONE) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - pOutbufOps->Enqueue", __FUNCTION__, __LINE__); + 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; + ExynosVideoFrameStatusType displayStatus = VIDEO_FRAME_STATUS_UNKNOWN; + 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, "HW is not available"); + pVideoBuffer = NULL; + ret = OMX_ErrorHardware; + goto EXIT; + } else { + pVideoBuffer = NULL; + ret = OMX_ErrorNone; + goto EXIT; + } + + pVp9Enc->hMFCVp9Handle.outputIndexTimestamp++; + pVp9Enc->hMFCVp9Handle.outputIndexTimestamp %= MAX_TIMESTAMP; + + pDstOutputData->multiPlaneBuffer.dataBuffer[0] = pVideoBuffer->planes[0].addr; + pDstOutputData->multiPlaneBuffer.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->multiPlaneBuffer.dataBuffer[0] == + pVideoEnc->pMFCEncOutputBuffer[i]->pVirAddr[0]) { + pDstOutputData->pPrivate = pVideoEnc->pMFCEncOutputBuffer[i]; + break; + } + } + + if (pDstOutputData->pPrivate == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Can not find buffer"); + ret = (OMX_ERRORTYPE)OMX_ErrorCodecEncode; + goto EXIT; + } + } + + /* For Share Buffer */ + pDstOutputData->bufferHeader = (OMX_BUFFERHEADERTYPE *)pVideoBuffer->pPrivate; + + if (pVideoEnc->bFirstOutput == OMX_FALSE) { + pDstOutputData->timeStamp = 0; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; + pDstOutputData->nFlags |= OMX_BUFFERFLAG_ENDOFFRAME; + pVideoEnc->bFirstOutput = OMX_TRUE; + } else { + indexTimestamp = pEncOps->Get_FrameTag(pVp9Enc->hMFCVp9Handle.hMFCHandle); + + if ((indexTimestamp < 0) || (indexTimestamp >= MAX_TIMESTAMP)) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "[%p][%s] Tag(%d) is invalid. changes to use outputIndexTimestamp(%d)", + pExynosComponent, __FUNCTION__, + indexTimestamp, pVp9Enc->hMFCVp9Handle.outputIndexTimestamp); + indexTimestamp = pVp9Enc->hMFCVp9Handle.outputIndexTimestamp; + } + + 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 timestamp %lld us (%.2f secs), Tag: %d, frameType: %d dataLen: %d", + pExynosComponent, __FUNCTION__, + pDstOutputData->timeStamp, pDstOutputData->timeStamp / 1E6, indexTimestamp, + pVideoBuffer->frameType, pDstOutputData->dataLen); + +#ifdef PERFORMANCE_DEBUG + if (pDstOutputData->bufferHeader != NULL) { + pDstOutputData->bufferHeader->nTimeStamp = pDstOutputData->timeStamp; + Exynos_OSAL_V4L2CountDecrease(pOutputPort->hBufferCount, pDstOutputData->bufferHeader, OUTPUT_PORT_INDEX); + } +#endif + + if ((displayStatus == VIDEO_FRAME_STATUS_CHANGE_RESOL) || + (((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) && + (pExynosComponent->bBehaviorEOS == OMX_FALSE))) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] displayStatus:%d, nFlags0x%x", pExynosComponent, __FUNCTION__, displayStatus, pDstOutputData->nFlags); + pDstOutputData->remainDataLen = 0; + } + + if (((pDstOutputData->nFlags & OMX_BUFFERFLAG_EOS) == OMX_BUFFERFLAG_EOS) && + (pExynosComponent->bBehaviorEOS == OMX_TRUE)) { + 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_ERROR, "%s: %d: Failed - SrcIn -> event is thrown to client", __FUNCTION__, __LINE__); + 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_SignalReset(pVp9Enc->hSourceStartEvent); + } + + ret = Exynos_VP9Enc_SrcOut(pOMXComponent, pSrcOutputData); + if ((ret != OMX_ErrorNone) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - SrcOut -> event is thrown to client", __FUNCTION__, __LINE__); + 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 (pOutputPort->bufferProcessType & BUFFER_SHARE) { + if ((pVp9Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pVp9Enc->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pVp9Enc->hDestinationStartEvent); + } + + if (Exynos_OSAL_GetElemNum(&pVp9Enc->bypassBufferInfoQ) > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] buffer with EOS will be returned by bypassBufferInfoQ", + pExynosComponent, __FUNCTION__); + + BYPASS_BUFFER_INFO *pBufferInfo = (BYPASS_BUFFER_INFO *)Exynos_OSAL_Dequeue(&pVp9Enc->bypassBufferInfoQ); + if (pBufferInfo == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + 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_ERROR, "%s: %d: Failed - DstIn -> event is thrown to client", __FUNCTION__, __LINE__); + 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 (pOutputPort->bufferProcessType & BUFFER_COPY) { + if ((pVp9Enc->bDestinationStart == OMX_FALSE) && + (!CHECK_PORT_BEING_FLUSHED(pOutputPort))) { + Exynos_OSAL_SignalWait(pVp9Enc->hDestinationStartEvent, DEF_MAX_WAIT_TIME); + if (pVideoEnc->bExitBufferProcessThread) + goto EXIT; + + Exynos_OSAL_SignalReset(pVp9Enc->hDestinationStartEvent); + } + + if (Exynos_OSAL_GetElemNum(&pVp9Enc->bypassBufferInfoQ) > 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ESSENTIAL, "[%p][%s] buffer with EOS will be returned by bypassBufferInfoQ", + pExynosComponent, __FUNCTION__); + + EXYNOS_OMX_DATABUFFER *dstOutputUseBuffer = &pOutputPort->way.port2WayDataBuffer.outputDataBuffer; + OMX_BUFFERHEADERTYPE *pOMXBuffer = NULL; + BYPASS_BUFFER_INFO *pBufferInfo = NULL; + + 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) && + (pExynosComponent->currentState == OMX_StateExecuting)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: %d: Failed - DstOut -> event is thrown to client", __FUNCTION__, __LINE__); + 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, "OMX_ErrorBadParameter, Line:%d", __LINE__); + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(EXYNOS_OMX_COMPONENT_VP9_ENC, componentName) != 0) { + ret = OMX_ErrorBadParameter; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorBadParameter, componentName:%s, Line:%d", componentName, __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)hComponent; + ret = Exynos_OMX_VideoEncodeComponentInit(pOMXComponent); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_Error, Line:%d", __LINE__); + 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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_OMX_VideoEncodeComponentDeinit(pOMXComponent); + ret = OMX_ErrorInsufficientResources; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInsufficientResources, Line:%d", __LINE__); + 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 = 8 */ + pVp9Enc->qpRangeI.nMaxQP = 63; /* index = 63, value = 255 */ + pVp9Enc->qpRangeP.nMinQP = 2; /* index = 2, value = 8 */ + 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_VP9ProfileMain; + pVp9Enc->VP9Component[i].eLevel = OMX_VIDEO_VP9Level_Version0; + } + pVp9Enc->nPFrames = -1; + + Exynos_OSAL_Memset(&pVp9Enc->AndroidVp9EncoderType, 0, sizeof(OMX_VIDEO_PARAM_ANDROID_VP9ENCODERTYPE)); + INIT_SET_SIZE_VERSION(&pVp9Enc->AndroidVp9EncoderType, OMX_VIDEO_PARAM_ANDROID_VP9ENCODERTYPE); + pVp9Enc->AndroidVp9EncoderType.nKeyFrameInterval = pVp9Enc->nPFrames + 1; + pVp9Enc->AndroidVp9EncoderType.eTemporalPattern = OMX_VIDEO_VPXTemporalLayerPatternNone; + pVp9Enc->AndroidVp9EncoderType.nTemporalLayerCount = 1; + for (i = 0; i < OMX_VIDEO_ANDROID_MAXVP9TEMPORALLAYERS; 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; + +#if 0 /* unused code */ + pVideoEnc->exynos_checkInputFrame = NULL; + pVideoEnc->exynos_codec_getCodecInputPrivateData = &GetCodecInputPrivateData; +#endif + + pVideoEnc->exynos_codec_getCodecOutputPrivateData = &GetCodecOutputPrivateData; + + pVideoEnc->exynos_codec_checkFormatSupport = &CheckFormatHWSupport; + + pVideoEnc->hSharedMemory = Exynos_OSAL_SharedMemory_Open(); + if (pVideoEnc->hSharedMemory == NULL) { + Exynos_OSAL_Free(pVp9Enc); + pVp9Enc = ((EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle)->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; + + 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 %d %d %d %d %d %d", pExynosComponent, __FUNCTION__, + (pVp9Enc->hMFCVp9Handle.videoInstInfo.specificInfo.enc.bRGBSupport), + (pVp9Enc->hMFCVp9Handle.videoInstInfo.specificInfo.enc.nSpareSize), + (pVp9Enc->hMFCVp9Handle.videoInstInfo.specificInfo.enc.bTemporalSvcSupport), + (pVp9Enc->hMFCVp9Handle.videoInstInfo.specificInfo.enc.bSkypeSupport), + (pVp9Enc->hMFCVp9Handle.videoInstInfo.specificInfo.enc.bRoiInfoSupport), + (pVp9Enc->hMFCVp9Handle.videoInstInfo.specificInfo.enc.bQpRangePBSupport)); + + if (pVp9Enc->hMFCVp9Handle.videoInstInfo.specificInfo.enc.nSpareSize > 0) + pVideoEnc->nInbufSpareSize = pVp9Enc->hMFCVp9Handle.videoInstInfo.specificInfo.enc.nSpareSize; + + Exynos_Input_SetSupportFormat(pExynosComponent); + SetProfileLevel(pExynosComponent); + + 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; + + 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; + } + + ret = Exynos_OMX_VideoEncodeComponentDeinit(pOMXComponent); + if (ret != OMX_ErrorNone) + goto EXIT; + + ret = OMX_ErrorNone; + +EXIT: + FunctionOut(); + + return ret; +} diff --git a/component/video/enc/vp9/Exynos_OMX_Vp9enc.h b/component/video/enc/vp9/Exynos_OMX_Vp9enc.h new file mode 100644 index 0000000..de87fef --- /dev/null +++ b/component/video/enc/vp9/Exynos_OMX_Vp9enc.h @@ -0,0 +1,91 @@ +/* + * + * 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; + + #define MAX_PROFILE_NUM 1 + 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_VP9ENCODERTYPE AndroidVp9EncoderType; + + /* SEC MFC Codec specific */ + EXYNOS_MFC_VP9ENC_HANDLE hMFCVp9Handle; + + OMX_BOOL bSourceStart; + OMX_BOOL bDestinationStart; + OMX_HANDLETYPE hSourceStartEvent; + OMX_HANDLETYPE hDestinationStartEvent; + + 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/component/video/enc/vp9/NOTICE b/component/video/enc/vp9/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/component/video/enc/vp9/library_register.c b/component/video/enc/vp9/library_register.c new file mode 100644 index 0000000..d74b842 --- /dev/null +++ b/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/component/video/enc/vp9/library_register.h b/component/video/enc/vp9/library_register.h new file mode 100644 index 0000000..bcb1b21 --- /dev/null +++ b/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/core/Android.mk b/core/Android.mk new file mode 100644 index 0000000..033857f --- /dev/null +++ b/core/Android.mk @@ -0,0 +1,44 @@ +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_CFLAGS := + +LOCAL_ARM_MODE := arm + +LOCAL_STATIC_LIBRARIES := libExynosOMX_OSAL libExynosOMX_Basecomponent +LOCAL_SHARED_LIBRARIES := libc libdl libcutils libutils \ + 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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +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 + +include $(BUILD_SHARED_LIBRARY) + diff --git a/core/Exynos_OMX_Component_Register.c b/core/Exynos_OMX_Component_Register.c new file mode 100644 index 0000000..b573f00 --- /dev/null +++ b/core/Exynos_OMX_Component_Register.c @@ -0,0 +1,266 @@ +/* + * + * 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" + +OMX_ERRORTYPE Exynos_OMX_Component_Register(EXYNOS_OMX_COMPONENT_REGLIST **compList, OMX_U32 *compNum) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + int componentNum = 0, roleNum = 0, totalCompNum = 0; + char *libName; + size_t len; + const char *errorMsg; + DIR *dir; + struct dirent *d; + + int (*Exynos_OMX_COMPONENT_Library_Register)(ExynosRegisterComponentType **exynosComponents); + ExynosRegisterComponentType **exynosComponentsTemp; + EXYNOS_OMX_COMPONENT_REGLIST *componentList; + + FunctionIn(); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s lib is loaded", (IS_64BIT_OS? "64bit":"32bit")); + dir = opendir((IS_64BIT_OS? + EXYNOS_OMX64_INSTALL_PATH : EXYNOS_OMX_INSTALL_PATH)); + if (dir == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + componentList = (EXYNOS_OMX_COMPONENT_REGLIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_COMPONENT_REGLIST) * MAX_OMX_COMPONENT_NUM); + Exynos_OSAL_Memset(componentList, 0, sizeof(EXYNOS_OMX_COMPONENT_REGLIST) * MAX_OMX_COMPONENT_NUM); + libName = Exynos_OSAL_Malloc(MAX_OMX_COMPONENT_LIBNAME_SIZE); + + while ((d = readdir(dir)) != NULL) { + OMX_HANDLETYPE soHandle; + + if (Exynos_OSAL_Strncmp(d->d_name, "libOMX.Exynos.", Exynos_OSAL_Strlen("libOMX.Exynos.")) == 0) { + Exynos_OSAL_Memset(libName, 0, MAX_OMX_COMPONENT_LIBNAME_SIZE); + Exynos_OSAL_Strcpy(libName, (IS_64BIT_OS? EXYNOS_OMX64_INSTALL_PATH : EXYNOS_OMX_INSTALL_PATH)); + Exynos_OSAL_Strcat(libName, d->d_name); + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "Loading the library: %s", 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) { + int i = 0; + unsigned int j = 0; + + componentNum = (*Exynos_OMX_COMPONENT_Library_Register)(NULL); + exynosComponentsTemp = (ExynosRegisterComponentType **)Exynos_OSAL_Malloc(sizeof(ExynosRegisterComponentType*) * componentNum); + for (i = 0; i < componentNum; i++) { + exynosComponentsTemp[i] = Exynos_OSAL_Malloc(sizeof(ExynosRegisterComponentType)); + Exynos_OSAL_Memset(exynosComponentsTemp[i], 0, sizeof(ExynosRegisterComponentType)); + } + (*Exynos_OMX_COMPONENT_Library_Register)(exynosComponentsTemp); + + for (i = 0; i < componentNum; i++) { + Exynos_OSAL_Strcpy(componentList[totalCompNum].component.componentName, exynosComponentsTemp[i]->componentName); + for (j = 0; j < 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]); + } + + Exynos_OSAL_Free(exynosComponentsTemp); + } else { + if ((errorMsg = Exynos_OSAL_dlerror()) != NULL) + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "dlsym failed: %s", errorMsg); + } + Exynos_OSAL_dlclose(soHandle); + } else { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "dlopen failed: %s", Exynos_OSAL_dlerror()); + } + } else { + /* not a component name line. skip */ + continue; + } + } + + Exynos_OSAL_Free(libName); + + closedir(dir); + + *compList = componentList; + *compNum = totalCompNum; + +EXIT: + 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; + OMX_COMPONENTTYPE *pOMXComponent; + + 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) { + ret = OMX_ErrorInvalidComponentName; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInvalidComponentName, Line:%d", __LINE__); + goto EXIT; + } + + Exynos_OMX_ComponentInit = Exynos_OSAL_dlsym(libHandle, "Exynos_OMX_ComponentInit"); + if (!Exynos_OMX_ComponentInit) { + Exynos_OSAL_dlclose(libHandle); + ret = OMX_ErrorInvalidComponent; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "OMX_ErrorInvalidComponent, Line:%d", __LINE__); + goto EXIT; + } + + pOMXComponent = (OMX_COMPONENTTYPE *)Exynos_OSAL_Malloc(sizeof(OMX_COMPONENTTYPE)); + 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]Exynos_OMX_ComponentInit() is failed(%d)", __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, "OMX_ErrorInvalidComponent, Line:%d", __LINE__); + 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/core/Exynos_OMX_Component_Register.h b/core/Exynos_OMX_Component_Register.h new file mode 100644 index 0000000..1860978 --- /dev/null +++ b/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/core/Exynos_OMX_Core.c b/core/Exynos_OMX_Core.c new file mode 100644 index 0000000..2119e73 --- /dev/null +++ b/core/Exynos_OMX_Core.c @@ -0,0 +1,416 @@ +/* + * + * 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, "Exynos_OMX_Init : %s", "OMX_ErrorInsufficientResources"); + goto EXIT; + } + + ret = Exynos_OMX_ResourceManager_Init(); + if (OMX_ErrorNone != ret) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Exynos_OMX_Init : Exynos_OMX_ResourceManager_Init failed"); + goto EXIT; + } + + ret = Exynos_OSAL_MutexCreate(&ghLoadComponentListMutex); + if (OMX_ErrorNone != ret) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Exynos_OMX_Init : Exynos_OSAL_MutexCreate(&ghLoadComponentListMutex) failed"); + goto EXIT; + } + + gInitialized = 1; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "Exynos_OMX_Init : %s", "OMX_ErrorNone"); + } + + 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)) { + 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, "ComponentName : %s", 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)); + 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, "OMX_Error, Line:%d", __LINE__); + 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, "OMX_Error, Line:%d", __LINE__); + 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); + 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, "Exynos_OMX_GetHandle : %s", "OMX_ErrorNone"); + 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; + OMX_STRING RoleString[MAX_OMX_COMPONENT_ROLE_SIZE]; + 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; +} diff --git a/core/Exynos_OMX_Core.h b/core/Exynos_OMX_Core.h new file mode 100644 index 0000000..09d578e --- /dev/null +++ b/core/Exynos_OMX_Core.h @@ -0,0 +1,78 @@ +/* + * + * 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/core/NOTICE b/core/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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/include/exynos/Exynos_OMX_Def.h b/include/exynos/Exynos_OMX_Def.h new file mode 100644 index 0000000..3fdf668 --- /dev/null +++ b/include/exynos/Exynos_OMX_Def.h @@ -0,0 +1,850 @@ +/* + * + * 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" + +#define VERSIONMAJOR_NUMBER 1 +#define VERSIONMINOR_NUMBER 1 +#define REVISION_NUMBER 2 +#define STEP_NUMBER 0 + +#define RESOURCE_VIDEO_DEC 16 +#define RESOURCE_VIDEO_ENC 16 +#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 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 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)) +#define EXYNOS_OMX_INSTALL_PATH "/system/lib/omx/" +#define EXYNOS_OMX64_INSTALL_PATH "/system/lib64/omx/" + +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_PARAM_THUMBNAIL "OMX.SEC.index.ThumbnailMode" + OMX_IndexVendorThumbnailMode = 0x7F000001, + +#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" + OMX_IndexVendorNeedContigMemory = 0x7F000004, + +#define EXYNOS_INDEX_CONFIG_GET_BUFFER_FD "OMX.SEC.index.GetBufferFD" + OMX_IndexVendorGetBufferFD = 0x7F000005, + +#define EXYNOS_INDEX_PARAM_SET_DTS_MODE "OMX.SEC.index.SetDTSMode" + OMX_IndexVendorSetDTSMode = 0x7F000006, + +#define EXYNOS_INDEX_CONFIG_SET_QOS_RATIO "OMX.SEC.index.SetQosRatio" + OMX_IndexVendorSetQosRatio = 0x7F000007, + + /* for Android Native Window */ +#define EXYNOS_INDEX_PARAM_ENABLE_ANB "OMX.google.android.index.enableAndroidNativeBuffers" + OMX_IndexParamEnableAndroidBuffers = 0x7F000011, + +#define EXYNOS_INDEX_PARAM_GET_ANB "OMX.google.android.index.getAndroidNativeBufferUsage" + OMX_IndexParamGetAndroidNativeBuffer = 0x7F000012, + +#define EXYNOS_INDEX_PARAM_USE_ANB "OMX.google.android.index.useAndroidNativeBuffer" + OMX_IndexParamUseAndroidNativeBuffer = 0x7F000013, + + /* for Android Store Metadata Inbuffer */ +#define EXYNOS_INDEX_PARAM_STORE_METADATA_BUFFER "OMX.google.android.index.storeMetaDataInBuffers" + OMX_IndexParamStoreMetaDataBuffer = 0x7F000014, + + /* prepend SPS/PPS to I/IDR for H.264 Encoder */ +#define EXYNOS_INDEX_PARAM_PREPEND_SPSPPS_TO_IDR "OMX.google.android.index.prependSPSPPSToIDRFrames" + OMX_IndexParamPrependSPSPPSToIDR = 0x7F000015, + +#ifdef USE_KHRONOS_OMX_HEADER + /* VP8 Codec */ +#if 0 /* USE_VP8_SUPPORT : these are declared in OMX_IndexExt.h */ +#define EXYNOS_INDEX_PARAM_VIDEO_VP8_TYPE "OMX.SEC.index.VideoVp8Type" + OMX_IndexParamVideoVp8 = 0x7F000016, + +#define EXYNOS_INDEX_CONFIG_VIDEO_VP8_REFERENCEFRAME "OMX.SEC.index.VideoVp8ReferenceFrame" + OMX_IndexConfigVideoVp8ReferenceFrame = 0x7F000017, + +#define EXYNOS_INDEX_CONFIG_VIDEO_VP8_REFERENCEFRAMETYPE "OMX.SEC.index.VideoVp8ReferenceFrameType" + OMX_IndexConfigVideoVp8ReferenceFrameType = 0x7F000018, +#endif // USE_VP8_SUPPORT + + /* HEVC Codec */ +#ifdef USE_HEVC_SUPPORT +#define EXYNOS_INDEX_PARAM_VIDEO_HEVC_TYPE "OMX.SEC.index.VideoHevcType" + OMX_IndexParamVideoHevc = 0x7F000019, +#endif // USE_HEVC_SUPPORT + +#endif // USE_KHRONOS_OMX_HEADER + + /* Thumbnail */ +#define EXYNOS_INDEX_PARAM_ENABLE_THUMBNAIL "OMX.SEC.index.enableThumbnailMode" + OMX_IndexParamEnableThumbnailMode = 0x7F000020, + + /* Android Native Buffer */ +#define EXYNOS_INDEX_PARAM_USE_ANB2 "OMX.google.android.index.useAndroidNativeBuffer2" + OMX_IndexParamUseAndroidNativeBuffer2 = 0x7F000021, + + /* QP control */ +#define EXYNOS_INDEX_PARAM_VIDEO_QPRANGE_TYPE "OMX.SEC.indexParam.VideoQPRange" + OMX_IndexParamVideoQPRange = 0x7F000022, + +#define EXYNOS_INDEX_CONFIG_VIDEO_QPRANGE_TYPE "OMX.SEC.indexConfig.VideoQPRange" + OMX_IndexConfigVideoQPRange = 0x7F000023, + +#ifdef USE_KHRONOS_OMX_HEADER + /* VP8 Codec */ +#ifdef USE_VP8_SUPPORT +#define EXYNOS_INDEX_PARAM_VIDEO_ANDROID_VP8_ENCODER "OMX.SEC.index.VideoAndroidVP8Encoder" + OMX_IndexParamVideoAndroidVp8Encoder = 0x7F000024, +#endif // USE_VP8_SUPPORT + +#define EXYNOS_INDEX_PARAM_SLICE_SEGMENTS "OMX.SEC.index.SliceSegments" + OMX_IndexParamSliceSegments = 0x7F000025, + +#endif // USE_KHRONOS_OMX_HEADER + + /* Temporal SVC */ +#define EXYNOS_INDEX_CONFIG_VIDEO_TEMPORALSVC "OMX.SEC.index.TemporalSVC" + OMX_IndexConfigVideoTemporalSVC = 0x7F000026, + +#define EXYNOS_INDEX_PARAM_VIDEO_AVC_ENABLE_TEMPORALSVC "OMX.SEC.index.AVC.enableTemporalSVC" + OMX_IndexParamVideoAVCEnableTemporalSVC = 0x7F000027, + + /* VC1 Codec */ +#ifndef USE_KHRONOS_OMX_1_2 +#define EXYNOS_INDEX_PARAM_VIDEO_VC1_TYPE "OMX.SEC.index.VideoVc1Type" + OMX_IndexParamVideoVC1 = 0x7F000028, +#endif + +//#ifdef USE_KHRONOS_OMX_HEADER + /* VP9 Codec */ +#ifdef USE_VP9_SUPPORT +#define EXYNOS_INDEX_PARAM_VIDEO_VP9_TYPE "OMX.SEC.index.VideoVp9Type" + OMX_IndexParamVideoVp9 = 0x7F000029, + +#define EXYNOS_INDEX_CONFIG_VIDEO_VP9_REFERENCEFRAME "OMX.SEC.index.VideoVp9ReferenceFrame" + OMX_IndexConfigVideoVp9ReferenceFrame = 0x7F000030, + +#define EXYNOS_INDEX_CONFIG_VIDEO_VP9_REFERENCEFRAMETYPE "OMX.SEC.index.VideoVp9ReferenceFrameType" + OMX_IndexConfigVideoVp9ReferenceFrameType = 0x7F000031, + +#define EXYNOS_INDEX_PARAM_VIDEO_ANDROID_VP9_ENCODER "OMX.SEC.index.VideoAndroidVP9Encoder" + OMX_IndexParamVideoAndroidVp9Encoder = 0x7F000032, +#endif // USE_VP9_SUPPORT +//#endif // USE_KHRONOS_OMX_HEADER + + /* blur filtering */ +#define EXYNOS_INDEX_PARAM_ENABLE_BLUR_FILTER "OMX.SEC.indexParam.enableBlurFilter" + OMX_IndexParamEnableBlurFilter = 0x7F000033, +#define EXYNOS_INDEX_CONFIG_BLUR_INFO "OMX.SEC.indexConfig.BlurInfo" + OMX_IndexConfigBlurInfo = 0x7F000034, + +#define EXYNOS_INDEX_PARAM_VIDEO_HEVC_ENABLE_TEMPORALSVC "OMX.SEC.index.Hevc.enableTemporalSVC" + OMX_IndexParamVideoHevcEnableTemporalSVC = 0x7F000035, + + /* ROI Information */ +#define EXYNOS_INDEX_CONFIG_VIDEO_ROIINFO "OMX.SEC.index.RoiInfo" + OMX_IndexConfigVideoRoiInfo = 0x7F000036, +#define EXYNOS_INDEX_PARAM_VIDEO_ENABLE_ROIINFO "OMX.SEC.index.enableRoiInfo" + OMX_IndexParamVideoEnableRoiInfo = 0x7F000037, + + /* rotation about encoder's input */ +#define EXYNOS_INDEX_PARAM_ROATION_INFO "OMX.SEC.indexParam.RotationInfo" + OMX_IndexParamRotationInfo = 0x7F000038, + +#define EXYNOS_INDEX_CONFIG_OPERATING_RATE "OMX.SEC.index.OperatingRate" +#ifdef USE_KHRONOS_OMX_HEADER + OMX_IndexConfigOperatingRate = 0x7F000039, +#endif + + /* for custom component(MSRND) */ + OMX_IndexExynosStartUnused = 0x7F050000, /* Reserved region for Exynos Extensions */ + +#define EXYNOS_CUSTOM_INDEX_CONFIG_PTS_MODE "OMX.SEC.CUSTOM.index.PTSMode" + OMX_IndexExynosConfigPTSMode = 0x7F050001, /* to support PTS Video TimeStamp - OMX_BOOL */ +#define EXYNOS_CUSTOM_INDEX_CONFIG_DISPLAY_DELAY "OMX.SEC.CUSTOM.index.DisplayDelay" + OMX_IndexExynosConfigDisplayDelay = 0x7F050002, /* to support H264 DisplayDelay Setting - OMX_U32 */ + /* Timestamp reorder */ +#define EXYNOS_CUSTOM_INDEX_PARAM_REORDER_MODE "OMX.SEC.CUSTOM.index.ReorderMode" + OMX_IndexExynosParamReorderMode = 0x7F050003, +#define EXYNOS_CUSTOM_INDEX_PARAM_CORRUPTEDHEADER "OMX.SEC.CUSTOM.index.CorruptedHeader" + OMX_IndexExynosParamCorruptedHeader = 0x7F050004, + + + /* for Skype HD Common */ +#define OMX_MS_SKYPE_PARAM_DRIVERVER "OMX.microsoft.skype.index.driverversion" + OMX_IndexSkypeParamDriverVersion = 0x7F060001, + /* for Skype HD Decode */ +#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, + /* for Skype HD Encode */ +#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, +#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, +#define OMX_MS_SKYPE_CONFIG_TEMPORALLAYERCOUNT "OMX.microsoft.skype.index.temporallayercount" + OMX_IndexSkypeConfigTemporalLayerCount = 0x7F060009, +#define OMX_MS_SKYPE_CONFIG_BASELAYERPID "OMX.microsoft.skype.index.basepid" + OMX_IndexSkypeConfigBasePid = 0x7F06000a, + + 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) 0x90000012, + OMX_ErrorNoneExpiration = (OMX_S32) 0x90000013, +} EXYNOS_OMX_ERRORTYPE; + +typedef enum _EXYNOS_OMX_COMMANDTYPE +{ + EXYNOS_OMX_CommandComponentDeInit = 0x7F000001, + EXYNOS_OMX_CommandEmptyBuffer, + EXYNOS_OMX_CommandFillBuffer, + EXYNOS_OMX_CommandFakeBuffer +} 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_COLOR_FORMATTYPE { + OMX_SEC_COLOR_FormatNV12TPhysicalAddress = 0x7F000001, /**< Reserved region for introducing Vendor Extensions */ + OMX_SEC_COLOR_FormatNV12LPhysicalAddress = 0x7F000002, + OMX_SEC_COLOR_FormatNV12LVirtualAddress = 0x7F000003, +#ifdef USE_KHRONOS_OMX_HEADER + OMX_SEC_COLOR_FormatNV12Tiled = 0x7FC00002, /* 0x7FC00002 */ +#endif + OMX_SEC_COLOR_FormatNV21LPhysicalAddress = 0x7F000010, + OMX_SEC_COLOR_FormatNV21Linear = 0x7F000011, + OMX_SEC_COLOR_FormatYVU420Planar = 0x7F000012, + OMX_SEC_COLOR_Format32bitABGR8888 = 0x7F000013, /* unused */ + OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace = 0x7F000014, + OMX_SEC_COLOR_Format10bitYUV420SemiPlanar = 0x7F000015, + + /* to copy a encoded data for drm component using gsc or fimc */ + OMX_SEC_COLOR_FormatEncodedData = OMX_COLOR_FormatYCbYCr, +#ifdef USE_KHRONOS_OMX_HEADER + /* for Android SurfaceMediaSource*/ + OMX_COLOR_FormatAndroidOpaque = 0x7F000789, + OMX_COLOR_Format32BitRGBA8888 = 0x7F00A000, +#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_METADATA = 0x04, + BUFFER_ANBSHARE = 0x08, +} 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_S3D_SUPPORT + OMX_EventS3DInformation, +#endif +} EXYNOS_OMX_EVENTTYPE; + +typedef enum _EXYNOS_ANB_TYPE { + NATIVE_GRAPHIC_BUFFER1, + NATIVE_GRAPHIC_BUFFER2, +} EXYNOS_ANB_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_VIDEO_THUMBNAILMODE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bEnable; +} EXYNOS_OMX_VIDEO_THUMBNAILMODE; + +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_PARAM_DTSMODE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bDTSMode; +} EXYNOS_OMX_VIDEO_PARAM_DTSMODE; + +typedef struct _EXYNOS_OMX_VIDEO_PARAM_REORDERMODE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bReorderMode; +} EXYNOS_OMX_VIDEO_PARAM_REORDERMODE; + +typedef struct _EXYNOS_OMX_VIDEO_PARAM_CORRUPTEDHEADER { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_BOOL bDiscardEvent; +} EXYNOS_OMX_VIDEO_PARAM_CORRUPTEDHEADER; + +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_CONFIG_QOSINFO { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nQosRatio; +} EXYNOS_OMX_VIDEO_CONFIG_QOSINFO; + +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; + +/* 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_ANDROID_MAXAVCTEMPORALLAYERS 7 +#define OMX_VIDEO_ANDROID_MAXHEVCTEMPORALLAYERS 7 + +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_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; + +/* for AVC */ +typedef enum EXYNOS_OMX_VIDEO_AVCPROFILETYPE { + OMX_VIDEO_AVCProfileConstrainedBaseline = 0x7F000001, + OMX_VIDEO_AVCProfileConstrainedHigh = 0x7F000002, +} EXYNOS_OMX_VIDEO_AVCPROFILETYPE; + +#ifdef USE_KHRONOS_OMX_HEADER +typedef enum EXYNOS_OMX_VIDEO_AVCLEVELTYPE { + OMX_VIDEO_AVCLevel52 = 0x10000, /**< Level 5.2 */ +} EXYNOS_OMX_VIDEO_AVCLEVELTYPE; +#endif + +/* for Ext-Codec support */ +typedef enum EXYNOS_OMX_VIDEO_CODINGTYPE { +#ifdef USE_KHRONOS_OMX_HEADER + OMX_VIDEO_CodingHEVC = 0x7F000002, /**< ITU H.265/HEVC */ + OMX_VIDEO_CodingVP9 = 0x7F000003, /**< Google VP9 */ +#endif + OMX_VIDEO_VendorCodingMAX = 0x7FFFFFFF, +} EXYNOS_OMX_VIDEO_CODINGTYPE; + +typedef enum _EXYNOS_OMX_HIERARCHICAL_CODING_TYPE +{ + EXYNOS_OMX_Hierarchical_P = 0x00, + EXYNOS_OMX_Hierarchical_B, +} EXYNOS_OMX_HIERARCHICAL_CODING_TYPE; + +#ifdef USE_KHRONOS_OMX_HEADER + +#if defined(USE_VP8_SUPPORT) || defined(USE_VP9_SUPPORT) +/** 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; +#endif + + /* VP8 Codec */ +#ifdef USE_VP8_SUPPORT +/** Maximum number of VP8 temporal layers */ +#define OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS 3 + +/** + * Android specific VP8 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; + 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; +#endif // USE_VP8_SUPPORT + + /* HEVC codec */ +#ifdef USE_HEVC_SUPPORT +/** HEVC Profile enum type */ +typedef enum OMX_VIDEO_HEVCPROFILETYPE { + OMX_VIDEO_HEVCProfileUnknown = 0x0, + OMX_VIDEO_HEVCProfileMain = 0x01, /**< Main profile */ + OMX_VIDEO_HEVCProfileMain10 = 0x02, /**< Main 10 profile */ + OMX_VIDEO_HEVCProfileMainStillPicture = 0x04, /**< Main Still Picture */ + 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_VIDEO_PARAM_HEVCTYPE; + +#endif // USE_HEVC_SUPPORT + +/** 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; + +#endif // USE_KHRONOS_OMX_HEADER + +//#ifdef USE_KHRONOS_OMX_HEADER + /* VP9 Codec */ +#ifdef USE_VP9_SUPPORT + /* VP9 profiles */ +typedef enum OMX_VIDEO_VP9PROFILETYPE { + OMX_VIDEO_VP9ProfileMain = 0x00000001, + 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_VP9Level_Version0 = 0x00000001, + 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; + + /* VP9 param */ +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; + + /* VP9 reference frames */ +typedef struct OMX_VIDEO_VP9REFERENCEFRAMETYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL nPreviousFrameRefresh; + OMX_BOOL bGoldenFrameRefresh; + OMX_BOOL bAlternateFrameRefresh; + OMX_BOOL bUsePreviousFrame; + OMX_BOOL bUseGoldenFrame; + OMX_BOOL bUseAlternateFrame; +} OMX_VIDEO_VP9REFERENCEFRAMETYPE; + + /* VP9 reference frame type */ +typedef struct OMX_VIDEO_VP9REFERENCEFRAMEINFOTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_BOOL bIsIntraFrame; + OMX_BOOL bIsGoldenOrAlternateFrame; +} OMX_VIDEO_VP9REFERENCEFRAMEINFOTYPE; + +/** Maximum number of VP9 temporal layers */ +#define OMX_VIDEO_ANDROID_MAXVP9TEMPORALLAYERS 3 + +/** + * Android specific 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_VP9ENCODERTYPE { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nKeyFrameInterval; + OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE eTemporalPattern; + OMX_U32 nTemporalLayerCount; + OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_ANDROID_MAXVP9TEMPORALLAYERS]; + OMX_U32 nMinQuantizer; + OMX_U32 nMaxQuantizer; +} OMX_VIDEO_PARAM_ANDROID_VP9ENCODERTYPE; +#endif // USE_VP9_SUPPORT +//#endif // USE_KHRONOS_OMX_HEADER + +#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 + +#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/include/exynos/Exynos_OMX_Macros.h b/include/exynos/Exynos_OMX_Macros.h new file mode 100644 index 0000000..ef49d95 --- /dev/null +++ b/include/exynos/Exynos_OMX_Macros.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_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. + */ +#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)) + +#define GET_2B_SIZE(w, h) (ALIGN(w / 4, 16) * ALIGN(h, 16) + 64) +#define GET_10B_Y_SIZE(w, h) (GET_Y_SIZE(w, h) + GET_2B_SIZE(w, h)) +#define GET_10B_UV_SIZE(w, h) (GET_UV_SIZE(w, h) + GET_2B_SIZE(w, h / 2)) +#define GET_10B_CB_SIZE(w, h) (GET_CB_SIZE(w, h) + GET_2B_SIZE(w, h / 2)) +#define GET_10B_CR_SIZE(w, h) (GET_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 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->bIsPortFlushed == OMX_TRUE) +#define CHECK_PORT_BEING_DISABLED(port) (port->bIsPortDisabled == OMX_TRUE) +#define CHECK_PORT_BEING_FLUSHED_OR_DISABLED(port) ((port->bIsPortFlushed == OMX_TRUE) || (port->bIsPortDisabled == OMX_TRUE)) +#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/include/khronos/OMX_Audio.h b/include/khronos/OMX_Audio.h new file mode 100644 index 0000000..04f1a99 --- /dev/null +++ b/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/include/khronos/OMX_Component.h b/include/khronos/OMX_Component.h new file mode 100644 index 0000000..d595640 --- /dev/null +++ b/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/include/khronos/OMX_ComponentExt.h b/include/khronos/OMX_ComponentExt.h new file mode 100644 index 0000000..3a5eeb5 --- /dev/null +++ b/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/include/khronos/OMX_ContentPipe.h b/include/khronos/OMX_ContentPipe.h new file mode 100644 index 0000000..5f6310c --- /dev/null +++ b/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/include/khronos/OMX_Core.h b/include/khronos/OMX_Core.h new file mode 100644 index 0000000..a076f2f --- /dev/null +++ b/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/include/khronos/OMX_CoreExt.h b/include/khronos/OMX_CoreExt.h new file mode 100644 index 0000000..1241168 --- /dev/null +++ b/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/include/khronos/OMX_IVCommon.h b/include/khronos/OMX_IVCommon.h new file mode 100644 index 0000000..4c4995c --- /dev/null +++ b/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/include/khronos/OMX_Image.h b/include/khronos/OMX_Image.h new file mode 100644 index 0000000..a6d4666 --- /dev/null +++ b/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/include/khronos/OMX_ImageExt.h b/include/khronos/OMX_ImageExt.h new file mode 100644 index 0000000..664a084 --- /dev/null +++ b/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/include/khronos/OMX_Index.h b/include/khronos/OMX_Index.h new file mode 100644 index 0000000..44d4ea7 --- /dev/null +++ b/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/include/khronos/OMX_Other.h b/include/khronos/OMX_Other.h new file mode 100644 index 0000000..caf7f38 --- /dev/null +++ b/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/include/khronos/OMX_Types.h b/include/khronos/OMX_Types.h new file mode 100644 index 0000000..8698358 --- /dev/null +++ b/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/include/khronos/OMX_Video.h b/include/khronos/OMX_Video.h new file mode 100644 index 0000000..163e450 --- /dev/null +++ b/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/include/khronos/OMX_VideoExt.h b/include/khronos/OMX_VideoExt.h new file mode 100644 index 0000000..c5a338a --- /dev/null +++ b/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/include/skype/OMX_Video_Extensions.h b/include/skype/OMX_Video_Extensions.h new file mode 100644 index 0000000..eef2193 --- /dev/null +++ b/include/skype/OMX_Video_Extensions.h @@ -0,0 +1,187 @@ +/*@@@+++@@@@****************************************************************** + + Microsoft Skype Engineering + Copyright (C) 2014 Microsoft Corporation. + +MIT License + +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. + +*@@@---@@@@******************************************************************/ + + +#ifndef __OMX_VIDEO_EXTENSIONS_H__ +#define __OMX_VIDEO_EXTENSIONS_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#define OMX_VIDEO_MajorVersion 2 +#define OMX_VIDEO_MinorVersion 0 +#pragma pack(push, 1) + +typedef enum OMX_VIDEO_SliceControlMode +{ + OMX_VIDEO_SliceControlModeNone = 0, + OMX_VIDEO_SliceControlModeMB = 1, + OMX_VIDEO_SliceControlModeByte = 2, + OMX_VIDEO_SliceControlModMBRow = 3, +} OMX_VIDEO_SliceControlMode; + +typedef enum OMX_VIDEO_DownScaleFactor +{ + OMX_VIDEO_DownScaleFactor_1_1 = 0, + OMX_VIDEO_DownScaleFactor_Equal_AR = 1, + OMX_VIDEO_DownScaleFactor_Any = 2, +} OMX_VIDEO_DownScaleFactor; + +typedef enum OMX_VIDEO_HierarType +{ + OMX_VIDEO_HierarType_P = 0x01, + OMX_VIDEO_HierarType_B = 0x02, +} OMX_VIDEO_HierarType; + +typedef enum OMX_VIDEO_EXTENSION_AVCPROFILETYPE +{ + OMX_VIDEO_EXT_AVCProfileConstrainedBaseline = 0x01, + OMX_VIDEO_EXT_AVCProfileConstrainedHigh = 0x02, +} OMX_VIDEO_EXTENSION_AVCPROFILETYPE; + +typedef struct OMX_VIDEO_ENCODERPARAMS { + OMX_BOOL bLowLatency; + OMX_BOOL bUseExtendedProfile; + OMX_BOOL bSequenceHeaderWithIDR; + OMX_VIDEO_EXTENSION_AVCPROFILETYPE eProfile; + OMX_U32 nLTRFrames; + OMX_VIDEO_HierarType eHierarType; + OMX_U32 nMaxTemporalLayerCount; + OMX_VIDEO_SliceControlMode eSliceControlMode; + OMX_U32 nSarIndex; + OMX_U32 nSarWidth; + OMX_U32 nSarHeight; +} OMX_VIDEO_ENCODERPARAMS; + +typedef struct OMX_VIDEO_ENCODERCAP { + OMX_BOOL bLowLatency; + OMX_U32 nMaxFrameWidth; + OMX_U32 nMaxFrameHeight; + OMX_U32 nMaxInstances; + OMX_U32 nMaxTemporaLayerCount; + OMX_U32 nMaxRefFrames; + OMX_U32 nMaxLTRFrames; + OMX_VIDEO_AVCLEVELTYPE nMaxLevel; + OMX_U32 nSliceControlModesBM; + OMX_U32 nMaxMacroblockProcessingRate; + OMX_VIDEO_DownScaleFactor nResize; + OMX_U32 xMinScaleFactor; +} OMX_VIDEO_ENCODERCAP; + +typedef struct OMX_VIDEO_PARAM_ENCODERSETTING { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_ENCODERPARAMS stEncParam; +} OMX_VIDEO_PARAM_ENCODERSETTING; + +typedef struct OMX_VIDEO_PARAM_ENCODERCAP { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_ENCODERCAP stEncCap; +} OMX_VIDEO_PARAM_ENCODERCAP; + +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_TEMPORALLAYERCOUNT { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U32 nTemporalLayerCount; +} OMX_VIDEO_CONFIG_TEMPORALLAYERCOUNT; + +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_VIDEO_DECODERPARAMS { + OMX_BOOL bLowLatency; +} OMX_VIDEO_DECODERPARAMS; + +typedef struct OMX_VIDEO_DECODERCAP { + OMX_BOOL bLowLatency; + OMX_U32 nMaxFrameWidth; + OMX_U32 nMaxFrameHeight; + OMX_U32 nMaxInstances; + OMX_VIDEO_AVCLEVELTYPE nMaxLevel; + OMX_U32 nMaxMacroblockProcessingRate; +} OMX_VIDEO_DECODERCAP; + +typedef struct OMX_VIDEO_PARAM_DECODERSETTING { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_DECODERPARAMS stDecParam; +} OMX_VIDEO_PARAM_DECODERSETTING; + +typedef struct OMX_VIDEO_PARAM_DECODERCAP { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_VIDEO_DECODERCAP stDecoderCap; +} OMX_VIDEO_PARAM_DECODERCAP; + +typedef struct OMX_VIDEO_PARAM_DRIVERVER { + OMX_U32 nSize; + OMX_VERSIONTYPE nVersion; + OMX_U32 nPortIndex; + OMX_U64 nDriverVersion; +} OMX_VIDEO_PARAM_DRIVERVER; + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/osal/Android.mk b/osal/Android.mk new file mode 100644 index 0000000..6bee8bc --- /dev/null +++ b/osal/Android.mk @@ -0,0 +1,187 @@ +LOCAL_PATH := $(call my-dir) + +ifeq ($(BOARD_USE_SKYPE_HD), true) + +################################# +#### libExynosOMX_SkypeHD_Enc ### +################################# +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libExynosOMX_SkypeHD_Enc + +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_INC)/skype \ + $(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/$(TARGET_SOC)/include \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_STATIC_LIBRARY) + +################################# +#### libExynosOMX_SkypeHD_Dec ### +################################# +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE := libExynosOMX_SkypeHD_Dec + +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_INC)/skype \ + $(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/$(TARGET_SOC)/include \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_STATIC_LIBRARY) +endif # for Skype HD + + +########################## +#### libExynosOMX_OSAL ### +########################## +include $(CLEAR_VARS) + +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_CFLAGS := + +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_SRC_FILES += \ + Exynos_OSAL_Android.cpp +endif + +ifeq ($(BOARD_USE_ANB), true) +LOCAL_CFLAGS += -DUSE_ANB + +ifeq ($(BOARD_USE_ANB_OUTBUF_SHARE), true) +LOCAL_CFLAGS += -DUSE_ANB_OUTBUF_SHARE +endif +endif + +ifeq ($(BOARD_USE_DMA_BUF), true) +LOCAL_CFLAGS += -DUSE_DMA_BUF +endif + +ifeq ($(BOARD_USE_METADATABUFFERTYPE), true) +LOCAL_CFLAGS += -DUSE_METADATABUFFERTYPE + +ifeq ($(BOARD_USE_STOREMETADATA), true) +LOCAL_CFLAGS += -DUSE_STOREMETADATA +endif + +ifeq ($(BOARD_USE_ANDROIDOPAQUE), true) +LOCAL_CFLAGS += -DUSE_ANDROIDOPAQUE +endif +endif + +ifeq ($(BOARD_USE_IMPROVED_BUFFER), true) +LOCAL_CFLAGS += -DUSE_IMPROVED_BUFFER +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 + +ifeq ($(TARGET_BOARD_PLATFORM),exynos3) +LOCAL_CFLAGS += -DUSE_MFC5X_ALIGNMENT +endif + +ifeq ($(TARGET_BOARD_PLATFORM),exynos4) +LOCAL_CFLAGS += -DUSE_MFC5X_ALIGNMENT +endif + +LOCAL_SHARED_LIBRARIES := libhardware +LOCAL_STATIC_LIBRARIES := liblog libcutils libExynosVideoApi + +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/$(TARGET_SOC)/include \ + $(TOP)/hardware/samsung_slsi/$(TARGET_BOARD_PLATFORM)/include \ + $(TOP)/hardware/samsung_slsi/exynos/include + +ifeq ($(BOARD_USE_ANDROID), true) +LOCAL_C_INCLUDES += \ + $(ANDROID_MEDIA_INC)/hardware \ + $(TOP)/system/core/libion/include +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_C_INCLUDES += $(ANDROID_MEDIA_INC)/openmax +endif +endif + +include $(BUILD_STATIC_LIBRARY) diff --git a/osal/Exynos_OSAL_Android.cpp b/osal/Exynos_OSAL_Android.cpp new file mode 100644 index 0000000..2402479 --- /dev/null +++ b/osal/Exynos_OSAL_Android.cpp @@ -0,0 +1,1330 @@ +/* + * 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 +#ifdef USE_DMA_BUF +#include +#endif + +#include +#include "exynos_ion.h" + +#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_Android.h" +#include "Exynos_OSAL_ETC.h" +#include "exynos_format.h" + +#include "ExynosVideoApi.h" + +#undef EXYNOS_LOG_TAG +#define EXYNOS_LOG_TAG "Exynos_OSAL_Android" +//#define EXYNOS_LOG_OFF +#include "Exynos_OSAL_Log.h" + +using namespace android; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _EXYNOS_OMX_SHARED_BUFFER { + OMX_S32 bufferFd; + OMX_S32 bufferFd1; + OMX_S32 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; + OMX_PTR pGrallocModule; + EXYNOS_OMX_SHARED_BUFFER SharedBuffer[MAX_BUFFER_REF]; +} EXYNOS_OMX_REF_HANDLE; + +static int lockCnt = 0; + +int getIonFd(gralloc_module_t const *module) +{ + private_module_t* m = const_cast(reinterpret_cast(module)); + return m->ionfd; +} + +OMX_ERRORTYPE setBufferProcessTypeForDecoder(EXYNOS_OMX_BASEPORT *pExynosPort) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (pExynosPort == NULL) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + +#ifdef USE_ANB_OUTBUF_SHARE + if (pExynosPort->bufferProcessType & BUFFER_ANBSHARE) { + 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; + } + } + pExynosPort->bufferProcessType = BUFFER_SHARE; + + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "output buffer sharing mode is on (%x)", pExynosPort->portDefinition.format.video.eColorFormat); + } else +#endif + if (pExynosPort->bufferProcessType & BUFFER_COPY) { + if (pExynosPort->bStoreMetaData == OMX_TRUE) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: bufferProcessType is invalid", __FUNCTION__); + goto EXIT; + } + + pExynosPort->bufferProcessType = BUFFER_COPY; + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + } + +EXIT: + return ret; +} + +void resetBufferProcessTypeForDecoder(EXYNOS_OMX_BASEPORT *pExynosPort) +{ + int i; + + if (pExynosPort == NULL) + return; + + pExynosPort->bufferProcessType = (EXYNOS_OMX_BUFFERPROCESS_TYPE)(BUFFER_COPY | BUFFER_ANBSHARE); + pExynosPort->portDefinition.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; + + return; +} + +OMX_ERRORTYPE Exynos_OSAL_LockANBHandle( + 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 OMX_PTR planes) +{ + FunctionIn(); + + OMX_ERRORTYPE ret = OMX_ErrorNone; + GraphicBufferMapper &mapper = GraphicBufferMapper::get(); + buffer_handle_t bufferHandle = (buffer_handle_t) handle; +#ifdef USE_DMA_BUF + private_handle_t *priv_hnd = (private_handle_t *) bufferHandle; +#endif + Rect bounds((uint32_t)width, (uint32_t)height); + ExynosVideoPlane *vplanes = (ExynosVideoPlane *) planes; + void *vaddr[MAX_BUFFER_PLANE] = {NULL, }; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: handle: 0x%x, format = %x", __FUNCTION__, handle, priv_hnd->format); + + int usage = 0; + switch ((int)format) { + case OMX_COLOR_FormatYUV420Planar: + case OMX_COLOR_FormatYUV420SemiPlanar: + case OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace: + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanar: + case OMX_SEC_COLOR_FormatNV12Tiled: + usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; + break; +#ifdef USE_ANDROIDOPAQUE + case OMX_COLOR_FormatAndroidOpaque: + { + OMX_COLOR_FORMATTYPE formatType; + formatType = Exynos_OSAL_GetANBColorFormat(priv_hnd); + if ((formatType == OMX_COLOR_FormatYUV420SemiPlanar) || + (formatType == (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatNV12Tiled)) + usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; + else + usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_VIDEO_ENCODER; + } + break; +#endif + default: + usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN; + break; + } + + if (mapper.lock(bufferHandle, usage, bounds, vaddr) != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: mapper.lock() fail", __func__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + lockCnt++; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: lockCnt:%d", __func__, lockCnt); + +#ifdef USE_DMA_BUF + vplanes[0].fd = priv_hnd->fd; + vplanes[0].offset = 0; + vplanes[1].fd = priv_hnd->fd1; + vplanes[1].offset = 0; + vplanes[2].fd = priv_hnd->fd2; + vplanes[2].offset = 0; +#endif + + if (priv_hnd->flags & GRALLOC_USAGE_PROTECTED) { + /* in case of DRM, vaddrs are invalid */ + vplanes[0].addr = INT_TO_PTR(priv_hnd->fd); + vplanes[1].addr = INT_TO_PTR(priv_hnd->fd1); + vplanes[2].addr = INT_TO_PTR(priv_hnd->fd2); + } else { + vplanes[0].addr = vaddr[0]; + vplanes[1].addr = vaddr[1]; + vplanes[2].addr = vaddr[2]; + } + + if ((priv_hnd->format == HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_PRIV) && + (vaddr[2] != NULL)) + vplanes[2].addr = vaddr[2]; + + *pStride = (OMX_U32)priv_hnd->stride; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: buffer locked: 0x%x", __func__, *vaddr); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_UnlockANBHandle(OMX_IN OMX_PTR handle) +{ + FunctionIn(); + + OMX_ERRORTYPE ret = OMX_ErrorNone; + GraphicBufferMapper &mapper = GraphicBufferMapper::get(); + buffer_handle_t bufferHandle = (buffer_handle_t) handle; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: handle: 0x%x", __func__, handle); + + if (mapper.unlock(bufferHandle) != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: mapper.unlock() fail", __func__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + lockCnt--; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: lockCnt:%d", __func__, lockCnt); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: buffer unlocked: 0x%x", __func__, handle); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_COLOR_FORMATTYPE Exynos_OSAL_GetANBColorFormat(OMX_IN OMX_PTR handle) +{ + FunctionIn(); + + OMX_COLOR_FORMATTYPE ret = OMX_COLOR_FormatUnused; + private_handle_t *priv_hnd = (private_handle_t *) handle; + + ret = Exynos_OSAL_HAL2OMXColorFormat(priv_hnd->format); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "ColorFormat: 0x%x", ret); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_LockMetaData( + OMX_IN OMX_PTR pBuffer, + OMX_IN OMX_U32 width, + OMX_IN OMX_U32 height, + OMX_IN OMX_COLOR_FORMATTYPE format, + OMX_OUT OMX_U32 *pStride, + OMX_OUT OMX_PTR planes) +{ + FunctionIn(); + + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_PTR pBuf = NULL; + + ret = Exynos_OSAL_GetInfoFromMetaData((OMX_BYTE)pBuffer, &pBuf); + if (ret == OMX_ErrorNone) + ret = Exynos_OSAL_LockANBHandle(pBuf, width, height, format, pStride, planes); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_UnlockMetaData(OMX_IN OMX_PTR pBuffer) +{ + FunctionIn(); + + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_PTR pBuf = NULL; + + ret = Exynos_OSAL_GetInfoFromMetaData((OMX_BYTE)pBuffer, &pBuf); + if (ret == OMX_ErrorNone) + ret = Exynos_OSAL_UnlockANBHandle(pBuf); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_HANDLETYPE Exynos_OSAL_RefANB_Create() +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_REF_HANDLE *phREF = NULL; + gralloc_module_t *module = NULL; + + int i = 0; + + FunctionIn(); + + phREF = (EXYNOS_OMX_REF_HANDLE *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_REF_HANDLE)); + if (phREF == NULL) + goto EXIT; + + Exynos_OSAL_Memset(phREF, 0, sizeof(EXYNOS_OMX_REF_HANDLE)); + for (i = 0; i < MAX_BUFFER_REF; i++) { + phREF->SharedBuffer[i].bufferFd = -1; + phREF->SharedBuffer[i].bufferFd1 = -1; + phREF->SharedBuffer[i].bufferFd2 = -1; + } + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&module) != 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: hw_get_module(GRALLOC_HARDWARE_MODULE_ID) fail", __func__); + ret = OMX_ErrorUndefined; + goto EXIT; + } + + phREF->pGrallocModule = (OMX_PTR)module; + + ret = Exynos_OSAL_MutexCreate(&phREF->hMutex); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Free(phREF); + phREF = NULL; + } + +EXIT: + FunctionOut(); + + return ((OMX_HANDLETYPE)phREF); +} + +OMX_ERRORTYPE Exynos_OSAL_RefANB_Reset(OMX_HANDLETYPE hREF) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_REF_HANDLE *phREF = (EXYNOS_OMX_REF_HANDLE *)hREF; + gralloc_module_t *module = NULL; + + int i = 0; + + FunctionIn(); + + if (phREF == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + module = (gralloc_module_t *)phREF->pGrallocModule; + + Exynos_OSAL_MutexLock(phREF->hMutex); + + for (i = 0; i < MAX_BUFFER_REF; i++) { + if (phREF->SharedBuffer[i].bufferFd > -1) { + while(phREF->SharedBuffer[i].cnt > 0) { + if (phREF->SharedBuffer[i].ionHandle != -1) + ion_free(getIonFd(module), phREF->SharedBuffer[i].ionHandle); + if (phREF->SharedBuffer[i].ionHandle1 != -1) + ion_free(getIonFd(module), phREF->SharedBuffer[i].ionHandle1); + if (phREF->SharedBuffer[i].ionHandle2 != -1) + ion_free(getIonFd(module), phREF->SharedBuffer[i].ionHandle2); + phREF->SharedBuffer[i].cnt--; + } + phREF->SharedBuffer[i].bufferFd = -1; + phREF->SharedBuffer[i].bufferFd1 = -1; + phREF->SharedBuffer[i].bufferFd2 = -1; + phREF->SharedBuffer[i].ionHandle = -1; + phREF->SharedBuffer[i].ionHandle1 = -1; + phREF->SharedBuffer[i].ionHandle2 = -1; + } + } + Exynos_OSAL_MutexUnlock(phREF->hMutex); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_RefANB_Terminate(OMX_HANDLETYPE hREF) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_REF_HANDLE *phREF = (EXYNOS_OMX_REF_HANDLE *)hREF; + + FunctionIn(); + + if (phREF == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + Exynos_OSAL_RefANB_Reset(phREF); + + phREF->pGrallocModule = NULL; + + 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_RefANB_Increase( + OMX_HANDLETYPE hREF, + OMX_PTR pBuffer, + PLANE_TYPE ePlaneType) +{ + 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 = (buffer_handle_t)pBuffer; + private_handle_t *priv_hnd = (private_handle_t *)bufferHandle; + gralloc_module_t *module = NULL; + + 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) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + eColorFormat = Exynos_OSAL_HAL2OMXColorFormat(priv_hnd->format); + if (eColorFormat == OMX_COLOR_FormatUnused) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + + nPlaneCnt = Exynos_OSAL_GetPlaneCount(eColorFormat, ePlaneType); + module = (gralloc_module_t *)phREF->pGrallocModule; + + Exynos_OSAL_MutexLock(phREF->hMutex); + + if ((priv_hnd->fd >= 0) && + (nPlaneCnt >= 1)) { + if (ion_import(getIonFd(module), priv_hnd->fd, &ionHandle) < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_import is failed(client:%d, fd:%d)", getIonFd(module), priv_hnd->fd); + ionHandle = -1; + } + } + + if ((priv_hnd->fd1 >= 0) && + (nPlaneCnt >= 2)) { + if (ion_import(getIonFd(module), priv_hnd->fd1, &ionHandle1) < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_import is failed(client:%d, fd1:%d)", getIonFd(module), priv_hnd->fd1); + ionHandle1 = -1; + } + } + + if ((priv_hnd->fd2 >= 0) && + (nPlaneCnt == 3)) { + if (ion_import(getIonFd(module), priv_hnd->fd2, &ionHandle2) < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion_import is failed(client:%d, fd2:%d)", getIonFd(module), priv_hnd->fd2); + ionHandle2 = -1; + } + } + + for (i = 0; i < MAX_BUFFER_REF; i++) { + if (phREF->SharedBuffer[i].bufferFd == priv_hnd->fd) { + phREF->SharedBuffer[i].cnt++; + break; + } + } + + if (i >= MAX_BUFFER_REF) { + for (i = 0; i < MAX_BUFFER_REF; i++) { + if (phREF->SharedBuffer[i].bufferFd == -1) { + phREF->SharedBuffer[i].bufferFd = priv_hnd->fd; + phREF->SharedBuffer[i].bufferFd1 = priv_hnd->fd1; + phREF->SharedBuffer[i].bufferFd2 = priv_hnd->fd2; + 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, "inc fd:%d cnt:%d", phREF->SharedBuffer[i].bufferFd, phREF->SharedBuffer[i].cnt); + Exynos_OSAL_MutexUnlock(phREF->hMutex); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_RefANB_Decrease(OMX_HANDLETYPE hREF, OMX_S32 bufferFd) +{ + + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_REF_HANDLE *phREF = (EXYNOS_OMX_REF_HANDLE *)hREF; + gralloc_module_t *module = NULL; + + int i; + + FunctionIn(); + + if ((phREF == NULL) || (bufferFd < 0)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + module = (gralloc_module_t *)phREF->pGrallocModule; + + Exynos_OSAL_MutexLock(phREF->hMutex); + + for (i = 0; i < MAX_BUFFER_REF; i++) { + if (phREF->SharedBuffer[i].bufferFd == bufferFd) { + if (phREF->SharedBuffer[i].ionHandle != -1) + ion_free(getIonFd(module), phREF->SharedBuffer[i].ionHandle); + if (phREF->SharedBuffer[i].ionHandle1 != -1) + ion_free(getIonFd(module), phREF->SharedBuffer[i].ionHandle1); + if (phREF->SharedBuffer[i].ionHandle2 != -1) + ion_free(getIonFd(module), phREF->SharedBuffer[i].ionHandle2); + phREF->SharedBuffer[i].cnt--; + + if (phREF->SharedBuffer[i].cnt == 0) { + phREF->SharedBuffer[i].bufferFd = -1; + phREF->SharedBuffer[i].bufferFd1 = -1; + phREF->SharedBuffer[i].bufferFd2 = -1; + phREF->SharedBuffer[i].ionHandle = -1; + phREF->SharedBuffer[i].ionHandle1 = -1; + phREF->SharedBuffer[i].ionHandle2 = -1; + } + break; + } + } + + if (i >= MAX_BUFFER_REF) { + ret = OMX_ErrorUndefined; + Exynos_OSAL_MutexUnlock(phREF->hMutex); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "dec fd:%d cnt:%d", phREF->SharedBuffer[i].bufferFd, phREF->SharedBuffer[i].cnt); + Exynos_OSAL_MutexUnlock(phREF->hMutex); + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE useAndroidNativeBuffer( + EXYNOS_OMX_BASEPORT *pExynosPort, + OMX_BUFFERHEADERTYPE **ppBufferHdr, + OMX_U32 nPortIndex, + OMX_PTR pAppPrivate, + OMX_U32 nSizeBytes, + OMX_U8 *pBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + OMX_BUFFERHEADERTYPE *temp_bufferHeader = NULL; + unsigned int i = 0; + OMX_U32 width, height; + OMX_U32 stride; + ExynosVideoPlane planes[MAX_BUFFER_PLANE]; + + FunctionIn(); + + if (pExynosPort == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + if (pExynosPort->portState != OMX_StateIdle) { + 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) { + 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); + if (pExynosPort->eANBType == NATIVE_GRAPHIC_BUFFER1) { + android_native_buffer_t *pANB = (android_native_buffer_t *)pBuffer; + temp_bufferHeader->pBuffer = (OMX_U8 *)pANB->handle; + } else { + temp_bufferHeader->pBuffer = (OMX_U8 *)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; + + width = pExynosPort->portDefinition.format.video.nFrameWidth; + height = pExynosPort->portDefinition.format.video.nFrameHeight; + Exynos_OSAL_LockANBHandle(temp_bufferHeader->pBuffer, width, height, + pExynosPort->portDefinition.format.video.eColorFormat, + &stride, planes); +#ifdef USE_DMA_BUF + pExynosPort->extendBufferHeader[i].buf_fd[0] = planes[0].fd; + pExynosPort->extendBufferHeader[i].buf_fd[1] = planes[1].fd; + pExynosPort->extendBufferHeader[i].buf_fd[2] = planes[2].fd; +#endif + pExynosPort->extendBufferHeader[i].pYUVBuf[0] = planes[0].addr; + pExynosPort->extendBufferHeader[i].pYUVBuf[1] = planes[1].addr; + pExynosPort->extendBufferHeader[i].pYUVBuf[2] = planes[2].addr; + Exynos_OSAL_UnlockANBHandle(temp_bufferHeader->pBuffer); + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "useAndroidNativeBuffer: buf %d pYUVBuf[0]:0x%x , pYUVBuf[1]:0x%x ", + i, pExynosPort->extendBufferHeader[i].pYUVBuf[0], + pExynosPort->extendBufferHeader[i].pYUVBuf[1]); + + 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_OSAL_GetAndroidParameter( + OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + 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 (pExynosComponent->currentState == OMX_StateInvalid) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (ComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + switch ((int)nIndex) { +#ifdef USE_ANB + case OMX_IndexParamGetAndroidNativeBuffer: + { + GetAndroidNativeBufferUsageParams *pANBParams = (GetAndroidNativeBufferUsageParams *) ComponentParameterStructure; + OMX_U32 portIndex = pANBParams->nPortIndex; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: OMX_IndexParamGetAndroidNativeBuffer", __func__); + + ret = Exynos_OMX_Check_SizeVersion(pANBParams, sizeof(GetAndroidNativeBufferUsageParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_Check_SizeVersion(GetAndroidNativeBufferUsageParams) is failed", __func__); + 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 |= (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP); +#if defined(USE_IMPROVED_BUFFER) && !defined(USE_CSC_HW) && !defined(USE_NON_CACHED_GRAPHICBUFFER) + pANBParams->nUsage |= (GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); +#endif +#if defined(USE_MFC5X_ALIGNMENT) + if ((pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX].bufferProcessType & BUFFER_SHARE) && + (pExynosComponent->pExynosPort[INPUT_PORT_INDEX].portDefinition.format.video.eCompressionFormat == OMX_VIDEO_CodingAVC)) { + pANBParams->nUsage |= GRALLOC_USAGE_PRIVATE_0; + } +#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 */ + pANBParams->nUsage |= GRALLOC_USAGE_PROTECTED_DPB; /* try to use a CMA area */ + } + } + } + break; + case OMX_IndexParamConsumerUsageBits: + { + OMX_U32 *pUsageBits = (OMX_U32 *)ComponentParameterStructure; + + switch ((int)pExynosComponent->codecType) { + case HW_VIDEO_ENC_CODEC: + (*pUsageBits) = GRALLOC_USAGE_HW_VIDEO_ENCODER; + break; + case HW_VIDEO_ENC_SECURE_CODEC: + (*pUsageBits) = GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_PROTECTED; + break; + default: + (*pUsageBits) = 0; + ret = OMX_ErrorUnsupportedIndex; + break; + } + } + break; +#endif + default: + { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Unsupported index (%d)", __func__, nIndex); + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_SetAndroidParameter( + 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 (pExynosComponent->currentState == OMX_StateInvalid ) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + if (ComponentParameterStructure == NULL) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + switch ((int)nIndex) { +#ifdef USE_ANB + case OMX_IndexParamEnableAndroidBuffers: + { + EnableAndroidNativeBuffersParams *pANBParams = (EnableAndroidNativeBuffersParams *) ComponentParameterStructure; + OMX_U32 portIndex = pANBParams->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: OMX_IndexParamEnableAndroidNativeBuffers", __func__); + + ret = Exynos_OMX_Check_SizeVersion(pANBParams, sizeof(EnableAndroidNativeBuffersParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_Check_SizeVersion(EnableAndroidNativeBuffersParams) is failed", __func__); + 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; + } + + if (pExynosPort->bStoreMetaData != OMX_TRUE) { + if (portIndex == OUTPUT_PORT_INDEX) { + if (pANBParams->enable == OMX_TRUE) { + ret = setBufferProcessTypeForDecoder(pExynosPort); + if (ret != OMX_ErrorNone) + goto EXIT; + } else if ((pANBParams->enable == OMX_FALSE) && + (pExynosPort->bIsANBEnabled == OMX_TRUE)) { + /* reset to initialized value */ + resetBufferProcessTypeForDecoder(pExynosPort); + } + } + + pExynosPort->bIsANBEnabled = pANBParams->enable; + } + } + break; + + case OMX_IndexParamUseAndroidNativeBuffer: + { + UseAndroidNativeBufferParams *pANBParams = (UseAndroidNativeBufferParams *) ComponentParameterStructure; + OMX_U32 portIndex = pANBParams->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + android_native_buffer_t *pANB; + OMX_U32 nSizeBytes; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: OMX_IndexParamUseAndroidNativeBuffer, portIndex: %d", __func__, portIndex); + + ret = Exynos_OMX_Check_SizeVersion(pANBParams, sizeof(UseAndroidNativeBufferParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_Check_SizeVersion(UseAndroidNativeBufferParams) is failed", __func__); + 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; + } + + if (pExynosPort->portState != OMX_StateIdle) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Port state should be IDLE", __func__); + ret = OMX_ErrorIncorrectStateOperation; + goto EXIT; + } + + pANB = pANBParams->nativeBuffer.get(); + + /* MALI alignment restriction */ + nSizeBytes = ALIGN(pANB->width, 16) * ALIGN(pANB->height, 16); + nSizeBytes += ALIGN(pANB->width / 2, 16) * ALIGN(pANB->height / 2, 16) * 2; + + ret = useAndroidNativeBuffer(pExynosPort, + pANBParams->bufferHeader, + pANBParams->nPortIndex, + pANBParams->pAppPrivate, + nSizeBytes, + (OMX_U8 *) pANB); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: useAndroidNativeBuffer is failed: err=0x%x", __func__,ret); + goto EXIT; + } + } + break; +#endif + +#ifdef USE_STOREMETADATA + case OMX_IndexParamStoreMetaDataBuffer: + { + StoreMetaDataInBuffersParams *pMetaParams = (StoreMetaDataInBuffersParams *)ComponentParameterStructure; + OMX_U32 portIndex = pMetaParams->nPortIndex; + EXYNOS_OMX_BASEPORT *pExynosPort = NULL; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s: OMX_IndexParamStoreMetaDataBuffer", __func__); + + ret = Exynos_OMX_Check_SizeVersion(pMetaParams, sizeof(StoreMetaDataInBuffersParams)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Exynos_OMX_Check_SizeVersion(StoreMetaDataInBuffersParams) is failed", __func__); + 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)) { + EXYNOS_OMX_BASEPORT *pOutputPort = &pExynosComponent->pExynosPort[OUTPUT_PORT_INDEX]; + if ((portIndex == INPUT_PORT_INDEX) || + (pOutputPort->bDynamicDPBMode == OMX_FALSE)) { + ret = OMX_ErrorUndefined; + goto EXIT; + } + } + + pExynosPort = &pExynosComponent->pExynosPort[portIndex]; + if (CHECK_PORT_TUNNELED(pExynosPort) && CHECK_PORT_BUFFER_SUPPLIER(pExynosPort)) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if (((pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) || + (pExynosComponent->codecType == HW_VIDEO_DEC_SECURE_CODEC)) && + (portIndex == OUTPUT_PORT_INDEX)) { + if (pMetaParams->bStoreMetaData == OMX_TRUE) { + pExynosPort->bStoreMetaData = pMetaParams->bStoreMetaData; + ret = setBufferProcessTypeForDecoder(pExynosPort); + } else if ((pMetaParams->bStoreMetaData == OMX_FALSE) && + (pExynosPort->bStoreMetaData == OMX_TRUE)) { + /* reset to initialized value */ + resetBufferProcessTypeForDecoder(pExynosPort); + } + } + + pExynosPort->bStoreMetaData = pMetaParams->bStoreMetaData; + } + break; +#endif + + default: + { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: Unsupported index (%d)", __func__, nIndex); + ret = OMX_ErrorUnsupportedIndex; + goto EXIT; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_GetInfoFromMetaData(OMX_IN OMX_BYTE pBuffer, + OMX_OUT OMX_PTR *ppBuf) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + MetadataBufferType type; + + FunctionIn(); + +/* + * meta data contains the following data format. + * payload depends on the MetadataBufferType + * --------------------------------------------------------------- + * | MetadataBufferType | payload | + * --------------------------------------------------------------- + * + * If MetadataBufferType is kMetadataBufferTypeCameraSource, then + * --------------------------------------------------------------- + * | kMetadataBufferTypeCameraSource | addr. of Y | addr. of UV | + * --------------------------------------------------------------- + * + * If MetadataBufferType is kMetadataBufferTypeGrallocSource, then + * --------------------------------------------------------------- + * | kMetadataBufferTypeGrallocSource | buffer_handle_t | + * --------------------------------------------------------------- + */ + + /* MetadataBufferType */ + Exynos_OSAL_Memcpy(&type, (MetadataBufferType *)pBuffer, sizeof(MetadataBufferType)); + + switch ((int)type) { + case kMetadataBufferTypeCameraSource: + { + void *pAddress = NULL; + + /* Address. of Y */ + Exynos_OSAL_Memcpy(&pAddress, pBuffer + sizeof(MetadataBufferType), sizeof(void *)); + ppBuf[0] = (void *)pAddress; + + /* Address. of CbCr */ + Exynos_OSAL_Memcpy(&pAddress, pBuffer + sizeof(MetadataBufferType) + sizeof(void *), sizeof(void *)); + ppBuf[1] = (void *)pAddress; + + if ((ppBuf[0] == NULL) || (ppBuf[1] == NULL)) + ret = OMX_ErrorBadParameter; + } + break; + case kMetadataBufferTypeGrallocSource: + { + buffer_handle_t pBufHandle; + + /* buffer_handle_t */ + Exynos_OSAL_Memcpy(&pBufHandle, pBuffer + sizeof(MetadataBufferType), sizeof(buffer_handle_t)); + ppBuf[0] = (OMX_PTR)pBufHandle; + + if (ppBuf[0] == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "GrallocBuffer's pHandle is NULL"); + ret = OMX_ErrorBadParameter; + } + } + break; + default: + { + ret = OMX_ErrorBadParameter; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_GetBufferFdFromMetaData( + OMX_IN OMX_BYTE pBuffer, + OMX_OUT OMX_PTR *ppBuf) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + MetadataBufferType type = kMetadataBufferTypeInvalid; + + FunctionIn(); + + /* MetadataBufferType */ + Exynos_OSAL_Memcpy(&type, (MetadataBufferType *)pBuffer, sizeof(MetadataBufferType)); + + switch ((int)type) { + case kMetadataBufferTypeCameraSource: + { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d - Unsupport Type of MetadataBuffer", __FUNCTION__, __LINE__); + } + break; + case kMetadataBufferTypeGrallocSource: + { + VideoGrallocMetadata *pMetaData = (VideoGrallocMetadata *)pBuffer; + buffer_handle_t bufferHandle = (buffer_handle_t)pMetaData->pHandle; + native_handle_t *pNativeHandle = (native_handle_t *)bufferHandle; + + /* ION FD. */ + ppBuf[0] = INT_TO_PTR(pNativeHandle->data[0]); + } + break; + default: + { + ret = OMX_ErrorBadParameter; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_SetDataLengthToMetaData( + OMX_IN OMX_BYTE pBuffer, + OMX_IN OMX_U32 dataLength) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + MetadataBufferType type = kMetadataBufferTypeInvalid; + + FunctionIn(); + + /* MetadataBufferType */ + Exynos_OSAL_Memcpy(&type, (MetadataBufferType *)pBuffer, sizeof(MetadataBufferType)); + + switch ((int)type) { + case kMetadataBufferTypeCameraSource: + { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d - Unsupport Type of MetadataBuffer", __FUNCTION__, __LINE__); + } + break; + case kMetadataBufferTypeGrallocSource: + { + VideoGrallocMetadata *pMetaData = (VideoGrallocMetadata *)pBuffer; + buffer_handle_t bufferHandle = (buffer_handle_t)pMetaData->pHandle; + native_handle_t *pNativeHandle = (native_handle_t *)bufferHandle; + + /* size of stream */ + pNativeHandle->data[3] = dataLength; + } + break; + default: + { + ret = OMX_ErrorBadParameter; + } + break; + } + +EXIT: + FunctionOut(); + + return ret; +} + +OMX_PTR Exynos_OSAL_AllocMetaDataBuffer( + OMX_HANDLETYPE hSharedMemory, + EXYNOS_CODEC_TYPE codecType, + OMX_U32 nPortIndex, + OMX_U32 nSizeBytes, + MEMORY_TYPE eMemoryType) +{ + /* + * meta data contains the following data format. + * payload depends on the MetadataBufferType + * --------------------------------------------------------------- + * | MetadataBufferType | payload | + * --------------------------------------------------------------- + * If MetadataBufferType is kMetadataBufferTypeGrallocSource, then + * --------------------------------------------------------------- + * | kMetadataBufferTypeGrallocSource | buffer_handle_t | + * --------------------------------------------------------------- + */ + +#define ENC_OUT_FD_NUM 1 +#define EXTRA_DATA_NUM 3 + + VideoGrallocMetadata *pMetaData = NULL; + buffer_handle_t bufferHandle = NULL; + native_handle_t *pNativeHandle = NULL; + + OMX_PTR pTempBuffer = NULL; + OMX_PTR pTempVirAdd = NULL; + OMX_U32 nTempFD = 0; + + if (((codecType == HW_VIDEO_ENC_CODEC) || + (codecType == HW_VIDEO_ENC_SECURE_CODEC)) && + (nPortIndex == OUTPUT_PORT_INDEX)) { + pTempBuffer = Exynos_OSAL_Malloc(MAX_METADATA_BUFFER_SIZE); + if (pTempBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d - Error InsufficientResources", __FUNCTION__, __LINE__); + goto EXIT; + } + + pNativeHandle = native_handle_create(ENC_OUT_FD_NUM, EXTRA_DATA_NUM); + if (pNativeHandle == NULL) { + Exynos_OSAL_Free(pTempBuffer); + pTempBuffer = NULL; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d - Error InsufficientResources", __FUNCTION__, __LINE__); + goto EXIT; + } + + pTempVirAdd = Exynos_OSAL_SharedMemory_Alloc(hSharedMemory, nSizeBytes, eMemoryType); + if (pTempVirAdd == NULL) { + native_handle_delete(pNativeHandle); + pNativeHandle = NULL; + Exynos_OSAL_Free(pTempBuffer); + pTempBuffer = NULL; + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d - Error InsufficientResources", __FUNCTION__, __LINE__); + goto EXIT; + } + + nTempFD = Exynos_OSAL_SharedMemory_VirtToION(hSharedMemory, pTempVirAdd); + + pNativeHandle->data[0] = (int)nTempFD; + pNativeHandle->data[1] = PTR_TO_INT(pTempVirAdd); /* caution : data loss & FIXME : remove */ + pNativeHandle->data[2] = (int)nSizeBytes; + pNativeHandle->data[3] = (int)0; + + pMetaData = (VideoGrallocMetadata *)pTempBuffer; + bufferHandle = (buffer_handle_t)pNativeHandle; + + pMetaData->eType = kMetadataBufferTypeGrallocSource; + pMetaData->pHandle = bufferHandle; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d - Unsupport MetadataBuffer", __FUNCTION__, __LINE__); + pTempBuffer = NULL; + } + +EXIT: + return pTempBuffer; +} + +OMX_ERRORTYPE Exynos_OSAL_FreeMetaDataBuffer( + OMX_HANDLETYPE hSharedMemory, + EXYNOS_CODEC_TYPE codecType, + OMX_U32 nPortIndex, + OMX_PTR pTempBuffer) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + + OMX_U32 nTempFD = 0; + OMX_PTR pTempVirAdd = NULL; + + VideoGrallocMetadata *pMetaData = NULL; + buffer_handle_t bufferHandle = NULL; + native_handle_t *pNativeHandle = NULL; + + if (((codecType == HW_VIDEO_ENC_CODEC) || + (codecType == HW_VIDEO_ENC_SECURE_CODEC)) && + (nPortIndex == OUTPUT_PORT_INDEX)) { + if (*(MetadataBufferType *)(pTempBuffer) != (MetadataBufferType)kMetadataBufferTypeGrallocSource) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d - Invalid MetaDataBuffer", __FUNCTION__, __LINE__); + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pMetaData = (VideoGrallocMetadata *)pTempBuffer; + bufferHandle = (buffer_handle_t)pMetaData->pHandle; + pNativeHandle = (native_handle_t *)bufferHandle; + + nTempFD = (OMX_U32)pNativeHandle->data[0]; + pTempVirAdd = Exynos_OSAL_SharedMemory_IONToVirt(hSharedMemory, nTempFD); + + Exynos_OSAL_SharedMemory_Free(hSharedMemory, pTempVirAdd); + + native_handle_delete(pNativeHandle); + + Exynos_OSAL_Free(pTempBuffer); + + ret = OMX_ErrorNone; + } else { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s : %d - Unsupport MetadataBuffer", __FUNCTION__, __LINE__); + ret = OMX_ErrorNotImplemented; + } + +EXIT: + 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: Exynos_OMX_Check_SizeVersion(PrependSPSPPSToIDRFramesParams) is failed", __func__); + 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_TRACE, "DisplayExtraBufferCount is 3. The OTF exist"); + return 3; /* Display System has OTF */ + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "DisplayExtraBufferCount is 2. The OTF not exist"); + return 2; /* min count */ +} + +#ifdef __cplusplus +} +#endif diff --git a/osal/Exynos_OSAL_Android.h b/osal/Exynos_OSAL_Android.h new file mode 100644 index 0000000..016b861 --- /dev/null +++ b/osal/Exynos_OSAL_Android.h @@ -0,0 +1,98 @@ +/* + * 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_OSAL_SharedMemory.h" + +#ifdef __cplusplus +extern "C" { +#endif + +OMX_ERRORTYPE Exynos_OSAL_GetAndroidParameter(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_INOUT OMX_PTR ComponentParameterStructure); + +OMX_ERRORTYPE Exynos_OSAL_SetAndroidParameter(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_INDEXTYPE nIndex, + OMX_IN OMX_PTR ComponentParameterStructure); + +OMX_COLOR_FORMATTYPE Exynos_OSAL_GetANBColorFormat(OMX_IN OMX_PTR handle); + +OMX_ERRORTYPE Exynos_OSAL_LockMetaData(OMX_IN OMX_PTR pBuffer, + OMX_IN OMX_U32 width, + OMX_IN OMX_U32 height, + OMX_IN OMX_COLOR_FORMATTYPE format, + OMX_OUT OMX_U32 *pStride, + OMX_OUT OMX_PTR planes); + +OMX_ERRORTYPE Exynos_OSAL_UnlockMetaData(OMX_IN OMX_PTR pBuffer); + +OMX_ERRORTYPE Exynos_OSAL_LockANBHandle(OMX_IN OMX_PTR pBuffer, + OMX_IN OMX_U32 width, + OMX_IN OMX_U32 height, + OMX_IN OMX_COLOR_FORMATTYPE format, + OMX_OUT OMX_U32 *pStride, + OMX_OUT OMX_PTR planes); + +OMX_HANDLETYPE Exynos_OSAL_RefANB_Create(); +OMX_ERRORTYPE Exynos_OSAL_RefANB_Reset(OMX_HANDLETYPE hREF); +OMX_ERRORTYPE Exynos_OSAL_RefANB_Terminate(OMX_HANDLETYPE hREF); +OMX_ERRORTYPE Exynos_OSAL_RefANB_Increase(OMX_HANDLETYPE hREF, OMX_PTR pBuffer, PLANE_TYPE ePlaneType); +OMX_ERRORTYPE Exynos_OSAL_RefANB_Decrease(OMX_HANDLETYPE hREF, OMX_S32 bufferFd); + +OMX_ERRORTYPE Exynos_OSAL_UnlockANBHandle(OMX_IN OMX_PTR pBuffer); + +OMX_ERRORTYPE Exynos_OSAL_GetInfoFromMetaData(OMX_IN OMX_BYTE pBuffer, + OMX_OUT OMX_PTR *pOutBuffer); +OMX_ERRORTYPE Exynos_OSAL_GetBufferFdFromMetaData(OMX_IN OMX_BYTE pBuffer, OMX_OUT OMX_PTR *pOutBuffer); + +OMX_PTR Exynos_OSAL_AllocMetaDataBuffer(OMX_HANDLETYPE hSharedMemory, EXYNOS_CODEC_TYPE codecType, OMX_U32 nPortIndex, OMX_U32 nSizeBytes, MEMORY_TYPE eMemoryType); +OMX_ERRORTYPE Exynos_OSAL_FreeMetaDataBuffer(OMX_HANDLETYPE hSharedMemory, EXYNOS_CODEC_TYPE codecType, OMX_U32 nPortIndex, OMX_PTR pTempBuffer); +OMX_ERRORTYPE Exynos_OSAL_SetDataLengthToMetaData(OMX_IN OMX_BYTE pBuffer, OMX_IN OMX_U32 dataLength); + +OMX_ERRORTYPE Exynos_OSAL_CheckANB(OMX_IN EXYNOS_OMX_DATA *pBuffer, + OMX_OUT OMX_BOOL *bIsANBEnabled); + +OMX_ERRORTYPE Exynos_OSAL_SetPrependSPSPPSToIDR(OMX_PTR pComponentParameterStructure, + OMX_PTR pbPrependSpsPpsToIdr); + +OMX_ERRORTYPE Exynos_OSAL_SetAndroidParameter(OMX_IN OMX_HANDLETYPE hComponent, OMX_IN OMX_INDEXTYPE nIndex, OMX_IN OMX_PTR ComponentParameterStructure); + +OMX_ERRORTYPE useAndroidNativeBuffer(EXYNOS_OMX_BASEPORT *pExynosPort, OMX_BUFFERHEADERTYPE **ppBufferHdr, OMX_U32 nPortIndex, OMX_PTR pAppPrivate, OMX_U32 nSizeBytes, OMX_U8 *pBuffer); + +OMX_U32 Exynos_OSAL_GetDisplayExtraBufferCount(void); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/osal/Exynos_OSAL_ETC.c b/osal/Exynos_OSAL_ETC.c new file mode 100644 index 0000000..0688ad7 --- /dev/null +++ b/osal/Exynos_OSAL_ETC.c @@ -0,0 +1,890 @@ +/* + * + * 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 +#include + +#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" + +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) +{ + return strlcpy(dest, src, (size_t)(strlen((const char *)src) + 1)); +} + +size_t Exynos_OSAL_Strncpy(OMX_PTR dest, OMX_PTR src, size_t num) +{ + return strlcpy(dest, src, (size_t)(num + 1)); +} + +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) +{ + return strlcat(dest, src, (size_t)(strlen((const char *)dest) + strlen((const char *)src) + 1)); +} + +size_t Exynos_OSAL_Strncat(OMX_PTR dest, OMX_PTR src, size_t num) +{ + size_t len = num; + + /* caution : num should be a size of dest buffer */ + return strlcat(dest, src, (size_t)(strlen((const char *)dest) + strlen((const char *)src) + 1)); +} + +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 Frame Count: %d", prefix, frameCount); + Exynos_OSAL_Log(EXYNOS_LOG_INFO, "%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_FormatYUV420SemiPlanarInterlace: + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanar: + case OMX_SEC_COLOR_FormatNV21Linear: + case OMX_SEC_COLOR_FormatNV12Tiled: + 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(%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; + + nAllocLen[0] = GET_Y_SIZE(nWidth, nHeight) + GET_CB_SIZE(nWidth, nHeight) + GET_CR_SIZE(nWidth, nHeight); + } else { + nDataLen[0] = nWidth * nHeight; + nDataLen[1] = nDataLen[0] >> 2; + nDataLen[2] = nDataLen[1]; + + nAllocLen[0] = ALIGN(ALIGN(nWidth, 16) * ALIGN(nHeight, 16), 256); + nAllocLen[1] = ALIGN(ALIGN(nWidth >> 1, 16) * (ALIGN(nHeight, 16) >> 1), 256); + 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; + + nAllocLen[0] = GET_Y_SIZE(nWidth, nHeight) + GET_UV_SIZE(nWidth, nHeight); + } else { + nDataLen[0] = nWidth * nHeight; + nDataLen[1] = nDataLen[0] >> 1; + + nAllocLen[0] = ALIGN(ALIGN(nWidth, 16) * ALIGN(nHeight, 16), 256); + nAllocLen[1] = ALIGN(ALIGN(nWidth, 16) * ALIGN(nHeight, 16) >> 1, 256); + } + break; + case OMX_SEC_COLOR_Format10bitYUV420SemiPlanar: + + if (ePlaneType == PLANE_SINGLE) { + nDataLen[0] = (nWidth * nHeight) * 3 / 2; + + nAllocLen[0] = GET_10B_Y_SIZE(nWidth, nHeight) + GET_10B_UV_SIZE(nWidth, nHeight); + } else { + nDataLen[0] = nWidth * nHeight; + nDataLen[1] = nDataLen[0] >> 1; + + nAllocLen[0] = ALIGN((ALIGN(nWidth, 16) * ALIGN(nHeight, 16) + 64) + (ALIGN(nWidth / 4, 16) * nHeight + 64), 256); + nAllocLen[1] = ALIGN((ALIGN(nWidth, 16) * ALIGN(nHeight, 16) + 64) + (ALIGN(nWidth / 4, 16) * (nHeight / 2) + 64), 256); + } + break; + case OMX_COLOR_Format32bitARGB8888: + case OMX_COLOR_Format32bitBGRA8888: + case OMX_COLOR_Format32BitRGBA8888: + nDataLen[0] = nWidth * nHeight * 4; + + nAllocLen[0] = ALIGN(ALIGN(nWidth, 16) * ALIGN(nHeight, 16) * 4, 256); + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "%s: unsupported color format(%x).", __func__, eColorFormat); + break; + } +} + +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, VIDEO_COLORFORMAT_NV12}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace}, +{{VIDEO_COLORFORMAT_NV12M, VIDEO_COLORFORMAT_NV12}, (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_Format10bitYUV420SemiPlanar}, +{{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_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}, +}; + +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_TRACE, "OMX(%x)/Plane type(%x) is not supported", eColorFormat, ePlaneType); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX(%x)/Plane type(%x) -> VIDEO(%x) is changed", 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_TRACE, "VIDEO(%x) is not supported", nVideoFormat); + goto EXIT; + } + +#if 0 + if ((eOMXFormat == OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace) || + (eOMXFormat == OMX_SEC_COLOR_Format10bitYUV420SemiPlanar)) { + eOMXFormat = OMX_COLOR_FormatYUV420SemiPlanar; /* hiding */ + } +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "VIDEO(%x) -> OMX(%x) is changed", 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 */ +{{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_PRIV, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP}, + (OMX_COLOR_FORMATTYPE)OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace}, /* deinterlacing at single-FD(H/W) is not supported */ + +{{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_Format10bitYUV420SemiPlanar}, + +/* 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}, + +/* 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}, +}; + +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) || + (HAL_COLORFORMAT_MAP[i].nHALFormat[2] == nHALFormat)) { + eOMXFormat = HAL_COLORFORMAT_MAP[i].eOMXFormat; + break; + } + } + + if (eOMXFormat == OMX_COLOR_FormatUnused) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "HAL(%x) is not supported", nHALFormat); + goto EXIT; + } + +#if 0 + if ((eOMXFormat == OMX_SEC_COLOR_FormatYUV420SemiPlanarInterlace) || + (eOMXFormat == OMX_SEC_COLOR_Format10bitYUV420SemiPlanar)) { + eOMXFormat = OMX_COLOR_FormatYUV420SemiPlanar; /* hiding */ + } +#endif + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "HAL(%x) -> OMX(%x) is changed", 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) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX(%x)/Plane type(%x) is not supported", eOMXFormat, ePlaneType); + goto EXIT; + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "OMX(%x) -> HAL(%x) is changed", eOMXFormat, nHALFormat); + +EXIT: + + return nHALFormat; +} + +#ifdef PERFORMANCE_DEBUG +typedef struct _EXYNOS_OMX_COUNT +{ + OMX_HANDLETYPE mutex; + OMX_S32 OMXQCount; + OMX_S32 V4L2QCount; + BUFFER_TIME sBufferTime[MAX_TIMESTAMP]; + OMX_U32 bufferTimeIndex; + OMX_TICKS dstOutPreviousTimeStamp; +} EXYNOS_OMX_COUNT; + +OMX_ERRORTYPE Exynos_OSAL_CountCreate(OMX_HANDLETYPE *hCountHandle) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_COUNT *countHandle = NULL; + + countHandle = (EXYNOS_OMX_COUNT *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_COUNT)); + if (countHandle == NULL) { + *hCountHandle = NULL; + return OMX_ErrorInsufficientResources; + } + Exynos_OSAL_Memset((OMX_PTR)countHandle, 0, sizeof(EXYNOS_OMX_COUNT)); + + ret = Exynos_OSAL_MutexCreate(&(countHandle->mutex)); + if (ret != OMX_ErrorNone) { + Exynos_OSAL_Free(countHandle); + *hCountHandle = NULL; + goto EXIT; + } + + countHandle->OMXQCount = 0; + *hCountHandle = countHandle; + +EXIT: + return ret; +} + +void Exynos_OSAL_CountTerminate(OMX_HANDLETYPE *hCountHandle) +{ + EXYNOS_OMX_COUNT *countHandle = (EXYNOS_OMX_COUNT *)*hCountHandle; + + if (countHandle == NULL) + return; + + Exynos_OSAL_MutexTerminate(countHandle->mutex); + Exynos_OSAL_Free(countHandle); + *hCountHandle = NULL; + + return; +} + +OMX_S32 Exynos_OSAL_CountIncrease(OMX_HANDLETYPE hCountHandle, OMX_BUFFERHEADERTYPE *OMXBufferHeader, OMX_U32 nPortIndex) +{ + EXYNOS_OMX_COUNT *countHandle = (EXYNOS_OMX_COUNT *)hCountHandle; + OMX_U32 nextIndex = 0; + OMX_S32 ret = -1; + + struct timeval currentTime; + struct tm* ptm; + char time_string[40]; + long milliseconds; + + if (countHandle == NULL) + return ret; + + if (OMX_ErrorNone == Exynos_OSAL_MutexLock(countHandle->mutex)) { + countHandle->OMXQCount++; + nextIndex = (countHandle->bufferTimeIndex + 1) % MAX_TIMESTAMP; + //Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "nextIndex:%d, countHandle->bufferTimeIndex:%d", nextIndex, countHandle->bufferTimeIndex); + gettimeofday(&(currentTime), NULL); + countHandle->sBufferTime[countHandle->bufferTimeIndex].currentTimeStamp = OMXBufferHeader->nTimeStamp; + Exynos_OSAL_Memcpy(&countHandle->sBufferTime[countHandle->bufferTimeIndex].currentIncomingTime, ¤tTime, sizeof(currentTime)); + countHandle->sBufferTime[countHandle->bufferTimeIndex].OMXQBufferCount = countHandle->OMXQCount; + countHandle->sBufferTime[countHandle->bufferTimeIndex].pBufferHeader = OMXBufferHeader; + countHandle->sBufferTime[nextIndex].previousTimeStamp = OMXBufferHeader->nTimeStamp; + Exynos_OSAL_Memcpy(&countHandle->sBufferTime[nextIndex].previousIncomingTime, ¤tTime, sizeof(currentTime)); + + countHandle->bufferTimeIndex = nextIndex; + ret = countHandle->OMXQCount; + Exynos_OSAL_MutexUnlock(countHandle->mutex); + + ptm = localtime (¤tTime.tv_sec); + strftime (time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm); + milliseconds = currentTime.tv_usec / 1000; +/* + if (nPortIndex == INPUT_PORT_INDEX) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "ETB time = %s.%03ld, header:0x%x, OMXQCount:%d", time_string, milliseconds, OMXBufferHeader, ret); + else + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "FTB time = %s.%03ld, header:0x%x, OMXQCount:%d", time_string, milliseconds, OMXBufferHeader, ret); +*/ + } + + return ret; +} + +OMX_S32 Exynos_OSAL_CountDecrease(OMX_HANDLETYPE hCountHandle, OMX_BUFFERHEADERTYPE *OMXBufferHeader, OMX_U32 nPortIndex) +{ + EXYNOS_OMX_COUNT *countHandle = (EXYNOS_OMX_COUNT *)hCountHandle; + OMX_U32 i = 0; + OMX_S32 ret = -1; + + struct timeval currentTime; + struct tm* ptm; + char time_string[40]; + long milliseconds; + + if (countHandle == NULL) + return ret; + + if (OMX_ErrorNone == Exynos_OSAL_MutexLock(countHandle->mutex)) { + for (i = 0; i < MAX_TIMESTAMP; i++) { + if (countHandle->sBufferTime[i].pBufferHeader == OMXBufferHeader) { + countHandle->sBufferTime[i].pBufferHeader = NULL; + if (nPortIndex == OUTPUT_PORT_INDEX) + countHandle->dstOutPreviousTimeStamp = countHandle->sBufferTime[i].currentTimeStamp; + break; + } + } + + countHandle->OMXQCount--; + ret = countHandle->OMXQCount; + Exynos_OSAL_MutexUnlock(countHandle->mutex); + + if (i >= MAX_TIMESTAMP) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "can not find a bufferHeader !!"); + ret = OMX_ErrorNoMore; + } + + gettimeofday(&(currentTime), NULL); + ptm = localtime (¤tTime.tv_sec); + strftime (time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm); + milliseconds = currentTime.tv_usec / 1000; +/* + if (nPortIndex == INPUT_PORT_INDEX) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "EBD time = %s.%03ld, header:0x%x, OMXQCount:%d", time_string, milliseconds, OMXBufferHeader, ret); + else + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "FBD time = %s.%03ld, header:0x%x, OMXQCount:%d", time_string, milliseconds, OMXBufferHeader, ret); +*/ + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_GetCountInfoUseOMXBuffer(OMX_HANDLETYPE hCountHandle, OMX_BUFFERHEADERTYPE *OMXBufferHeader, BUFFER_TIME *pBufferInfo) +{ + OMX_ERRORTYPE ret = OMX_ErrorNone; + EXYNOS_OMX_COUNT *countHandle = (EXYNOS_OMX_COUNT *)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; +} + +OMX_ERRORTYPE Exynos_OSAL_GetCountInfoUseTimestamp(OMX_HANDLETYPE hCountHandle, OMX_TICKS Timestamp, BUFFER_TIME *pBufferInfo) +{ + EXYNOS_OMX_COUNT *countHandle = (EXYNOS_OMX_COUNT *)hCountHandle; + OMX_U32 i = 0; + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if ((countHandle == 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].currentTimeStamp == Timestamp) { + 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 timestamp !!"); + ret = OMX_ErrorNoMore; + } + } + return ret; +} + +OMX_S32 Exynos_OSAL_V4L2CountIncrease(OMX_HANDLETYPE hCountHandle, OMX_BUFFERHEADERTYPE *OMXBufferHeader, OMX_U32 nPortIndex) +{ + EXYNOS_OMX_COUNT *countHandle = (EXYNOS_OMX_COUNT *)hCountHandle; + OMX_U32 i = 0, index = 0; + OMX_S32 ret = -1; + + struct tm* ptm; + char time_string[40]; + long milliseconds; + + if (countHandle == NULL) + return ret; + + if (OMX_ErrorNone == Exynos_OSAL_MutexLock(countHandle->mutex)) { + for (i = 0; i < MAX_TIMESTAMP; i++) { + if (countHandle->sBufferTime[i].pBufferHeader == OMXBufferHeader) { + index = i; + break; + } + } + + if (i >= MAX_TIMESTAMP) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "can not find a bufferHeader !!"); + Exynos_OSAL_MutexUnlock(countHandle->mutex); + return OMX_ErrorNoMore; + } + + countHandle->V4L2QCount++; + gettimeofday(&(countHandle->sBufferTime[index].V4L2QBufferTime), NULL); + countHandle->sBufferTime[index].V4L2QBufferCount = countHandle->V4L2QCount; + ret = countHandle->V4L2QCount; + Exynos_OSAL_MutexUnlock(countHandle->mutex); + + ptm = localtime (&countHandle->sBufferTime[index].V4L2QBufferTime.tv_sec); + strftime (time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm); + milliseconds = countHandle->sBufferTime[index].V4L2deQBufferTime.tv_usec / 1000; +/* + if (nPortIndex == INPUT_PORT_INDEX) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "V4L2 Src Q time = %s.%03ld, header:0x%x, index:%d", time_string, milliseconds, OMXBufferHeader, index); + else + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "V4L2 Dst Q time = %s.%03ld, header:0x%x", time_string, milliseconds, OMXBufferHeader); +*/ + } + + return ret; +} + +OMX_S32 Exynos_OSAL_V4L2CountDecrease(OMX_HANDLETYPE hCountHandle, OMX_BUFFERHEADERTYPE *OMXBufferHeader, OMX_U32 nPortIndex) +{ + EXYNOS_OMX_COUNT *countHandle = (EXYNOS_OMX_COUNT *)hCountHandle; + OMX_U32 i = 0, index = 0; + OMX_S32 ret = -1; + + struct tm* ptm; + char time_string[40]; + long milliseconds; + + if (countHandle == NULL) + return ret; + + if (OMX_ErrorNone == Exynos_OSAL_MutexLock(countHandle->mutex)) { + for (i = 0; i < MAX_TIMESTAMP; i++) { + if (countHandle->sBufferTime[i].pBufferHeader == OMXBufferHeader) { + index = i; + break; + } + } + + if (i >= MAX_TIMESTAMP) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "can not find a bufferHeader !!"); + Exynos_OSAL_MutexUnlock(countHandle->mutex); + return OMX_ErrorNoMore; + } + + countHandle->V4L2QCount--; + gettimeofday(&(countHandle->sBufferTime[index].V4L2deQBufferTime), NULL); + if (nPortIndex == OUTPUT_PORT_INDEX) { + countHandle->sBufferTime[index].currentTimeStamp = OMXBufferHeader->nTimeStamp; + countHandle->sBufferTime[index].previousTimeStamp = countHandle->dstOutPreviousTimeStamp; + } + ret = countHandle->V4L2QCount; + Exynos_OSAL_MutexUnlock(countHandle->mutex); + + ptm = localtime (&countHandle->sBufferTime[index].V4L2deQBufferTime.tv_sec); + strftime (time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm); + milliseconds = countHandle->sBufferTime[index].V4L2deQBufferTime.tv_usec / 1000; +/* + if (nPortIndex == INPUT_PORT_INDEX) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "V4L2 Src deQ time = %s.%03ld, header:0x%x", time_string, milliseconds, OMXBufferHeader); + else + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "V4L2 Dst deQ time = %s.%03ld, header:0x%x", time_string, milliseconds, OMXBufferHeader); +*/ + } + + return ret; +} + +OMX_ERRORTYPE Exynos_OSAL_CountReset(OMX_HANDLETYPE hCountHandle) +{ + EXYNOS_OMX_COUNT *countHandle = (EXYNOS_OMX_COUNT *)hCountHandle; + + OMX_ERRORTYPE ret = OMX_ErrorNone; + + if (countHandle == NULL) + return OMX_ErrorBadParameter; + + if (OMX_ErrorNone == Exynos_OSAL_MutexLock(countHandle->mutex)) { + countHandle->bufferTimeIndex = 0; + countHandle->OMXQCount = 0; + countHandle->V4L2QCount = 0; + Exynos_OSAL_Memset(&countHandle->sBufferTime, 0, sizeof(BUFFER_TIME) * MAX_TIMESTAMP); + Exynos_OSAL_MutexUnlock(countHandle->mutex); + } + + return ret; +} + +void Exynos_OSAL_PrintCountInfo(BUFFER_TIME srcBufferInfo, BUFFER_TIME dstBufferInfo) +{ + struct timeval FBDTime; + struct tm* ptm; + char time_string[40]; + 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; + + { + gettimeofday(&FBDTime, NULL); + + srcOMXtoV4L2 = Exynos_OSAL_MeasureTime(&(srcBufferInfo.currentIncomingTime), &(srcBufferInfo.V4L2QBufferTime)) / 1000; + //srcV4L2toOMX = Exynos_OSAL_MeasureTime(&(srcBufferInfo.V4L2deQBufferTime), &(srcBufferInfo.?????????????????)) / 1000; + dstOMXtoV4L2 = Exynos_OSAL_MeasureTime(&(dstBufferInfo.currentIncomingTime), &(dstBufferInfo.V4L2QBufferTime)) / 1000; + dstV4L2toOMX = Exynos_OSAL_MeasureTime(&(dstBufferInfo.V4L2deQBufferTime), &FBDTime) / 1000; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PERFORM:: INTERNAL: srcOMXtoV4L2:%d, srcV4L2toOMX:%d, dstOMXtoV4L2:%d, dstV4L2toOMX:%d", srcOMXtoV4L2, srcV4L2toOMX, dstOMXtoV4L2, dstV4L2toOMX); + } + + { + srcQdstQ = Exynos_OSAL_MeasureTime(&(srcBufferInfo.V4L2QBufferTime), &(dstBufferInfo.V4L2QBufferTime)) / 1000; + srcQdstDQ = Exynos_OSAL_MeasureTime(&(srcBufferInfo.V4L2QBufferTime), &(dstBufferInfo.V4L2deQBufferTime)) / 1000; + dstQdstDQ = Exynos_OSAL_MeasureTime(&(dstBufferInfo.V4L2QBufferTime), &(dstBufferInfo.V4L2deQBufferTime)) / 1000; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PERFORM:: V4L2: srcQdstQ:%d, srcQdstDQ:%d, dstQdstDQ:%d, src-V4L2QBufferCount:%d, dst-V4L2QBufferCount:%d", + srcQdstQ, srcQdstDQ, dstQdstDQ, srcBufferInfo.V4L2QBufferCount, dstBufferInfo.V4L2QBufferCount); + } + + { + ETBFTB = Exynos_OSAL_MeasureTime(&(srcBufferInfo.currentIncomingTime), &(dstBufferInfo.currentIncomingTime)) / 1000; + ETBFBD = Exynos_OSAL_MeasureTime(&(srcBufferInfo.currentIncomingTime), &FBDTime) / 1000; + FTBFBD = Exynos_OSAL_MeasureTime(&(dstBufferInfo.currentIncomingTime), &FBDTime) / 1000; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PERFORM:: BUFFER: ETBFTB:%d, ETBFBD:%d, FTBFBD:%d, src-OMXQBufferCount:%d, dst-OMXQBufferCount:%d", + ETBFTB, ETBFBD, FTBFBD, srcBufferInfo.OMXQBufferCount, dstBufferInfo.OMXQBufferCount); + + if (ETBFTB > 0) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PERFORM:: BUFFER: Output port buffer slow. real decode time:%d", FTBFBD / dstBufferInfo.OMXQBufferCount); + else if (ETBFTB < 0) + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PERFORM:: BUFFER: Input port buffer slow. real decode time:%d", ETBFBD / srcBufferInfo.OMXQBufferCount); + else + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "PERFORM:: BUFFER: real decode time:%d or %d", ETBFBD / srcBufferInfo.OMXQBufferCount, FTBFBD / dstBufferInfo.OMXQBufferCount); + } + + { + 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.currentTimeStamp - 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.currentTimeStamp - 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.currentTimeStamp - srcBufferInfo.previousTimeStamp)) / 1000; + dstTimestampInterval = ((OMX_S32)(dstBufferInfo.currentTimeStamp - 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/osal/Exynos_OSAL_ETC.h b/osal/Exynos_OSAL_ETC.h new file mode 100644 index 0000000..37f658d --- /dev/null +++ b/osal/Exynos_OSAL_ETC.h @@ -0,0 +1,122 @@ +/* + * + * 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); +ssize_t getline(char **ppLine, size_t *len, FILE *stream); + +/* 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]); + +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); + +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 +typedef struct _BUFFER_TIME +{ + OMX_TICKS previousTimeStamp; + OMX_TICKS currentTimeStamp; + struct timeval previousIncomingTime; + struct timeval currentIncomingTime; + OMX_S32 OMXQBufferCount; + OMX_BUFFERHEADERTYPE *pBufferHeader; + + OMX_S32 V4L2QBufferCount; + struct timeval V4L2QBufferTime; + struct timeval V4L2deQBufferTime; +} BUFFER_TIME; + +OMX_ERRORTYPE Exynos_OSAL_CountCreate(OMX_HANDLETYPE *phCountHandle); +void Exynos_OSAL_CountTerminate(OMX_HANDLETYPE *phCountHandle); +OMX_S32 Exynos_OSAL_CountIncrease(OMX_HANDLETYPE hCountHandle, OMX_BUFFERHEADERTYPE *OMXBufferHeader, OMX_U32 nPortIndex); +OMX_S32 Exynos_OSAL_CountDecrease(OMX_HANDLETYPE hCountHandle, OMX_BUFFERHEADERTYPE *OMXBufferHeader, OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_OSAL_GetCountInfoUseOMXBuffer(OMX_HANDLETYPE hCountHandle, OMX_BUFFERHEADERTYPE *OMXBufferHeader, BUFFER_TIME *pBufferInfo); +OMX_ERRORTYPE Exynos_OSAL_GetCountInfoUseTimestamp(OMX_HANDLETYPE hCountHandle, OMX_TICKS Timestamp, BUFFER_TIME *pBufferInfo); +OMX_S32 Exynos_OSAL_V4L2CountIncrease(OMX_HANDLETYPE hCountHandle, OMX_BUFFERHEADERTYPE *OMXBufferHeader, OMX_U32 nPortIndex); +OMX_S32 Exynos_OSAL_V4L2CountDecrease(OMX_HANDLETYPE hCountHandle, OMX_BUFFERHEADERTYPE *OMXBufferHeader, OMX_U32 nPortIndex); +OMX_ERRORTYPE Exynos_OSAL_CountReset(OMX_HANDLETYPE hCountHandle); +void Exynos_OSAL_PrintCountInfo(BUFFER_TIME srcBufferInfo, BUFFER_TIME dstBufferInfo); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/osal/Exynos_OSAL_Event.c b/osal/Exynos_OSAL_Event.c new file mode 100644 index 0000000..c238153 --- /dev/null +++ b/osal/Exynos_OSAL_Event.c @@ -0,0 +1,217 @@ +/* + * + * 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 "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)) { + 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; + OMX_U32 tv_us; + + 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; + timeout.tv_nsec = (tv_us % 1000000) * 1000; + + 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/osal/Exynos_OSAL_Event.h b/osal/Exynos_OSAL_Event.h new file mode 100644 index 0000000..f7ccd89 --- /dev/null +++ b/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/osal/Exynos_OSAL_Library.c b/osal/Exynos_OSAL_Library.c new file mode 100644 index 0000000..88775ee --- /dev/null +++ b/osal/Exynos_OSAL_Library.c @@ -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 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 "Exynos_OSAL_Library.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(); +} diff --git a/osal/Exynos_OSAL_Library.h b/osal/Exynos_OSAL_Library.h new file mode 100644 index 0000000..16bbd2a --- /dev/null +++ b/osal/Exynos_OSAL_Library.h @@ -0,0 +1,46 @@ +/* + * + * 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); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/osal/Exynos_OSAL_Log.c b/osal/Exynos_OSAL_Log.c new file mode 100644 index 0000000..d1216c2 --- /dev/null +++ b/osal/Exynos_OSAL_Log.c @@ -0,0 +1,122 @@ +/* + * + * 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_DEFAULT = EXYNOS_LOG_INFO, + LOG_LEVEL1 = EXYNOS_LOG_ESSENTIAL, + LOG_LEVEL2 = EXYNOS_LOG_TRACE, + LOG_LEVELTAG = 3 +} EXYNOS_DEBUG_LEVEL; + +static unsigned int log_prop = LOG_DEFAULT; + +void Exynos_OSAL_Get_Log_Property() +{ +#ifdef EXYNOS_LOG + if (property_get("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 { + 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_TRACE: + __android_log_vprint(ANDROID_LOG_VERBOSE, tag, msg, argptr); + break; + case EXYNOS_LOG_ESSENTIAL: + __android_log_vprint(ANDROID_LOG_DEBUG, tag, msg, argptr); + break; + 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/osal/Exynos_OSAL_Log.h b/osal/Exynos_OSAL_Log.h new file mode 100644 index 0000000..947d1f5 --- /dev/null +++ b/osal/Exynos_OSAL_Log.h @@ -0,0 +1,80 @@ +/* + * + * 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 + +typedef enum _LOG_LEVEL +{ + 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_TRACE, EXYNOS_LOG_TAG, "%s In , Line: %d", __FUNCTION__, __LINE__) +#define FunctionOut() _Exynos_OSAL_Log(EXYNOS_LOG_TRACE, EXYNOS_LOG_TAG, "%s Out , Line: %d", __FUNCTION__, __LINE__) +#else +#define FunctionIn() ((void *)0) +#define FunctionOut() ((void *)0) +#endif + +extern void Exynos_OSAL_Get_Log_Property(); +extern void _Exynos_OSAL_Log(EXYNOS_LOG_LEVEL logLevel, const char *tag, const char *msg, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/osal/Exynos_OSAL_Memory.c b/osal/Exynos_OSAL_Memory.c new file mode 100644 index 0000000..8782746 --- /dev/null +++ b/osal/Exynos_OSAL_Memory.c @@ -0,0 +1,76 @@ +/* + * + * 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 "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) +{ + mem_cnt++; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "alloc count: %d", mem_cnt); + + return (OMX_PTR)malloc(size); +} + +void Exynos_OSAL_Free(OMX_PTR addr) +{ + mem_cnt--; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "free count: %d", mem_cnt); + + if (addr) + free(addr); + + 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); +} diff --git a/osal/Exynos_OSAL_Memory.h b/osal/Exynos_OSAL_Memory.h new file mode 100644 index 0000000..e3fb406 --- /dev/null +++ b/osal/Exynos_OSAL_Memory.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_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); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/osal/Exynos_OSAL_Mutex.c b/osal/Exynos_OSAL_Mutex.c new file mode 100644 index 0000000..4ef773c --- /dev/null +++ b/osal/Exynos_OSAL_Mutex.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_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; + int result; + + 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; + int result; + + if (mutex == NULL) + return OMX_ErrorBadParameter; + + if (pthread_mutex_unlock(mutex) != 0) + return OMX_ErrorUndefined; + + return OMX_ErrorNone; +} diff --git a/osal/Exynos_OSAL_Mutex.h b/osal/Exynos_OSAL_Mutex.h new file mode 100644 index 0000000..d8875ed --- /dev/null +++ b/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/osal/Exynos_OSAL_Queue.c b/osal/Exynos_OSAL_Queue.c new file mode 100644 index 0000000..28c472e --- /dev/null +++ b/osal/Exynos_OSAL_Queue.c @@ -0,0 +1,197 @@ +/* + * + * 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++) { + currentqelem = queue->first->qNext; + Exynos_OSAL_Free(queue->first); + queue->first = currentqelem; + } + + if(queue->first) { + Exynos_OSAL_Free(queue->first); + queue->first = NULL; + } + + ret = Exynos_OSAL_MutexTerminate(queue->qMutex); + + 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/osal/Exynos_OSAL_Queue.h b/osal/Exynos_OSAL_Queue.h new file mode 100644 index 0000000..6300b45 --- /dev/null +++ b/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/osal/Exynos_OSAL_Semaphore.c b/osal/Exynos_OSAL_Semaphore.c new file mode 100644 index 0000000..d454730 --- /dev/null +++ b/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/osal/Exynos_OSAL_Semaphore.h b/osal/Exynos_OSAL_Semaphore.h new file mode 100644 index 0000000..8618407 --- /dev/null +++ b/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/osal/Exynos_OSAL_SharedMemory.c b/osal/Exynos_OSAL_SharedMemory.c new file mode 100644 index 0000000..c31caf1 --- /dev/null +++ b/osal/Exynos_OSAL_SharedMemory.c @@ -0,0 +1,539 @@ +/* + * + * 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 +#include +#include +#include + +#include +#include "exynos_ion.h" + +#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 +{ + OMX_U32 IONBuffer; + OMX_PTR mapAddr; + OMX_U32 allocSize; + OMX_BOOL owner; + struct _EXYNOS_SHAREDMEM_LIST *pNextMemory; +} EXYNOS_SHAREDMEM_LIST; + +typedef struct _EXYNOS_SHARED_MEMORY +{ + int hIONHandle; + EXYNOS_SHAREDMEM_LIST *pAllocMemory; + OMX_HANDLETYPE hSMMutex; +} EXYNOS_SHARED_MEMORY; + + +OMX_HANDLETYPE Exynos_OSAL_SharedMemory_Open() +{ + EXYNOS_SHARED_MEMORY *pHandle = NULL; + int 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 = 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 = IONClient; + + if (OMX_ErrorNone != Exynos_OSAL_MutexCreate(&pHandle->hSMMutex)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "Exynos_OSAL_MutexCreate(hSMMutex) is failed"); + /* free a ion_client */ + ion_close(pHandle->hIONHandle); + pHandle->hIONHandle = -1; + + 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 != INT_TO_PTR(pDeleteElement->IONBuffer)) { + if (munmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "munmap is failed"); + } + + pDeleteElement->mapAddr = NULL; + pDeleteElement->allocSize = 0; + + if (pDeleteElement->owner) { + /* free a ion_buffer */ + ion_close(pDeleteElement->IONBuffer); + mem_cnt--; + } + pDeleteElement->IONBuffer = 0; + + Exynos_OSAL_Free(pDeleteElement); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory mem count: %d", mem_cnt); + } + + pHandle->pAllocMemory = pSMList = NULL; + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + Exynos_OSAL_MutexTerminate(pHandle->hSMMutex); + pHandle->hSMMutex = NULL; + + /* free a ion_client */ + ion_close(pHandle->hIONHandle); + pHandle->hIONHandle = -1; + + 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; + OMX_S32 IONBuffer = 0; + 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 = ION_HEAP_EXYNOS_CONTIG_MASK; + flag = ION_EXYNOS_VIDEO_EXT_MASK | 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 = ION_HEAP_EXYNOS_CONTIG_MASK; + flag = ION_EXYNOS_VIDEO_EXT_MASK; + break; + case (SECURE_MEMORY | CONTIG_MEMORY | CACHED_MEMORY): /* SECURE */ + case (SECURE_MEMORY | CONTIG_MEMORY): + case (SECURE_MEMORY | CACHED_MEMORY): + case SECURE_MEMORY: + mask = ION_HEAP_EXYNOS_CONTIG_MASK; + flag = ION_EXYNOS_MFC_INPUT_MASK | ION_FLAG_PROTECTED; + break; + case (CONTIG_MEMORY | CACHED_MEMORY): /* CONTIG */ + case CONTIG_MEMORY: + mask = ION_HEAP_EXYNOS_CONTIG_MASK; + flag = ION_EXYNOS_MFC_INPUT_MASK; + break; + case CACHED_MEMORY: /* CACHED */ + mask = ION_HEAP_SYSTEM_MASK; + flag = ION_FLAG_CACHED; + break; + default: /* NORMAL */ + mask = ION_HEAP_SYSTEM_MASK; + flag = ION_FLAG_CACHED; + break; + } + +#ifdef USE_IMPROVED_BUFFER + if (flag & ION_FLAG_CACHED) /* use improved cache oprs */ + flag |= ION_FLAG_CACHED_NEEDS_SYNC; +#endif + + if (ion_alloc_fd(pHandle->hIONHandle, size, 0, mask, flag, (int *)&IONBuffer) < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "ion_alloc_fd is failed(mask:%x, flag:%x)", mask, flag); + if (memoryType == CONTIG_MEMORY) { + /* retry at normal area */ + flag = 0; + if (ion_alloc_fd(pHandle->hIONHandle, size, 0, mask, flag, (int *)&IONBuffer) < 0) + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "retry, ion_alloc_fd is failed(mask:%x, flag:%x)", mask, flag); + } + } + + if (IONBuffer < 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ion buffer is wrong: fd = %d", IONBuffer); + 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 = INT_TO_PTR(IONBuffer); + } else { + pBuffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, IONBuffer, 0); + if (pBuffer == MAP_FAILED) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "mmap is failed(size:%d)", size); + /* free a ion_buffer */ + ion_close(IONBuffer); + Exynos_OSAL_Free((OMX_PTR)pElement); + pBuffer = NULL; + 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); + + mem_cnt++; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory mem count: %d", 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, "Can not find SharedMemory"); + goto EXIT; + } + } + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + if (pDeleteElement->mapAddr != INT_TO_PTR(pDeleteElement->IONBuffer)) { + if (munmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "munmap is failed"); + goto EXIT; + } + } + + pDeleteElement->mapAddr = NULL; + pDeleteElement->allocSize = 0; + + if (pDeleteElement->owner) { + /* free a ion_buffer */ + ion_close(pDeleteElement->IONBuffer); + mem_cnt--; + } + pDeleteElement->IONBuffer = 0; + + Exynos_OSAL_Free(pDeleteElement); + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory mem count: %d", mem_cnt); + +EXIT: + return; +} + +#ifdef USE_DMA_BUF +OMX_PTR Exynos_OSAL_SharedMemory_Map(OMX_HANDLETYPE handle, OMX_U32 size, unsigned int 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) + goto EXIT; + + pElement = (EXYNOS_SHAREDMEM_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_SHAREDMEM_LIST)); + Exynos_OSAL_Memset(pElement, 0, sizeof(EXYNOS_SHAREDMEM_LIST)); + + IONBuffer = (OMX_S32)ionfd; + + if (IONBuffer <= 0) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "ionFD(%d) is wrong", IONBuffer); + Exynos_OSAL_Free((void*)pElement); + goto EXIT; + } + + pBuffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, IONBuffer, 0); + if (pBuffer == NULL) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "mmap is failed(size:%d)", size); + /* free a ion_buffer */ + ion_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, "SharedMemory map count: %d", map_cnt); + +EXIT: + return pBuffer; +} + +void Exynos_OSAL_SharedMemory_Unmap(OMX_HANDLETYPE handle, unsigned int 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, "Can not find SharedMemory"); + goto EXIT; + } + } + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + if (munmap(pDeleteElement->mapAddr, pDeleteElement->allocSize)) { + Exynos_OSAL_Log(EXYNOS_LOG_ERROR, "munmap is failed"); + goto EXIT; + } + pDeleteElement->mapAddr = NULL; + pDeleteElement->allocSize = 0; + pDeleteElement->IONBuffer = 0; + + Exynos_OSAL_Free(pDeleteElement); + + map_cnt--; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SharedMemory map count: %d", map_cnt); + +EXIT: + return; +} +#endif + +int 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; + int 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_WARNING, "Can not find SharedMemory"); + goto EXIT; + } + } + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + ion_addr = pFindElement->IONBuffer; + +EXIT: + return ion_addr; +} + +OMX_PTR Exynos_OSAL_SharedMemory_IONToVirt(OMX_HANDLETYPE handle, int ion_addr) +{ + 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 || ion_addr == 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 == (OMX_U32)ion_addr) { + pFindElement = pSMList; + } else { + while ((pCurrentElement != NULL) && (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) && + (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer != (OMX_U32)ion_addr)) + pCurrentElement = pCurrentElement->pNextMemory; + + if ((((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory)) != NULL) && + (((EXYNOS_SHAREDMEM_LIST *)(pCurrentElement->pNextMemory))->IONBuffer == (OMX_U32)ion_addr)) { + pFindElement = pCurrentElement->pNextMemory; + } else { + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + Exynos_OSAL_Log(EXYNOS_LOG_WARNING, "Can not find SharedMemory"); + goto EXIT; + } + } + Exynos_OSAL_MutexUnlock(pHandle->hSMMutex); + + pBuffer = pFindElement->mapAddr; + +EXIT: + return pBuffer; +} diff --git a/osal/Exynos_OSAL_SharedMemory.h b/osal/Exynos_OSAL_SharedMemory.h new file mode 100644 index 0000000..1f17d31 --- /dev/null +++ b/osal/Exynos_OSAL_SharedMemory.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_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); +int Exynos_OSAL_SharedMemory_VirtToION(OMX_HANDLETYPE handle, OMX_PTR pBuffer); +OMX_PTR Exynos_OSAL_SharedMemory_IONToVirt(OMX_HANDLETYPE handle, int ion_addr); + +#ifdef USE_DMA_BUF +OMX_PTR Exynos_OSAL_SharedMemory_Map(OMX_HANDLETYPE handle, OMX_U32 size, unsigned int ionfd); +void Exynos_OSAL_SharedMemory_Unmap(OMX_HANDLETYPE handle, unsigned int ionfd); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/osal/Exynos_OSAL_SkypeHD.c b/osal/Exynos_OSAL_SkypeHD.c new file mode 100644 index 0000000..9b599b3 --- /dev/null +++ b/osal/Exynos_OSAL_SkypeHD.c @@ -0,0 +1,1183 @@ +/* + * 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" + +#include "OMX_Video_Extensions.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 + +/* Change CHECK_SIZE_VERSION Macro for SkypeHD */ +OMX_ERRORTYPE Exynos_OMX_Check_SizeVersion_SkypeHD(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_TRACE, "nVersionMajor:%d, nVersionMinor:%d", version->s.nVersionMajor, version->s.nVersionMinor); + if (version->s.nVersionMajor != OMX_VIDEO_MajorVersion || + version->s.nVersionMinor > OMX_VIDEO_MinorVersion) { + ret = OMX_ErrorVersionMismatch; + goto EXIT; + } + + ret = OMX_ErrorNone; + +EXIT: + return ret; +} + + + +/* ENCODE_ONLY */ +#ifdef BUILD_ENC +/* video enc */ +OMX_ERRORTYPE Exynos_H264Enc_GetExtensionIndex_SkypeHD( + 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; + } + + if (Exynos_OSAL_Strcmp(cParameterName, OMX_MS_SKYPE_PARAM_DRIVERVER) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexSkypeParamDriverVersion; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, OMX_MS_SKYPE_PARAM_ENCODERSETTING) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexSkypeParamEncoderSetting; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, OMX_MS_SKYPE_PARAM_ENCODERCAP) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexSkypeParamEncoderCapability; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, OMX_MS_SKYPE_CONFIG_MARKLTRFRAME) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexSkypeConfigMarkLTRFrame; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, OMX_MS_SKYPE_CONFIG_USELTRFRAME) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexSkypeConfigUseLTRFrame; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, OMX_MS_SKYPE_CONFIG_QP) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexSkypeConfigQP; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, OMX_MS_SKYPE_CONFIG_TEMPORALLAYERCOUNT) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexSkypeConfigTemporalLayerCount; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, OMX_MS_SKYPE_CONFIG_BASELAYERPID) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexSkypeConfigBasePid; + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = OMX_ErrorUnsupportedIndex; + +EXIT: + FunctionOut(); + + return ret; +} + +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_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + 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_SkypeHD(pDriverVer, sizeof(OMX_VIDEO_PARAM_DRIVERVER)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pDriverVer->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDriverVer->nDriverVersion = (OMX_U64)(pH264Enc->hMFCH264Handle.videoInstInfo.SwVersion); + } + break; + case OMX_IndexSkypeParamEncoderCapability: + { + OMX_VIDEO_PARAM_ENCODERCAP *pEncoderCap = (OMX_VIDEO_PARAM_ENCODERCAP *)pComponentParameterStructure; + OMX_VIDEO_ENCODERCAP *pstEncCap = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pEncoderCap, sizeof(OMX_VIDEO_PARAM_ENCODERCAP)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pEncoderCap->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pstEncCap = &(pEncoderCap->stEncCap); + + pstEncCap->bLowLatency = OMX_TRUE; + pstEncCap->nMaxFrameWidth = MAX_FRAME_WIDTH; + pstEncCap->nMaxFrameHeight = MAX_FRAME_HEIGHT; + pstEncCap->nMaxInstances = RESOURCE_VIDEO_ENC; + pstEncCap->nMaxTemporaLayerCount = OMX_VIDEO_MAX_TEMPORAL_LAYERS; + pstEncCap->nMaxRefFrames = ((OMX_VIDEO_MAX_TEMPORAL_LAYERS_WITH_LTR + 1) / 2) + OMX_VIDEO_MAX_LTR_FRAMES; + pstEncCap->nMaxLTRFrames = OMX_VIDEO_MAX_LTR_FRAMES; + pstEncCap->nMaxLevel = OMX_VIDEO_AVCLevel42; + pstEncCap->nSliceControlModesBM = (1 << (OMX_VIDEO_SliceControlModeMB - 1)) | (1 << (OMX_VIDEO_SliceControlModeByte - 1)); + pstEncCap->nMaxMacroblockProcessingRate = ENC_BLOCKS_PER_SECOND; + pstEncCap->nResize = 0; + pstEncCap->xMinScaleFactor = 0; + } + break; + case OMX_IndexSkypeParamEncoderSetting: + { + OMX_VIDEO_PARAM_ENCODERSETTING *pEncoderSetting = (OMX_VIDEO_PARAM_ENCODERSETTING *)pComponentParameterStructure; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pEncoderSetting, sizeof(OMX_VIDEO_PARAM_ENCODERSETTING)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pEncoderSetting->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + Exynos_OSAL_Memcpy(&(pEncoderSetting->stEncParam), &(pH264Enc->stEncParam), sizeof(OMX_VIDEO_ENCODERPARAMS)); + } + 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_VIDEOENC_COMPONENT *pVideoEnc = NULL; + EXYNOS_H264ENC_HANDLE *pH264Enc = 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + switch ((int)nIndex) { + case OMX_IndexSkypeParamEncoderSetting: + { + OMX_VIDEO_PARAM_ENCODERSETTING *pEncoderSetting = (OMX_VIDEO_PARAM_ENCODERSETTING *)pComponentParameterStructure; + OMX_VIDEO_ENCODERPARAMS *pstEncParam = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pEncoderSetting, sizeof(OMX_VIDEO_PARAM_ENCODERSETTING)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pEncoderSetting->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pstEncParam = &(pEncoderSetting->stEncParam); + + pH264Enc->bLowLatency = pstEncParam->bLowLatency; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pstEncParam->bLowLatency: %s", (pstEncParam->bLowLatency == OMX_TRUE) ? "OMX_TRUE" : "OMX_FALSE"); + + /* SetPrependSPSPPSToIDR */ + pH264Enc->hMFCH264Handle.bPrependSpsPpsToIdr = pstEncParam->bSequenceHeaderWithIDR; + + if (pstEncParam->bUseExtendedProfile == OMX_TRUE) { + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pstEncParam->eProfile: 0x%x", pstEncParam->eProfile); + switch (pstEncParam->eProfile) { + case OMX_VIDEO_EXT_AVCProfileConstrainedBaseline: + pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].eProfile = OMX_VIDEO_AVCProfileConstrainedBaseline; + break; + case OMX_VIDEO_EXT_AVCProfileConstrainedHigh: + pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].eProfile = OMX_VIDEO_AVCProfileConstrainedHigh; + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "default eProfile: 0x%x", pH264Enc->AVCComponent[OUTPUT_PORT_INDEX].eProfile); + break; + } + } + + switch (pstEncParam->eHierarType) { + case OMX_VIDEO_HierarType_P: + pH264Enc->eHierarchicalType = EXYNOS_OMX_Hierarchical_P; + break; + case OMX_VIDEO_HierarType_B: + pH264Enc->eHierarchicalType = EXYNOS_OMX_Hierarchical_B; + break; + default: + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "default eHierarType: 0x%x", pH264Enc->eHierarchicalType); + break; + } + + if (pstEncParam->nMaxTemporalLayerCount > OMX_VIDEO_ANDROID_MAXAVCTEMPORALLAYERS) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } else { + if (pstEncParam->nMaxTemporalLayerCount > 0) { + pH264Enc->hMFCH264Handle.bTemporalSVC = OMX_TRUE; + pH264Enc->TemporalSVC.nTemporalLayerCount = pstEncParam->nMaxTemporalLayerCount | GENERAL_TSVC_ENABLE; + } else { + pH264Enc->hMFCH264Handle.bTemporalSVC = OMX_FALSE; + } + } + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pstEncParam->nLTRFrames: %d", pstEncParam->nLTRFrames); + if (((int)(pstEncParam->nLTRFrames) > ((int)OMX_VIDEO_MAX_LTR_FRAMES)) || + (((int)pstEncParam->nLTRFrames) < 0)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } else { + if (pstEncParam->nLTRFrames > 0) + pH264Enc->hMFCH264Handle.bLTREnable = OMX_TRUE; + else + pH264Enc->hMFCH264Handle.bLTREnable = OMX_FALSE; + } + + switch (pstEncParam->eSliceControlMode) { + case OMX_VIDEO_SliceControlModeMB: + pH264Enc->AVCSliceFmo.eSliceMode = OMX_VIDEO_SLICEMODE_AVCMBSlice; + break; + case OMX_VIDEO_SliceControlModeByte: + pH264Enc->AVCSliceFmo.eSliceMode = OMX_VIDEO_SLICEMODE_AVCByteSlice; + break; + case OMX_VIDEO_SliceControlModeNone: + case OMX_VIDEO_SliceControlModMBRow: + default: + pH264Enc->AVCSliceFmo.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault; + break; + } + + if (pstEncParam->nSarIndex > 0) + pH264Enc->stSarParam.SarEnable = OMX_TRUE; + + pH264Enc->stSarParam.SarIndex = pstEncParam->nSarIndex; + pH264Enc->stSarParam.SarWidth = pstEncParam->nSarWidth; + pH264Enc->stSarParam.SarHeight = pstEncParam->nSarHeight; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "SarIndex:%d, SarWidth:%d, SarHeight:%d", + pstEncParam->nSarIndex, pstEncParam->nSarWidth, pstEncParam->nSarHeight); + + Exynos_OSAL_Memcpy(&(pH264Enc->stEncParam), &(pEncoderSetting->stEncParam), sizeof(OMX_VIDEO_ENCODERPARAMS)); + } + 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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + switch ((int)nIndex) { + case OMX_IndexSkypeConfigTemporalLayerCount: + { + OMX_VIDEO_CONFIG_TEMPORALLAYERCOUNT *pTemporalLayerCount = (OMX_VIDEO_CONFIG_TEMPORALLAYERCOUNT *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pTemporalLayerCount, sizeof(OMX_VIDEO_CONFIG_TEMPORALLAYERCOUNT)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pTemporalLayerCount->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pTemporalLayerCount->nTemporalLayerCount = pH264Enc->TemporalSVC.nTemporalLayerCount & (~GENERAL_TSVC_ENABLE); + } + break; + case OMX_IndexSkypeConfigBasePid: + { + OMX_VIDEO_CONFIG_BASELAYERPID *pBaseLayerPid = (OMX_VIDEO_CONFIG_BASELAYERPID *)pComponentConfigStructure; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pBaseLayerPid, sizeof(OMX_VIDEO_CONFIG_BASELAYERPID)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pBaseLayerPid->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pBaseLayerPid->nPID = pH264Enc->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)) { + 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; + } + + pVideoEnc = (EXYNOS_OMX_VIDEOENC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Enc = (EXYNOS_H264ENC_HANDLE *)pVideoEnc->hCodecHandle; + + switch ((int)nIndex) { + case OMX_IndexSkypeConfigMarkLTRFrame: + { + OMX_VIDEO_CONFIG_MARKLTRFRAME *pMarkLTRFrame = (OMX_VIDEO_CONFIG_MARKLTRFRAME *)pComponentConfigStructure; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH264Param *pH264Param = NULL; + ExynosVideoEncOps *pEncOps = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pMarkLTRFrame, sizeof(OMX_VIDEO_CONFIG_MARKLTRFRAME)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pMarkLTRFrame->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncParam = &pMFCH264Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pH264Param = &pEncParam->codecParam.h264; + pEncOps = pMFCH264Handle->pEncOps; + + /* TBD */ + } + break; + case OMX_IndexSkypeConfigUseLTRFrame: + { + OMX_VIDEO_CONFIG_USELTRFRAME *pUseLTRFrame = (OMX_VIDEO_CONFIG_USELTRFRAME *)pComponentConfigStructure; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH264Param *pH264Param = NULL; + ExynosVideoEncOps *pEncOps = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pUseLTRFrame, sizeof(OMX_VIDEO_CONFIG_USELTRFRAME)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pUseLTRFrame->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncParam = &pMFCH264Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pH264Param = &pEncParam->codecParam.h264; + pEncOps = pMFCH264Handle->pEncOps; + + /* TBD */ + } + break; + case OMX_IndexSkypeConfigQP: + { + OMX_VIDEO_CONFIG_QP *pConfigQp = (OMX_VIDEO_CONFIG_QP *)pComponentConfigStructure; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH264Param *pH264Param = NULL; + ExynosVideoEncOps *pEncOps = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pConfigQp, sizeof(OMX_VIDEO_CONFIG_QP)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pConfigQp->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncParam = &pMFCH264Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pH264Param = &pEncParam->codecParam.h264; + pEncOps = pMFCH264Handle->pEncOps; + + /* will remove */ + pVideoEnc->quantization.nQpI = pConfigQp->nQP; + pVideoEnc->quantization.nQpP = pConfigQp->nQP; + pVideoEnc->quantization.nQpB = pConfigQp->nQP; +// pCommonParam->FrameQp = pVideoEnc->quantization.nQpI; +// pCommonParam->FrameQp_P = pVideoEnc->quantization.nQpP; +// pH264Param->FrameQp_B = pVideoEnc->quantization.nQpB; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "%s : pConfigQp->nQP:%d", __FUNCTION__, pConfigQp->nQP); + + /* TBD */ + } + break; + case OMX_IndexSkypeConfigTemporalLayerCount: + { + OMX_VIDEO_CONFIG_TEMPORALLAYERCOUNT *pTemporalLayerCount = (OMX_VIDEO_CONFIG_TEMPORALLAYERCOUNT *)pComponentConfigStructure; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + + int i = 0; + TemporalLayerShareBuffer TemporalSVC; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pTemporalLayerCount, sizeof(OMX_VIDEO_CONFIG_TEMPORALLAYERCOUNT)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pTemporalLayerCount->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.bTemporalSVC == OMX_FALSE) || + (pTemporalLayerCount->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXAVCTEMPORALLAYERS)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + /* Temporal SVC */ + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncOps = pMFCH264Handle->pEncOps; + + pH264Enc->TemporalSVC.nTemporalLayerCount = pTemporalLayerCount->nTemporalLayerCount | GENERAL_TSVC_ENABLE; + } + break; + case OMX_IndexSkypeConfigBasePid: + { + OMX_VIDEO_CONFIG_BASELAYERPID *pBaseLayerPid = (OMX_VIDEO_CONFIG_BASELAYERPID *)pComponentConfigStructure; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH264Param *pH264Param = NULL; + ExynosVideoEncOps *pEncOps = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pBaseLayerPid, sizeof(OMX_VIDEO_CONFIG_BASELAYERPID)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pBaseLayerPid->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncParam = &pMFCH264Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pH264Param = &pEncParam->codecParam.h264; + pEncOps = pMFCH264Handle->pEncOps; + + pH264Enc->nBaseLayerPid = pBaseLayerPid->nPID; + } + break; + default: + ret = OMX_ErrorUnsupportedIndex; + break; + } + +EXIT: + + FunctionOut(); + + return ret; +} + +void 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; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH264Param *pH264Param = NULL; + ExynosVideoEncOps *pEncOps = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pMarkLTRFrame, sizeof(OMX_VIDEO_CONFIG_MARKLTRFRAME)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pMarkLTRFrame->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncParam = &pMFCH264Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pH264Param = &pEncParam->codecParam.h264; + pEncOps = pMFCH264Handle->pEncOps; + + /* TBD */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pMarkLTRFrame->nLongTermFrmIdx: %d", 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; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH264Param *pH264Param = NULL; + ExynosVideoEncOps *pEncOps = NULL; + + OMX_S32 nUsedLTRFrameNum = 0; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pUseLTRFrame, sizeof(OMX_VIDEO_CONFIG_USELTRFRAME)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pUseLTRFrame->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncParam = &pMFCH264Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pH264Param = &pEncParam->codecParam.h264; + pEncOps = pMFCH264Handle->pEncOps; + + nUsedLTRFrameNum = pUseLTRFrame->nUsedLTRFrameBM; + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pUseLTRFrame->nUsedLTRFrameBM: %d, nUsedLTRFrameNum = %d", pUseLTRFrame->nUsedLTRFrameBM, nUsedLTRFrameNum); + if (nUsedLTRFrameNum < 0) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + pEncOps->Set_UsedLTRFrame(pMFCH264Handle->hMFCHandle, nUsedLTRFrameNum); + } + break; + case OMX_IndexSkypeConfigQP: + { + OMX_VIDEO_CONFIG_QP *pConfigQp = (OMX_VIDEO_CONFIG_QP *)pConfigData; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH264Param *pH264Param = NULL; + ExynosVideoEncOps *pEncOps = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pConfigQp, sizeof(OMX_VIDEO_CONFIG_QP)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pConfigQp->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncParam = &pMFCH264Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pH264Param = &pEncParam->codecParam.h264; + pEncOps = pMFCH264Handle->pEncOps; + + /* will remove */ + pVideoEnc->quantization.nQpI = pConfigQp->nQP; + pVideoEnc->quantization.nQpP = pConfigQp->nQP; + pVideoEnc->quantization.nQpB = pConfigQp->nQP; +// pCommonParam->FrameQp = pVideoEnc->quantization.nQpI; +// pCommonParam->FrameQp_P = pVideoEnc->quantization.nQpP; +// pH264Param->FrameQp_B = pVideoEnc->quantization.nQpB; + + /* TBD */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pConfigQp->nQP: %d", pConfigQp->nQP); + pEncOps->Set_DynamicQpControl(pMFCH264Handle->hMFCHandle, pConfigQp->nQP); + } + break; + case OMX_IndexSkypeConfigTemporalLayerCount: + { + OMX_VIDEO_CONFIG_TEMPORALLAYERCOUNT *pTemporalLayerCount = (OMX_VIDEO_CONFIG_TEMPORALLAYERCOUNT *)pConfigData; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + ExynosVideoEncOps *pEncOps = NULL; + + int i = 0; + TemporalLayerShareBuffer TemporalSVC; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pTemporalLayerCount, sizeof(OMX_VIDEO_CONFIG_TEMPORALLAYERCOUNT)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pTemporalLayerCount->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + if ((pH264Enc->hMFCH264Handle.bTemporalSVC == OMX_FALSE) || + (pTemporalLayerCount->nTemporalLayerCount > OMX_VIDEO_ANDROID_MAXAVCTEMPORALLAYERS)) { + ret = OMX_ErrorBadParameter; + goto EXIT; + } + + /* Temporal SVC */ + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncOps = pMFCH264Handle->pEncOps; + + Exynos_OSAL_Memset(&TemporalSVC, 0, sizeof(TemporalLayerShareBuffer)); + TemporalSVC.nTemporalLayerCount = (unsigned int)pTemporalLayerCount->nTemporalLayerCount | GENERAL_TSVC_ENABLE; + for (i = 0; i < OMX_VIDEO_ANDROID_MAXAVCTEMPORALLAYERS; i++) + TemporalSVC.nTemporalLayerBitrateRatio[i] = 0; + + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "TemporalSVC.nTemporalLayerCount: %d", TemporalSVC.nTemporalLayerCount & (~GENERAL_TSVC_ENABLE)); + pEncOps->Set_LayerChange(pMFCH264Handle->hMFCHandle, TemporalSVC); + } + break; + case OMX_IndexSkypeConfigBasePid: + { + OMX_VIDEO_CONFIG_BASELAYERPID *pBaseLayerPid = (OMX_VIDEO_CONFIG_BASELAYERPID *)pConfigData; + EXYNOS_MFC_H264ENC_HANDLE *pMFCH264Handle = NULL; + ExynosVideoEncParam *pEncParam = NULL; + ExynosVideoEncCommonParam *pCommonParam = NULL; + ExynosVideoEncH264Param *pH264Param = NULL; + ExynosVideoEncOps *pEncOps = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pBaseLayerPid, sizeof(OMX_VIDEO_CONFIG_BASELAYERPID)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pBaseLayerPid->nPortIndex != OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pMFCH264Handle = &pH264Enc->hMFCH264Handle; + pEncParam = &pMFCH264Handle->encParam; + pCommonParam = &pEncParam->commonParam; + pH264Param = &pEncParam->codecParam.h264; + pEncOps = pMFCH264Handle->pEncOps; + + /* TBD */ + Exynos_OSAL_Log(EXYNOS_LOG_TRACE, "pBaseLayerPid->nPID: %d", pBaseLayerPid->nPID); + pEncOps->Set_BasePID(pMFCH264Handle->hMFCHandle, pBaseLayerPid->nPID); + } + break; + default: + break; + } + +EXIT: + + FunctionOut(); + + return; +} +#endif + + +/* DECODE_ONLY */ +#ifdef BUILD_DEC +/* video dec */ +OMX_ERRORTYPE Exynos_H264Dec_GetExtensionIndex_SkypeHD( + 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; + } + + if (Exynos_OSAL_Strcmp(cParameterName, OMX_MS_SKYPE_PARAM_DRIVERVER) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexSkypeParamDriverVersion; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, OMX_MS_SKYPE_PARAM_DECODERSETTING) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexSkypeParamDecoderSetting; + ret = OMX_ErrorNone; + goto EXIT; + } + + if (Exynos_OSAL_Strcmp(cParameterName, OMX_MS_SKYPE_PARAM_DECODERCAP) == 0) { + *pIndexType = (OMX_INDEXTYPE) OMX_IndexSkypeParamDecoderCapability; + ret = OMX_ErrorNone; + goto EXIT; + } + + ret = OMX_ErrorUnsupportedIndex; + +EXIT: + FunctionOut(); + + return ret; +} + +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)) { + 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; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + 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_SkypeHD(pDriverVer, sizeof(OMX_VIDEO_PARAM_DRIVERVER)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pDriverVer->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pDriverVer->nDriverVersion = (OMX_U64)(pH264Dec->hMFCH264Handle.videoInstInfo.SwVersion); + } + break; + case OMX_IndexSkypeParamDecoderCapability: + { + OMX_VIDEO_PARAM_DECODERCAP *pDecoderCap = (OMX_VIDEO_PARAM_DECODERCAP *)pComponentParameterStructure; + OMX_VIDEO_DECODERCAP *pstDecCap = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pDecoderCap, sizeof(OMX_VIDEO_PARAM_DECODERCAP)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pDecoderCap->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pstDecCap = &(pDecoderCap->stDecoderCap); + + /* TBD */ + pstDecCap->bLowLatency = OMX_TRUE; + pstDecCap->nMaxFrameWidth = MAX_FRAME_WIDTH; + pstDecCap->nMaxFrameHeight = MAX_FRAME_HEIGHT; + pstDecCap->nMaxInstances = RESOURCE_VIDEO_DEC; + pstDecCap->nMaxLevel = OMX_VIDEO_AVCLevel42; + pstDecCap->nMaxMacroblockProcessingRate = DEC_BLOCKS_PER_SECOND; + } + break; + case OMX_IndexSkypeParamDecoderSetting: + { + OMX_VIDEO_PARAM_DECODERSETTING *pDecoderSetting = (OMX_VIDEO_PARAM_DECODERSETTING *)pComponentParameterStructure; + EXYNOS_OMX_VIDEODEC_COMPONENT *pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + EXYNOS_H264DEC_HANDLE *pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + OMX_VIDEO_DECODERPARAMS *pstDecParam = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pDecoderSetting, sizeof(OMX_VIDEO_PARAM_DECODERSETTING)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pDecoderSetting->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pstDecParam = &(pDecoderSetting->stDecParam); + pstDecParam->bLowLatency = pH264Dec->bLowLatency; + } + 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) { + ret = OMX_ErrorInvalidState; + goto EXIT; + } + + pVideoDec = (EXYNOS_OMX_VIDEODEC_COMPONENT *)pExynosComponent->hComponentHandle; + pH264Dec = (EXYNOS_H264DEC_HANDLE *)pVideoDec->hCodecHandle; + + switch ((int)nIndex) { + case OMX_IndexSkypeParamDecoderSetting: + { + OMX_VIDEO_PARAM_DECODERSETTING *pDecoderSetting = (OMX_VIDEO_PARAM_DECODERSETTING *)pComponentParameterStructure; + OMX_VIDEO_DECODERPARAMS *pstDecParam = NULL; + + ret = Exynos_OMX_Check_SizeVersion_SkypeHD(pDecoderSetting, sizeof(OMX_VIDEO_PARAM_DECODERSETTING)); + if (ret != OMX_ErrorNone) + goto EXIT; + + if (pDecoderSetting->nPortIndex > OUTPUT_PORT_INDEX) { + ret = OMX_ErrorBadPortIndex; + goto EXIT; + } + + pstDecParam = &(pDecoderSetting->stDecParam); + pH264Dec->bLowLatency = pstDecParam->bLowLatency; + } + break; + default: + ret = OMX_ErrorUnsupportedIndex; + break; + + } + +EXIT: + + FunctionOut(); + + return ret; +} +#endif + +#ifdef __cplusplus +} +#endif diff --git a/osal/Exynos_OSAL_SkypeHD.h b/osal/Exynos_OSAL_SkypeHD.h new file mode 100644 index 0000000..8952090 --- /dev/null +++ b/osal/Exynos_OSAL_SkypeHD.h @@ -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 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 + +/* COMMON_ONLY */ +OMX_ERRORTYPE Exynos_OMX_Check_SizeVersion_SkypeHD(OMX_PTR header, OMX_U32 size); + +#ifdef BUILD_ENC +/* ENCODE_ONLY */ +OMX_ERRORTYPE Exynos_H264Enc_GetExtensionIndex_SkypeHD(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, OMX_OUT OMX_INDEXTYPE *pIndexType); +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); +void Change_H264Enc_SkypeHDParam(EXYNOS_OMX_BASECOMPONENT *pExynosComponent, OMX_PTR pDynamicConfigCMD); +#endif + +#ifdef BUILD_DEC +/* DECODE_ONLY */ +OMX_ERRORTYPE Exynos_H264Dec_GetExtensionIndex_SkypeHD(OMX_IN OMX_HANDLETYPE hComponent, + OMX_IN OMX_STRING cParameterName, OMX_OUT OMX_INDEXTYPE *pIndexType); +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/osal/Exynos_OSAL_Thread.c b/osal/Exynos_OSAL_Thread.c new file mode 100644 index 0000000..d92998b --- /dev/null +++ b/osal/Exynos_OSAL_Thread.c @@ -0,0 +1,165 @@ +/* + * + * 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)); + 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_ThreadCancel(OMX_HANDLETYPE threadHandle) +{ + EXYNOS_THREAD_HANDLE_TYPE *thread = (EXYNOS_THREAD_HANDLE_TYPE *)threadHandle; + + if (!thread) + return OMX_ErrorBadParameter; + + /* thread_cancel(thread->pthread); */ + pthread_exit(&thread->pthread); + pthread_join(thread->pthread, NULL); + + 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/osal/Exynos_OSAL_Thread.h b/osal/Exynos_OSAL_Thread.h new file mode 100644 index 0000000..2048cb9 --- /dev/null +++ b/osal/Exynos_OSAL_Thread.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_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_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/osal/NOTICE b/osal/NOTICE new file mode 100644 index 0000000..316b4eb --- /dev/null +++ b/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 + -- 2.20.1